home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 17.ddi / SAMPLES / VERSTAMP / VERSTAMP.C_ / VERSTAMP.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  37.9 KB  |  1,148 lines

  1. //------------------------------------------------------------------------
  2. // File name: verstamp.c                            Creation date: 911204
  3. //
  4. // Abstract:  Sample to demonstrate version information API from VER.DLL
  5. //
  6. // Demonstrates the following functions:
  7. //
  8. //    GetFileVersionInfo      - Returns version information about a file
  9. //    GetFileVersionInfoSize  - Returns the size of a file's version
  10. //                              information
  11. //    GetSystemDirectory      - Returns the Windows system subdirectory
  12. //    GetWindowsDirectory     - Returns the Windows directory
  13. //    VerFindFile             - Determines where to install a file
  14. //    VerInstallFile          - Installs a file using version info
  15. //    VerLanguageName         - Converts a binary language ID into a string
  16. //    VerQueryValue           - Returns version information about a block
  17. //
  18. // Written by Microsoft Product Support Services, Windows Developer Support.
  19. //
  20. // Copyright (c) 1991 Microsoft Corporation. All rights reserved.
  21. //--------------------------------------------------------------------------
  22. #include <windows.h>
  23. #include <commdlg.h>                  // Common dialog header
  24. #include <ver.h>                      // version info header
  25. #include <stdlib.h>                   // for _MAX_PATH
  26. #include "verstamp.h"                 // Header for this program
  27.  
  28. //-------------------------------------------------------------------------
  29. //
  30. // Function:    WinMain()
  31. //
  32. // Purpose:     Main window procedure - initializes window data
  33. //
  34. // Parameters:  hInstance
  35. //              hPrevious
  36. //              lpCmdLine
  37. //              nCmdShow
  38. //
  39. // Return Val:  msg.wParam
  40. //
  41. // Comments:    Used a dialog for the main window.  This is modeled
  42. //              after Petzold's hexcalc program.  The important things
  43. //              to remember are:
  44. //              1) use DLGWINDOWEXTRA in the cbWndExtra member of the
  45. //                 window class
  46. //              2) make sure the class statement in the rc file matches
  47. //                 classname member of the window class structure
  48. //
  49. // Date      Reason
  50. // ----      ------
  51. // 911204    Function created
  52. //
  53. //--------------------------------------------------------------------------
  54. int PASCAL WinMain(HANDLE hInstance,
  55.                    HANDLE hPrevInstance,
  56.                    LPSTR  lpCmdLine,
  57.                    int    nCmdShow)
  58. {
  59.   WNDCLASS  WndClass;                 // window class structure
  60.   HWND      hWnd;                     // window handle
  61.   MSG       msg;                      // message
  62.  
  63.   if (!hPrevInstance)
  64.     {
  65.     WndClass.style          = 0;
  66.     WndClass.lpfnWndProc    = WndProc;
  67.     WndClass.cbClsExtra     = 0;
  68.     WndClass.cbWndExtra     = DLGWINDOWEXTRA;
  69.     WndClass.hInstance      = hInstance;
  70.     WndClass.hIcon          = LoadIcon(hInstance, "VerStampIcon");
  71.     WndClass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  72.     WndClass.hbrBackground  = COLOR_WINDOW+1;
  73.     WndClass.lpszMenuName   = "VerStampMenu";
  74.     WndClass.lpszClassName  = gszAppName;
  75.  
  76.     RegisterClass(&WndClass);
  77.     }
  78.  
  79.   // Use this call to create the window.  Be sure to allocate
  80.   // extra bytes for the window using DLGWINDOWEXTRA and make
  81.   // sure that the class is included in the rc file.
  82.  
  83.   if (!(hWnd = CreateDialog(hInstance, gszAppName, 0, NULL)))
  84.     return FALSE;
  85.  
  86.   ghInst  = hInstance;                // Set global instance handle
  87.  
  88.   ShowWindow(hWnd, nCmdShow);
  89.   while (GetMessage(&msg,NULL,NULL,NULL))
  90.     {
  91.     TranslateMessage(&msg);
  92.     DispatchMessage(&msg);
  93.     }
  94.   return (msg.wParam);
  95. }
  96.  
  97. //------------------------------------------------------------------------
  98. //
  99. //     Function:  WndProc()
  100. //
  101. //      Purpose:  Window procedure for version info sample
  102. //
  103. //   Parameters:  hWnd    - Window handle
  104. //                wMsg    - Message
  105. //                wParam  - Word parameter
  106. //                lParam  - Long parameter
  107. //
  108. // Return Value:  DefWindowProc()
  109. //                NULL
  110. //
  111. //     Comments:
  112. //
  113. // Date      Reason
  114. // ----      ------
  115. // 911204    Function created
  116. //
  117. //-------------------------------------------------------------------------
  118. long FAR PASCAL __export WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
  119. {
  120.   FARPROC lpProcAbout;                // About function ptr
  121.   FARPROC lpProcMoreVerInfo;          // About function ptr
  122.   WORD    wRes;                       // WORD ret value
  123.   DWORD   dwRes;                      // DWORD ret value
  124.  
  125.   switch (wMsg)
  126.     {
  127.     case WM_CREATE:
  128.  
  129.       // Get the files in the windows/system directory.
  130.       // The sample uses this as a default directory to
  131.       // obtain version stamp information.  Could have
  132.       // just as easily used the current directory.  DOS
  133.       // programs would use the GetSystemDir function.
  134.       GetSystemDirectory((LPSTR) gszSrcDir, (BUFLEN - 1));
  135.       break;
  136.  
  137.     case WM_COMMAND:
  138.         switch (wParam)
  139.             {
  140.             case IDM_ABOUT:
  141.           // Do the about dialog box
  142.  
  143.           lpProcAbout = MakeProcInstance(About, ghInst);
  144.           DialogBox(ghInst, "AboutBox", hWnd, lpProcAbout);
  145.           FreeProcInstance(lpProcAbout);
  146.           break;
  147.  
  148.         case IDM_FILEOPEN:
  149.           // Open the file using the common dialog open file
  150.           // and get the version information
  151.  
  152.           gszSrcFile[0] = '\0';       // For GetOpenFileName
  153.  
  154.           // Do the open file dialog to get the source file name
  155.           // and the source directory name.  The file name will
  156.           // only have the file and extension, not the path.
  157.  
  158.           if (MyGetOpenFileName(hWnd, gszSrcDir, gszSrcFile))
  159.  
  160.             // Show the version stamp info in the dialog
  161.  
  162.             if (ShowVerInfo(hWnd, gszSrcDir, gszSrcFile, DLG_SRCFILENAME))
  163.               {
  164.               // Since we have version stamp information, turn
  165.               // on the VerInstall button in the dialog.
  166.  
  167.               EnableWindow(GetDlgItem(hWnd, IDD_VERINSTALL), TRUE);
  168.               EnableWindow(GetDlgItem(hWnd, IDD_MOREINFO),   TRUE);
  169.  
  170.               // Put the focus on the More info... button
  171.               SetFocus(GetDlgItem(hWnd, IDD_MOREINFO));
  172.               }
  173.  
  174.             else
  175.               {
  176.               // Since we don't have version stamp info, be sure to
  177.               // turn off the VerInstall button.
  178.  
  179.               EnableWindow (GetDlgItem(hWnd, IDD_MOREINFO),   FALSE);
  180.               EnableWindow (GetDlgItem(hWnd, IDD_VERINSTALL), FALSE);
  181.               }
  182.  
  183.           break;
  184.  
  185.         case IDD_MOREINFO:
  186.           // Show the dialog that contains the string information
  187.           // about the file
  188.  
  189.           lpProcMoreVerInfo = MakeProcInstance(MoreVerInfo, ghInst);
  190.           DialogBox(ghInst, "MoreVerInfo", hWnd, lpProcMoreVerInfo);
  191.           FreeProcInstance(lpProcMoreVerInfo);
  192.           break;
  193.  
  194.         case IDD_VERINSTALL:
  195.           // Attempt to install the file.  Since we don't want anyone
  196.           // to overwrite a file inadvertently, we take care to proceed
  197.           // with caution.
  198.  
  199.           // Look to see where Windows thinks you should install the file
  200.           wRes = MyVerFindFile(hWnd, gszSrcDir, gszSrcFile, gszDstDir);
  201.  
  202.           // Show whatever information you can for the target file in
  203.           // the destination side of the directory.
  204.  
  205.           ShowVerInfo(hWnd, gszDstDir, gszSrcFile, DLG_DSTFILENAME);
  206.  
  207.           // Show information about the return value off VerFindFile
  208.           // and determine if the user wants to continue.
  209.  
  210.           if (HandleVerFindFileRes(hWnd, wRes, gszDstDir, gszSrcFile))
  211.             {
  212.             // Either the user has said that it is okay to continue
  213.             // or VerFindFile has returned a 0 indicating that there
  214.             // is no problem with proceeding to the call to VerInstall-
  215.             // File.
  216.  
  217.             dwRes = MyVerInstallFile(gszSrcDir, gszSrcFile, gszDstDir);
  218.  
  219.             // If everything went ok - indicated by a zero return
  220.             // value - then this is where you would perform any post
  221.             // processing that needs to be done on the destination
  222.             // file.  For instance, marking it as read only.  In our
  223.             // particular case, we just let the user know that the
  224.             // file was installed.
  225.  
  226.             if (!dwRes)
  227.               PostInstallProcessing(hWnd, gszDstDir, gszSrcFile);
  228.  
  229.             else
  230.               // If everything didn't go okay then we need to
  231.               // deal with it.
  232.  
  233.               HandleVerInstallFileRes(hWnd, dwRes, gszDstDir, gszSrcFile);
  234.             }
  235.  
  236.           // Disable the buttons and clear the dialog
  237.  
  238.           EnableWindow (GetDlgItem(hWnd, IDD_MOREINFO),   FALSE);
  239.           EnableWindow (GetDlgItem(hWnd, IDD_VERINSTALL), FALSE);
  240.           ClearDlgVer  (hWnd, DLG_DSTFILENAME);
  241.           ClearDlgVer  (hWnd, DLG_SRCFILENAME);
  242.  
  243.           break;
  244.  
  245.         case IDM_EXIT:                // All done
  246.           DestroyWindow(hWnd);
  247.           break;
  248.  
  249.         default:
  250.           return (DefWindowProc(hWnd, wMsg, wParam, lParam));
  251.             }
  252.         break;
  253.  
  254.     case WM_DESTROY:
  255.       PostQuitMessage(0);
  256.       break;
  257.  
  258.     case WM_PAINT:
  259.       if (bFirst)                     // Do this on the 1st time through
  260.         {
  261.         // Set windows directory in dialog box.  DOS installation
  262.         // programs would use the GetWindowsDir.
  263.         GetWindowsDirectory((LPSTR) gszWinDir, (BUFLEN - 1));
  264.         SetDlgItemText(hWnd, DLG_WINDIR, gszWinDir);
  265.  
  266.         // Set system subdirectory in dialog box
  267.  
  268.         GetSystemDirectory((LPSTR) gszSysDir, (BUFLEN - 1));
  269.         SetDlgItemText(hWnd, DLG_SYSDIR, gszSysDir);
  270.  
  271.         bFirst = FALSE;               // Only the first paint message
  272.         }                             // !! Drop through to DefWindowProc
  273.  
  274.     default:
  275.       return (DefWindowProc(hWnd, wMsg, wParam, lParam));
  276.     }
  277.  
  278.   return (NULL);
  279. }
  280.  
  281. //------------------------------------------------------------------------
  282. //
  283. //     Function:  About()
  284. //
  285. //      Purpose:  Show the about box for the version info sample
  286. //
  287. //   Parameters:  hDlg    - Handle to the dialog Window
  288. //                wMsg    - Message
  289. //                wParam  - Word parameter
  290. //                lParam  - Long parameter
  291. //
  292. // Return Value:  TRUE
  293. //                FALSE
  294. //
  295. //     Comments:  Standard about box dialog
  296. //
  297. // Date      Reason
  298. // ----      ------
  299. // 911204    Function created
  300. //
  301. //--------------------------------------------------------------------------
  302. BOOL FAR PASCAL __export About(HWND hDlg,      // Window handle for dialog
  303.               unsigned wMsg,      // Dialog message
  304.                       WORD wParam,    // Word parameter
  305.                       LONG lParam)    // Long parameter
  306.  
  307. {
  308.   switch (wMsg)
  309.       {
  310.     case WM_INITDIALOG:               // Initialize dialog
  311.       return (TRUE);
  312.  
  313.     case WM_COMMAND:                  // Look for dialog command message
  314.           switch(wParam)
  315.               {
  316.           case IDOK:                    // User pressed OK button
  317.               case IDCANCEL:                // Dialog's been canceled
  318.                   EndDialog(hDlg, TRUE);
  319.                   return TRUE;
  320.  
  321.               default:
  322.                   break;
  323.             }
  324.           break;
  325.  
  326.       default:
  327.           break;
  328.       }
  329.   return FALSE;                       // Not done yet
  330. }
  331.  
  332.  
  333. //--------------------------------------------------------------------------
  334. //
  335. //     Function:  MyGetOpenFileName
  336. //
  337. //      Purpose:  Fills in the directory and file using the
  338. //                GetOpenFileName API in the common dialog.
  339. //
  340. //   Parameters:  hWnd    - handle to the window
  341. //                szDir   - pointer to the string that will
  342. //                          be filled in with the dir name.
  343. //                          If this is initialized coming into
  344. //                          the function, it will be used as the
  345. //                          default directory.
  346. //                szFile  - pointer to the string that will
  347. //                          be filled with the file name,
  348. //                          including the extension
  349. //
  350. //     Comments:  The filter that this function uses for the call
  351. //                to the open file dialog is initialized to DLL's,
  352. //                .EXE's, and .DRV.
  353. //
  354. // Return Value:  TRUE or FALSE
  355. //
  356. // Date      Reason
  357. // ----      ------
  358. // 911207    Function created
  359. //
  360. //------------------------------------------------------------------------
  361. BOOL MyGetOpenFileName(HWND  hWnd, LPSTR szDir, LPSTR szFile)
  362. {
  363.   OPENFILENAME  ofn;
  364.   char          szofnFile[BUFLEN];
  365.   char          szofnDir[_MAX_PATH];
  366.   char          szFileTitle[BUFLEN];
  367.   char         *szFilter [] = {"EXE's, DLL's, and DRV'S",
  368.                                 "*.exe; *.dll; *.drv", ""};
  369.  
  370.   // Initialize the OPENFILENAME members
  371.   lstrcpy(szofnDir, szDir);           // Use as default
  372.  
  373.   szofnFile[0]           =  '\0';
  374.  
  375.   ofn.lStructSize        = sizeof(OPENFILENAME);
  376.   ofn.hwndOwner          = hWnd;
  377.   ofn.lpstrFilter        = szFilter[0];
  378.   ofn.lpstrCustomFilter  = (LPSTR) NULL;
  379.   ofn.nMaxCustFilter     = 0L;
  380.   ofn.nFilterIndex       = 1L;
  381.   ofn.lpstrFile          = szofnFile;
  382.   ofn.nMaxFile           = sizeof(szofnFile);
  383.   ofn.lpstrFileTitle     = szFileTitle;
  384.   ofn.nMaxFileTitle      = sizeof(szFileTitle);
  385.   ofn.lpstrInitialDir    = szofnDir;
  386.   ofn.lpstrTitle         = gszAppName;
  387.   ofn.Flags              = OFN_SHOWHELP | OFN_PATHMUSTEXIST |
  388.                               OFN_FILEMUSTEXIST;
  389.   ofn.nFileOffset        = 0;
  390.   ofn.nFileExtension     = 0;
  391.   ofn.lpstrDefExt        = (LPSTR) NULL;
  392.  
  393.   // Call GetOpenFilename to fill in the filename and dirname
  394.   if (GetOpenFileName(&ofn))
  395.     {
  396.     // Copy the results into the file
  397.     lstrcpy(szFile, &ofn.lpstrFile[ofn.nFileOffset]);
  398.  
  399.     // Get the dir.  Since the ofn.file has the path and the
  400.     // file we have to truncate the path at the ofn.fileoffset
  401.     // character.
  402.     lstrcpy(szDir, ofn.lpstrFile);
  403.     szDir[ofn.nFileOffset - 1] = '\0';
  404.  
  405.     return TRUE;                      // Success
  406.     }
  407.  
  408.   else
  409.     return FALSE;                     // Failure
  410. }
  411.  
  412.  
  413. //---------------------------------------------------------------------------
  414. //
  415. //     Function:  ShowVerInfo()
  416. //
  417. //      Purpose:  Called after there is a file to get version info on
  418. //
  419. //   Parameters:  hWnd      - handle to the window that owns the dialog
  420. //                szDir     - path
  421. //                szFile    - file name
  422. //                wDlgItem  - the starting dialog item
  423. //
  424. // Return Value:  void
  425. //
  426. //     Comments:
  427. //
  428. // Date      Reason
  429. // ----      ------
  430. // 911207    Function created
  431. //
  432. //-------------------------------------------------------------------------
  433. BOOL ShowVerInfo(HWND hWnd, LPSTR szDir, LPSTR szFile, WORD wDlgItem)
  434. {
  435.   DWORD dwVerInfoSize;
  436.   DWORD dwVerHnd;
  437.   char szFullPath[_MAX_PATH];
  438.  
  439.   // Get file name in dialog control
  440.   SetDlgItemText(hWnd, wDlgItem++,szFile);
  441.  
  442.   // Pick off directory name for dialog control
  443.   SetDlgItemText(hWnd, wDlgItem++, szDir);
  444.  
  445.   // Make full path and file name for call to GetFileVersionInfoSize
  446.   lstrcpy(szFullPath, szDir);
  447.   lstrcat(szFullPath, "\\");
  448.   lstrcat(szFullPath, szFile);
  449.  
  450.   // You must fine the file size first before getting any file info
  451.   dwVerInfoSize =
  452.     GetFileVersionInfoSize(szFullPath, &dwVerHnd);
  453.  
  454.   if (dwVerInfoSize)
  455.     {
  456.     LPSTR   lpstrVffInfo;             // Pointer to block to hold info
  457.     HANDLE  hMem;                     // handle to mem alloc'ed
  458.  
  459.     // Get a block big enough to hold version info
  460.     hMem          = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);
  461.     lpstrVffInfo  = GlobalLock(hMem);
  462.  
  463.     // Get the info and fill in the pertinent dialog components
  464.     if(GetFileVersionInfo(szFullPath, 0L, dwVerInfoSize, lpstrVffInfo))
  465.       FillVerDialog(hWnd, (VS_VERSION FAR *)lpstrVffInfo, wDlgItem);
  466.  
  467.     // Let go of the memory
  468.     GlobalUnlock(hMem);
  469.     GlobalFree(hMem);
  470.     return TRUE;                      // return success
  471.     }
  472.  
  473.   else
  474.     {
  475.     // Clear the dialog if version info
  476.     ClearDlgVer(hWnd, wDlgItem);
  477.     wsprintf(gszUserMsg, "No Version info for %s", (LPSTR) szFullPath);
  478.     MessageBox(hWnd, gszUserMsg, "VerStamp", MB_OK);
  479.     return FALSE;                     // return failure
  480.     }
  481. }
  482.  
  483. //-----------------------------------------------------------------------
  484. //
  485. //     Function:  ClearDlgVer()
  486. //
  487. //      Purpose:  Clears the dialog of version information
  488. //
  489. //   Parameters:  hWnd    - window handle
  490. //                DlgItem - dialog item to start with
  491. //
  492. // Return Value:  void
  493. //
  494. // Date      Reason
  495. // ----      ------
  496. // 911207    Function created
  497. //-----------------------------------------------------------------------
  498. void ClearDlgVer(HWND hWnd, int nDlgItem)
  499. {
  500.   int i;
  501.   int nDlgGroupLimit;
  502.  
  503.   // See if the starting dialog item is in the source column
  504.  
  505.   if (nDlgItem >= DLG_SRCFILENAME && nDlgItem <= DLG_SRCLANGUAGE)
  506.     nDlgGroupLimit = DLG_SRCLANGUAGE;
  507.  
  508.   // Default to the limit being in the destination info column
  509.   else
  510.     nDlgGroupLimit = DLG_DSTLANGUAGE;
  511.  
  512.   // Clear everything from the startin point to the ending point
  513.   for (i=nDlgItem;  i<=nDlgGroupLimit; i++)
  514.     SetDlgItemText(hWnd, i, gszDlgClear);
  515. }
  516.  
  517.  
  518. //---------------------------------------------------------------------------
  519. //
  520. //     Function:  void FillVerDialog
  521. //
  522. //   Parameters:  hWnd      - window handle
  523. //                *pVerInfo - points to ver info block
  524. //                wDlgItem  - starting point to fill dialog items
  525. //
  526. //      Purpose:  fills in the dialog components with the version
  527. //                info.
  528. //
  529. // Return Value:  void
  530. //
  531. // Date      Reason
  532. // ----      ------
  533. // 920108    Function created
  534. //
  535. //--------------------------------------------------------------------------
  536. void FillVerDialog(HWND hWnd, VS_VERSION FAR *pVerInfo, WORD wDlgItem)
  537. {
  538.   DWORD           dwNum;              // to make this more readable
  539.   UINT          wNum;           // for call to VerQueryValue
  540.   LANGANDCP FAR   *lpTrans;           // holds lang and codepage
  541.  
  542.   // fill in the file version
  543.   wsprintf(gszUserMsg,
  544.             "%d.%d.%d.%d",
  545.             HIWORD(pVerInfo->vffInfo.dwFileVersionMS),
  546.             LOWORD(pVerInfo->vffInfo.dwFileVersionMS),
  547.             HIWORD(pVerInfo->vffInfo.dwFileVersionLS),
  548.             LOWORD(pVerInfo->vffInfo.dwFileVersionLS));
  549.   SetDlgItemText(hWnd, wDlgItem, gszUserMsg);
  550.  
  551.   // fill in the product version
  552.   wsprintf(gszUserMsg,
  553.             "%d.%d.%d.%d",
  554.             HIWORD(pVerInfo->vffInfo.dwProductVersionMS),
  555.             LOWORD(pVerInfo->vffInfo.dwProductVersionMS),
  556.             HIWORD(pVerInfo->vffInfo.dwProductVersionLS),
  557.             LOWORD(pVerInfo->vffInfo.dwProductVersionLS));
  558.   SetDlgItemText(hWnd, ++wDlgItem, gszUserMsg);
  559.  
  560.   // File flags are bitwise or'ed so there can be more than one.
  561.   // dwNum is used to make this easier to read
  562.   dwNum = pVerInfo->vffInfo.dwFileFlags;
  563.   wsprintf(gszUserMsg, "%s %s %s %s %s %s %s",
  564.            (LPSTR) (VS_FF_DEBUG         & dwNum ? "Debug"   : ""),
  565.            (LPSTR) (VS_FF_PRERELEASE    & dwNum ? "PreRel"  : ""),
  566.            (LPSTR) (VS_FF_PATCHED       & dwNum ? "Patched" : ""),
  567.            (LPSTR) (VS_FF_PRIVATEBUILD  & dwNum ? "Private" : ""),
  568.            (LPSTR) (VS_FF_INFOINFERRED  & dwNum ? "Info"    : ""),
  569.            (LPSTR) (VS_FF_DEBUG         & dwNum ? "Special" : ""),
  570.            (LPSTR) (0xFFFFFF00L         & dwNum ? "Unknown" : ""));
  571.   SetDlgItemText(hWnd, ++wDlgItem, gszUserMsg);
  572.  
  573.   // OS type - there should be only one of these
  574.   switch (pVerInfo->vffInfo.dwFileOS)
  575.     {
  576.     case VOS_DOS_WINDOWS16:
  577.       lstrcpy(gszUserMsg, "DOS-Win16");
  578.       break;
  579.  
  580.     case VOS_DOS_WINDOWS32:
  581.       lstrcpy(gszUserMsg, "DOS-Win32");
  582.       break;
  583.  
  584.     case VOS_OS216_PM16:
  585.       lstrcpy(gszUserMsg, "OS/2-16 PM-16");
  586.       break;
  587.  
  588.     case VOS_OS232_PM32:
  589.       lstrcpy(gszUserMsg, "OS/2-32 PM-32");
  590.       break;
  591.  
  592.     case VOS_NT_WINDOWS32:
  593.       lstrcpy(gszUserMsg, "NT-Win32");
  594.       break;
  595.  
  596.     case VOS_UNKNOWN:
  597.     default:
  598.       lstrcpy(gszUserMsg, "Unknown");
  599.       break;
  600.     }
  601.   SetDlgItemText(hWnd, ++wDlgItem, gszUserMsg);
  602.  
  603.   // Type of file
  604.   switch (pVerInfo->vffInfo.dwFileType)
  605.     {
  606.     case VFT_APP:
  607.       lstrcpy(gszUserMsg, "App");
  608.       break;
  609.  
  610.     case VFT_DLL:
  611.       lstrcpy(gszUserMsg, "DLL");
  612.       break;
  613.  
  614.     case VFT_DRV:
  615.       lstrcpy(gszUserMsg, "Driver");
  616.       break;
  617.  
  618.     case VFT_FONT:
  619.       lstrcpy(gszUserMsg, "Font");
  620.       break;
  621.  
  622.     case VFT_VXD:
  623.       lstrcpy(gszUserMsg, "VxD");
  624.       break;
  625.  
  626.     case VFT_STATIC_LIB:
  627.       lstrcpy(gszUserMsg, "Lib");
  628.       break;
  629.  
  630.     case VFT_UNKNOWN:
  631.     default:
  632.       lstrcpy(gszUserMsg, "Unknown");
  633.       break;
  634.  
  635.     }
  636.   SetDlgItemText(hWnd, ++wDlgItem, gszUserMsg);
  637.  
  638.   // Depending on the file type we look at a subset of file subtypes
  639.   switch (pVerInfo->vffInfo.dwFileType)
  640.     {
  641.     case VFT_FONT:
  642.       switch (pVerInfo->vffInfo.dwFileSubtype)
  643.         {
  644.         case VFT2_FONT_RASTER:
  645.           lstrcpy(gszUserMsg, "Raster font");
  646.           break;
  647.  
  648.         case VFT2_FONT_VECTOR:
  649.           lstrcpy(gszUserMsg, "Vector font");
  650.           break;
  651.  
  652.         case VFT2_FONT_TRUETYPE:
  653.           lstrcpy(gszUserMsg, "TrueType font");
  654.           break;
  655.         }
  656.       break;
  657.  
  658.     case VFT_DRV:
  659.       switch (pVerInfo->vffInfo.dwFileSubtype)
  660.         {
  661.         case VFT2_DRV_PRINTER:
  662.           lstrcpy(gszUserMsg, "Printer drv");
  663.           break;
  664.  
  665.         case VFT2_DRV_KEYBOARD:
  666.           lstrcpy(gszUserMsg, "Keyboard drv");
  667.           break;
  668.  
  669.         case VFT2_DRV_LANGUAGE:
  670.           lstrcpy(gszUserMsg, "Language drv");
  671.           break;
  672.  
  673.         case VFT2_DRV_DISPLAY:
  674.           lstrcpy(gszUserMsg, "Display drv");
  675.           break;
  676.  
  677.         case VFT2_DRV_MOUSE:
  678.           lstrcpy(gszUserMsg, "Mouse drv");
  679.           break;
  680.  
  681.         case VFT2_DRV_NETWORK:
  682.           lstrcpy(gszUserMsg, "Network drv");
  683.           break;
  684.  
  685.         case VFT2_DRV_SYSTEM:
  686.           lstrcpy(gszUserMsg, "System drv");
  687.           break;
  688.  
  689.         case VFT2_DRV_INSTALLABLE:
  690.           lstrcpy(gszUserMsg, "Installable");
  691.           break;
  692.  
  693.         case VFT2_DRV_SOUND:
  694.           lstrcpy(gszUserMsg, "Sound drv");
  695.           break;
  696.  
  697.         case VFT2_DRV_COMM:
  698.           lstrcpy(gszUserMsg, "Comm drv");
  699.           break;
  700.  
  701.         case VFT2_UNKNOWN:
  702.         default:
  703.           lstrcpy(gszUserMsg, "Unknown");
  704.           break;
  705.         }
  706.       break;
  707.  
  708.       default:
  709.         lstrcpy(gszUserMsg, gszDlgClear);
  710.         break;
  711.     }
  712.   SetDlgItemText(hWnd, ++wDlgItem, gszUserMsg);
  713.  
  714.   // Finally, show the language of the file.  First query the
  715.   // verinfo block for the translation and then pass this onto
  716.   // the VerLanguageName to get the string.  Finally, set the
  717.   // dialog item.
  718.   VerQueryValue   (pVerInfo, (LPCSTR)gszTrans, (void FAR* FAR*)&lpTrans,(UINT FAR*) &wNum);
  719.   VerLanguageName (lpTrans->wLanguage, gszUserMsg, BUFLEN - 1);
  720.   SetDlgItemText  (hWnd, ++wDlgItem, gszUserMsg);
  721. }
  722.  
  723. //---------------------------------------------------------------------------
  724. //
  725. //     Function:  WORD MyVerFindFile
  726. //
  727. //   Parameters:  hWnd      - Window handle
  728. //                szSrcDir  - Source directory
  729. //                szFile    - file name
  730. //                szDstDir  - destination directory where VerFindFile
  731. //                            thinks the file ought to be installed
  732. //
  733. //      Purpose:  A wrapper function for the call to VerFindFile.
  734. //                Since we are not using the current dir in this
  735. //                sample.
  736. //
  737. //     Comments:  VerFindFile was not working correctly for earlier
  738. //                beta versions of 3.1.  It would return the windows
  739. //                system subdirectory in inappropriate cases - that
  740. //                is anytime you would specify a destination dir.
  741. //
  742. // Return Value:  VerFindFile - The return value is a bitmask that
  743. //                indicates the status of the file.
  744. //
  745. // Date      Reason
  746. // ----      ------
  747. // 920108    Function created
  748. //
  749. //---------------------------------------------------------------------------
  750. WORD MyVerFindFile(HWND   hWnd,
  751.                    LPSTR  szSrcDir,
  752.                    LPSTR  szFile,
  753.                    LPSTR  szDstDir)
  754. {
  755.   WORD wCurDirLen = _MAX_PATH;
  756.   WORD wDstDirLen = _MAX_PATH;
  757.  
  758.   // By default, the flag is set to 0.  If you were installing a
  759.   // redistributable component of Window or if your file is to be
  760.   // shared by other apps then you would want to set it to
  761.   // VFFF_ISSHAREDFILE to make sure that it goes into the windows
  762.   // system directory.
  763.  
  764.   return (VerFindFile(0,
  765.                       szFile,
  766.                       gszWinDir,
  767.                       szSrcDir,
  768.                       (LPSTR) gszCurDir,
  769.                       (LPWORD) &wCurDirLen,
  770.                       (LPSTR) szDstDir,
  771.                       (LPWORD) &wDstDirLen));
  772. }
  773.  
  774. //------------------------------------------------------------------------
  775. //
  776. //     Function:  DWORD MyVerInstallFile
  777. //
  778. //   Parameters:  szSrcDir  - source directory
  779. //                szSrcFile - file name
  780. //                szDstDir  - the destination dir
  781. //
  782. //      Purpose:  A wrapper function for the call to VerInstallFile
  783. //
  784. //      Comment:  This is a very simplified call to VerInstallFile.
  785. //                In this sample we do now allow the user to change
  786. //                the destination path.
  787. //
  788. // Return Value:  dwRet which is the return value from VerInstallFile.
  789. //                This is a bit mask which indicates information about
  790. //                the installation attemp.
  791. //
  792. // Date      Reason
  793. // ----      ------
  794. // 920108    Function created
  795. //
  796. //----------------------------------------------------------------------------
  797. DWORD MyVerInstallFile(LPSTR szSrcDir,
  798.                        LPSTR szSrcFile,
  799.                        LPSTR szDstDir)
  800. {
  801.   char  szTmpFile[_MAX_PATH];         // VerInstallFile may create a temp file
  802.   WORD  wTmpFileLen = _MAX_PATH;
  803.   WORD  wVerFlags;
  804.   DWORD dwRet;
  805.  
  806.   // Don't get rid of old file - afterall, this is a sample.  We don't
  807.   // want to do anything too drastic.
  808.  
  809.   wVerFlags = VIFF_DONTDELETEOLD;
  810.  
  811.   // The VerInstallFile function attempts to install a file based
  812.   // on information returned from the VerFindFile function.
  813.   // VerInstallFile uncompresses the file with LZcopy and checks
  814.   // for errors, such as outdated files.
  815.  
  816.   // The source and file names are the same in all cases for this
  817.   // sample.
  818.  
  819.   dwRet = VerInstallFile(wVerFlags,
  820.                          szSrcFile, szSrcFile,
  821.                          szSrcDir,  szDstDir,
  822.                          gszCurDir, szTmpFile, (LPWORD) &wTmpFileLen);
  823.   return dwRet;
  824. }
  825.  
  826. //---------------------------------------------------------------------------
  827. //
  828. //     Function:  MoreVerInfo()
  829. //
  830. //      Purpose:  Shows the user additional version information about
  831. //                the file.
  832. //
  833. //   Parameters:  hDlg    -   handle to the dialog window
  834. //                wMsg    -   dialog message
  835. //                wParam  -   word parameter
  836. //                lParam  -   long parameter
  837. //
  838. // Return Value:  TRUE or FALSE
  839. //
  840. //     Comments:  Uses the globals gszSrcDir and gszSrcFile
  841. //
  842. // Date      Reason
  843. // ----      ------
  844. // 911227    Function created
  845. //
  846. //-------------------------------------------------------------------------
  847. BOOL FAR PASCAL __export MoreVerInfo
  848.                      (HWND hDlg,    // Window handle for dialog
  849.               unsigned wMsg,    // Dialog message
  850.                       WORD wParam,  // Word parameter
  851.                       LONG lParam)  // Long parameter
  852. {
  853.   LPSTR   lpVersion;
  854.   DWORD   dwVerInfoSize;
  855.   DWORD   dwVerHnd;
  856.   WORD    wVersionLen;
  857.   WORD    wRootLen;
  858.   BOOL    bRetCode;
  859.   int     i;
  860.   char    szFullPath[_MAX_PATH];
  861.   char    szResult[BUFLEN];
  862.   char    szGetName[BUFLEN];
  863.  
  864.   switch (wMsg)
  865.       {
  866.     case WM_INITDIALOG:
  867.       // Initialize dialog with the filename
  868.       lstrcpy(szFullPath, gszSrcDir);
  869.       lstrcat(szFullPath, "\\");
  870.       lstrcat(szFullPath, gszSrcFile);
  871.  
  872.       // Get the file version info size
  873.       dwVerInfoSize = GetFileVersionInfoSize(szFullPath, &dwVerHnd);
  874.  
  875.       if (dwVerInfoSize)
  876.         {
  877.         LPSTR   lpstrVffInfo;
  878.         HANDLE  hMem;
  879.  
  880.         // allocate memory to hold the verinfo block
  881.         hMem          = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);
  882.         lpstrVffInfo  = GlobalLock(hMem);
  883.  
  884.         GetFileVersionInfo(szFullPath, dwVerHnd,
  885.            dwVerInfoSize, lpstrVffInfo);
  886.  
  887.         // Do this the American english translation be default.
  888.         // Keep track of the string length for easy updating.
  889.         // 040904E4 represents the language ID and the four
  890.         // least significant digits represent the codepage for
  891.         // which the data is formatted.  The language ID is
  892.         // composed of two parts: the low ten bits represent
  893.         // the major language and the high six bits represent
  894.         // the sub language.
  895.  
  896.         lstrcpy(szGetName, "\\StringFileInfo\\040904E4\\");
  897.         wRootLen = lstrlen(szGetName);
  898.  
  899.         // Get data item from Ver structure.  This uses the
  900.         // gszVerString array to get the various component
  901.         // ver strings.  The contents of the gszVerString are:
  902.  
  903.         // "Illegal string"  "CompanyName"   "FileDescription",
  904.         // "FileVersion"     "InternalName"  "LegalCopyright"
  905.         // "LegalTrademarks" "ProductName"   "ProductVersion
  906.  
  907.         for (i = 1; i <= 8; i++)
  908.           {
  909.           lstrcat(szGetName, gszVerString[i]);
  910.           wVersionLen   = 0;
  911.           lpVersion     = NULL;
  912.  
  913.           // Look for the corresponding string.
  914.           bRetCode      =  VerQueryValue((LPVOID)lpstrVffInfo,
  915.                       (LPSTR)szGetName,
  916.                       (void FAR* FAR*)&lpVersion,
  917.                       (UINT FAR *) &wVersionLen);
  918.  
  919.           if ( bRetCode && wVersionLen && lpVersion)
  920.             {
  921.             lstrcpy(szResult, lpVersion);
  922.             SetDlgItemText(hDlg, DLG_COMPANYNAME + (i - 1) , szResult);
  923.             }
  924.  
  925.           else if (i == 1)
  926.             {
  927.             // This is an attempt to special case the multimedia
  928.             // extensions.  I think they paid attention to the
  929.             // original docs which suggested that they use the
  930.             // 0409 language ID and 0 codepage which indicates
  931.             // 7 bit ASCII.
  932.  
  933.             lstrcpy(szGetName, "\\StringFileInfo\\04090000\\");
  934.             i = 0;                    // be sure to reset the counter
  935.             }
  936.  
  937.           // Be sure to reset to NULL so that we can concat
  938.           szGetName[wRootLen] = NULL;
  939.           }
  940.  
  941.         GlobalUnlock(hMem);
  942.         GlobalFree(hMem);
  943.         }
  944.  
  945.       return (TRUE);
  946.  
  947.     case WM_COMMAND:                  // Look for dialog command message
  948.           switch(wParam)
  949.               {
  950.           case IDOK:                    // User pressed OK button
  951.               case IDCANCEL:                // Dialog's been canceled
  952.                   EndDialog(hDlg, TRUE);
  953.                   return TRUE;
  954.  
  955.               default:
  956.                   break;
  957.             }
  958.           break;
  959.  
  960.       default:
  961.           break;
  962.       }
  963.   return FALSE;                       // Not done yet
  964. }
  965.  
  966. //----------------------------------------------------------------------
  967. //
  968. //     Function:  HandleVerFindFileRes()
  969. //
  970. //      Purpose:  Handles the return from VerFindFile - showing asking the
  971. //                user if they want to continue.
  972. //
  973. //   Parameters:  hWnd    - Handle to the window
  974. //                wRes    - the return value from the call to
  975. //                          VerFindFile
  976. //                szDir   - the directory specification
  977. //                szFile  - the file name
  978. //
  979. // Return Value:  TRUE    - if the user wants to continue
  980. //                FALSE   - if the user doesn't want to continue
  981. //
  982. // Date      Reason
  983. // ----      ------
  984. // 911231    Function created
  985. //
  986. //-------------------------------------------------------------------------
  987. BOOL PASCAL HandleVerFindFileRes(HWND   hWnd,
  988.                                  WORD   wRes,
  989.                                  LPSTR  szDir,
  990.                                  LPSTR  szFile)
  991. {
  992.   char szBuf[BUFLEN];
  993.  
  994.   // If the return value from VerFindFile is 0 then everything
  995.   // is okay and we can proceed to VerInstallFile right away
  996.  
  997.   if (!wRes)
  998.     return TRUE;
  999.  
  1000.   // Make sure that we are starting with no message
  1001.   gszUserMsg[0] = '\0';
  1002.  
  1003.   // Is the file in recommended destination directory?
  1004.   // Beta versions of VerFindFile would always report that
  1005.   // the file wasn't where it was supposed to be.
  1006.  
  1007.   if (VFF_CURNEDEST & wRes)
  1008.     {
  1009.     wsprintf(szBuf,
  1010.              "%s\\%s is not in the recomended destination:",
  1011.               szDir, szFile);
  1012.     lstrcat(gszUserMsg, szBuf);
  1013.     }
  1014.  
  1015.   // Is the file currently in use?
  1016.   if (VFF_FILEINUSE & wRes)
  1017.     {
  1018.     wsprintf(szBuf,
  1019.              " %s\\%s is currently in use:",
  1020.              (LPSTR) gszCurDir, szFile);
  1021.     lstrcat(gszUserMsg, szBuf);
  1022.     }
  1023.  
  1024.   // Are the buffers too small to hold the directory names?
  1025.   if (VFF_BUFFTOOSMALL & wRes)
  1026.     {
  1027.     wsprintf(szBuf,
  1028.              " Buffer size is too small to hold dir strings:");
  1029.     lstrcat(gszUserMsg, szBuf);
  1030.     }
  1031.  
  1032.   // Ask the user if they want to continue.
  1033.  
  1034.   lstrcat(gszUserMsg, " Do you wish to continue?");
  1035.   if (IDYES == MessageBox(hWnd, gszUserMsg, gszAppName, MB_YESNO))
  1036.     return TRUE;
  1037.  
  1038.   // If the user is in doubt about proceeding then we return
  1039.   // FALSE and do not proceed with the call to VerInstallFile
  1040.   return FALSE;
  1041. }
  1042.  
  1043. //---------------------------------------------------------------------------
  1044. //
  1045. //     Function:  PostInstallProcessing()
  1046. //
  1047. //      Purpose:  This procedure performs any post processing that
  1048. //                would need to be done after the call to VerInstallFile.
  1049. //                An example of this would be to mark a file as read
  1050. //                only.  In this particular case, all we are doing is
  1051. //                letting the user know that the install went okay.
  1052. //
  1053. //   Parameters:  hWnd    - a handle to the window
  1054. //                szDir   - the dir path where the file is installed
  1055. //                szFile  - the name of file
  1056. //
  1057. // Return Value:  void
  1058. //
  1059. // Date      Reason
  1060. // ----      ------
  1061. // 920103    Function created
  1062. //
  1063. //--------------------------------------------------------------------------
  1064. void PostInstallProcessing(HWND hWnd, LPSTR szDir, LPSTR szFile)
  1065. {
  1066.   wsprintf(gszUserMsg, "%s\\%s was installed.",
  1067.            szDir, szFile);
  1068.   MessageBox(hWnd, gszUserMsg, gszAppName, MB_OK);
  1069. }
  1070.  
  1071. //-------------------------------------------------------------------------
  1072. //
  1073. //     Function:  void HandleVerInstallFileRes
  1074. //
  1075. //   Parameters:  hWnd    - handle to the windos
  1076. //                dwRes   - return value from VerInstallFile
  1077. //                szDir   - destination dir
  1078. //                szFile  - file name
  1079. //
  1080. //      Purpose:  Handles the return value from the call to
  1081. //                VerInstallFile.
  1082. //
  1083. // Return Value:  void
  1084. //
  1085. // Date      Reason
  1086. // ----      ------
  1087. // 920103    Function created
  1088. //
  1089. //------------------------------------------------------------------------
  1090. void HandleVerInstallFileRes(HWND   hWnd,
  1091.                              DWORD  dwRes,
  1092.                              LPSTR  szDir,
  1093.                              LPSTR  szFile)
  1094. {
  1095.   // VerInstallFile leaves the temporary file in the destination
  1096.   // directory. If all of the error codes are recoverable, the
  1097.   // installation program can override the error by calling
  1098.   // VerInstallFile again with the VIFF_FORCEINSTALL flag. In
  1099.   // this case, lpszSrcFileName should point to the name of the
  1100.   // temporary file.  Then, VerInstallFile deletes the preexisting
  1101.   // file and renames the temporary file to the name specified by
  1102.   // lpszSrcFileName.
  1103.  
  1104.   // If an installation program attempts to force installation
  1105.   // after a non-recoverable error, such as VIF_CANNOTREADSRC,
  1106.   // VerInstallFile will not install the file.
  1107.  
  1108.   if (dwRes & VIF_MISMATCH)
  1109.     {
  1110.     // In the case of a robust installation program you could notify
  1111.     // the user of the mismatch.  You would do this using a dialog showing
  1112.     // all the version stamp information from both files.  You would
  1113.     // let the user decide whether they want to over-ride VerInstallFile
  1114.     // or not.  If they decide to proceed, you would make a second call
  1115.     // to VerInstallFile with the same parameters except with the
  1116.     // VIFF_FORCEINSTALL flag set.
  1117.  
  1118.     wsprintf(gszUserMsg,
  1119.              "Install failed with these flags: %s %s %s %s %s %s",
  1120.               (LPSTR) (VIF_MISMATCH   & dwRes ? "VIF_MISMATCH "    : ""),
  1121.               (LPSTR) (VIF_TEMPFILE   & dwRes ? "VIF_TEMPFILE "    : ""),
  1122.               (LPSTR) (VIF_SRCOLD     & dwRes ? "VIF_SRCOLD "      : ""),
  1123.               (LPSTR) (VIF_DIFFLANG   & dwRes ? "VIF_DIFFLANG "    : ""),
  1124.               (LPSTR) (VIF_DIFFCODEPG & dwRes ? "VIF_DIFFCODEPG "  : ""),
  1125.               (LPSTR) (VIF_DIFFTYPE   & dwRes ? "VIF_DIFFTYPE "    : ""));
  1126.     MessageBox(hWnd, gszUserMsg, gszAppName, MB_OK);
  1127.     return;
  1128.     }
  1129.  
  1130.   else
  1131.     {
  1132.     wsprintf(gszUserMsg,
  1133.              "Install failed with these flags: %s %s %s %s %s %s %s %s %s %s",
  1134.               (LPSTR) (VIF_WRITEPROT        & dwRes ? "VIF_WRITEPROT "    : ""),
  1135.               (LPSTR) (VIF_FILEINUSE        & dwRes ? "VIF_FILEINUSE "    : ""),
  1136.               (LPSTR) (VIF_OUTOFSPACE       & dwRes ? "VIF_OUTOFSPACE "      : ""),
  1137.               (LPSTR) (VIF_ACCESSVIOLATION  & dwRes ? "VIF_ACCESSVIOLATION "    : ""),
  1138.               (LPSTR) (VIF_SHARINGVIOLATION & dwRes ? "VIF_SHARINGVIOLATION "  : ""),
  1139.               (LPSTR) (VIF_CANNOTCREATE     & dwRes ? "VIF_CANNOTCREATE "  : ""),
  1140.               (LPSTR) (VIF_OUTOFMEMORY      & dwRes ? "VIF_OUTOFMEMORY "  : ""),
  1141.               (LPSTR) (VIF_CANNOTREADSRC    & dwRes ? "VIF_CANNOTREADSRC "  : ""),
  1142.               (LPSTR) (VIF_CANNOTREADDST    & dwRes ? "VIF_CANNOTREADDST "  : ""),
  1143.               (LPSTR) (VIF_BUFFTOOSMALL     & dwRes ? "VIF_BUFFTOOSMALL "  : ""));
  1144.     MessageBox(hWnd, gszUserMsg, gszAppName, MB_OK);
  1145.     }
  1146.   return ;
  1147. }
  1148.