home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sysmgmt / msi / instmsi / initmsi.cpp
C/C++ Source or Header  |  1997-09-17  |  7KB  |  212 lines

  1. // initmsi.cpp: MSI initialisation functions for msispy
  2. #include "initmsi.h"
  3. #include "resource.h"
  4. #include "propshts.h"
  5. #include "stdio.h"
  6.  
  7. // hard-coded component GUIDs and feature Names
  8. TCHAR    g_szEXEComponentCode[MAX_GUID+1]    = TEXT("{5CB2D5F1-19DD-11d1-9A9D-006097C4E489}");
  9. TCHAR    g_szDLLComponentCode[MAX_GUID+1]    = TEXT("{5CB2D5F0-19DD-11d1-9A9D-006097C4E489}");
  10. TCHAR    g_szIntlDLLComponentCode[MAX_GUID+1]= TEXT("{B62B2CE0-1A98-11d1-9A9E-006097C4E489}");
  11. TCHAR    g_szHelpComponentCode[MAX_GUID+1]    = TEXT("{1F7586D0-20B1-11d1-9AB3-006097C4E489}"); 
  12. TCHAR    g_szMyProductCode[MAX_GUID+1]        = TEXT("");        // will be obtained at runtime
  13. TCHAR    g_szDLLFeatureName[]                = TEXT("SystemInterface");
  14. TCHAR    g_szEXEFeatureName[]                = TEXT("UserInterface");
  15. TCHAR    g_szDefaultQualifier[]                = TEXT("0");
  16. LCID    g_lcidCurrentLocale;
  17. TCHAR    g_szHelpFilePath[MAX_PATH+1]        = TEXT("");        
  18.  
  19. extern    MSISPYSTRUCT    vmInfo;
  20.  
  21. // This message is displayed if the (localised) resource DLL could not be loaded. 
  22. // This string will always appear in English regardless of the User/System LCID.
  23.  
  24. #define ERRORMESSAGE_UNABLETOLOADDLL        TEXT("Msispy was unable to load the resource file.\nComponent Code: %s\nError Code: %d")
  25. #define    ERRORCAPTION_UNABLETOLOADDLL        TEXT("Msispy: Fatal Error")
  26.  
  27.  
  28. // -------------------------------------------------------------------------------------------
  29. // FindComponent()
  30. //    Locates and provides the required component calling MsiProvideQualifiedComponent,
  31. //    using the global LCID (g_lcidCurrentLocale) as the qualifier. If that fails, it
  32. //    tries just the primary lang-ID of g_lcidCurrentLocale. If that fails as well,
  33. //    it tries the default qualifier (g_szDefaultQualifier). Finally if this fails as
  34. //    well it returns the error code of this attempt, else it returns ERROR_SUCCESS
  35. // The path to the component is returned in szPath
  36.  
  37. UINT FindComponent(
  38.       LPCTSTR    szComponentCode,        // GUID of the component to Provide
  39.       LPTSTR    szPath,                    //    Buffer for returned path
  40.       DWORD        *pcchPath                //    size of buffer
  41.       ) 
  42. {
  43.     DWORD    cchPathInitial = *pcchPath;
  44.     lstrcpy(szPath, TEXT(""));            // set [out] variable to known value
  45.  
  46.     TCHAR    szQualifier[MAX_PATH+1];
  47.     UINT    iResult;
  48.     for (UINT iCount = 0; 3 > iCount ; iCount++) 
  49.     {
  50.         switch (iCount) 
  51.         {
  52.         case 0:    
  53.             //    Try the full Language ID
  54.             wsprintf(szQualifier, TEXT("%4.4x"), LANGIDFROMLCID(g_lcidCurrentLocale));
  55.             break;
  56.  
  57.         case 1:
  58.             // Full language ID failed, try primary Language ID
  59.             wsprintf(szQualifier, TEXT("%2.2x"), PRIMARYLANGID(LANGIDFROMLCID(g_lcidCurrentLocale)));
  60.             break;
  61.             
  62.         case 2:
  63.             // language IDs failed, try the default qualifier
  64.             lstrcpy(szQualifier, g_szDefaultQualifier);
  65.             break;
  66.         }
  67.  
  68.         *pcchPath = cchPathInitial;
  69.         iResult = MsiProvideQualifiedComponent(szComponentCode, szQualifier, 0, szPath, pcchPath);
  70.  
  71.         switch (iResult) 
  72.         {
  73.             case ERROR_SUCCESS:
  74.             case ERROR_INSTALL_USEREXIT:
  75.             case ERROR_INSTALL_FAILURE:
  76.                 return iResult;
  77.         }
  78.     }
  79.  
  80.     // ProvideQualifiedComponent failed 
  81.     return iResult;
  82. }
  83.  
  84.  
  85. // -------------------------------------------------------------------------------------------
  86. // fInitMSI()
  87. //    Function to fault in resource DLL and initialise MSI related items
  88. //    Returns TRUE if the MSI initialisation succeeded, FALSE if there 
  89. //    was a fatal error.
  90. //    When the function returns, hResourceInstance points to the hInstance 
  91. //    of the resource DLL if the DLL was loaded successfully
  92.  
  93. BOOL fInitMSI(HINSTANCE *hResourceInstance) 
  94. {
  95.  
  96.     // set [out] variable to known value
  97.     *hResourceInstance = 0;
  98.  
  99.     g_lcidCurrentLocale = GetUserDefaultLCID();
  100.     // Get the product-code of the product using this component.
  101.     // The product-code is not hard-coded in because a component may be
  102.     // shared by multiple products.
  103.     MsiGetProductCode(g_szEXEComponentCode, g_szMyProductCode);
  104.  
  105.     TCHAR    szIntlDLLPath[MAX_PATH+1];
  106.     DWORD    cchIntlDLLPath = MAX_PATH+1;
  107.     UINT    iResult;
  108.     
  109.     // Try finding the resource DLL- if unsuccessful, inform user and exit
  110.     if (ERROR_SUCCESS != (iResult = FindComponent(g_szIntlDLLComponentCode, szIntlDLLPath, &cchIntlDLLPath)))
  111.     {
  112.         TCHAR    szErrorMessage[MAX_MESSAGE+1];
  113.         wsprintf(szErrorMessage, ERRORMESSAGE_UNABLETOLOADDLL, g_szIntlDLLComponentCode, iResult);
  114.  
  115.         TCHAR    szErrorCaption[MAX_HEADER+1];
  116.         wsprintf(szErrorCaption, ERRORCAPTION_UNABLETOLOADDLL);
  117.  
  118.         MessageBox(NULL, szErrorMessage, szErrorCaption, MB_ICONSTOP|MB_OK);
  119.         return FALSE;
  120.     }
  121.  
  122.  
  123.     // Load the international DLL
  124.     *hResourceInstance = W32::LoadLibrary(szIntlDLLPath);
  125.  
  126.     
  127.     // Check if the SystemInterface feature is available for use. If not,
  128.     // call SwitchMode to gray out features that depend on it and inform
  129.     // user.
  130.     if (MsiQueryFeatureState(g_szMyProductCode, g_szDLLFeatureName) == INSTALLSTATE_UNKNOWN) 
  131.     {
  132.         // Switch to Degraded Mode [grays out features that depend on SystemInterface feature]
  133.         SwitchMode(MODE_DEGRADED);
  134.  
  135.         TCHAR    szRestrMsg[MAX_MESSAGE+1];
  136.         LoadString(*hResourceInstance, IDS_STARTUPRESTRICTEDMSG, szRestrMsg, MAX_MESSAGE+1);
  137.  
  138.         TCHAR    szRestrCaption[MAX_HEADER+1];
  139.         LoadString(*hResourceInstance, IDS_STARTUPRESTRICTEDCPN, szRestrCaption, MAX_HEADER+1);
  140.  
  141.         // Inform user that Msispy is now in "Restricted Mode"
  142.         MessageBox(NULL, szRestrMsg, szRestrCaption, MB_OK|MB_ICONEXCLAMATION);
  143.     }
  144.     else 
  145.         SwitchMode(MODE_NORMAL);
  146.  
  147.  
  148.     // Prepare to use the UserInterface feature: check its current state and increase usage count.
  149.     INSTALLSTATE iEXEFeatureState = MsiUseFeature(g_szMyProductCode, g_szEXEFeatureName);
  150.  
  151.     // If feature is not currently usable, try fixing it
  152.     switch (iEXEFeatureState) 
  153.     {
  154.     case INSTALLSTATE_DEFAULT:
  155.     case INSTALLSTATE_LOCAL:
  156.     case INSTALLSTATE_SOURCE:
  157.  
  158.         // feature is installed and usable
  159.         return TRUE;
  160.  
  161.     case INSTALLSTATE_ABSENT:
  162.  
  163.         // feature isn't installed, try installing it
  164.         if (MsiConfigureFeature(g_szMyProductCode, g_szEXEFeatureName, INSTALLSTATE_LOCAL) != ERROR_SUCCESS)
  165.             return FALSE;            // installation failed
  166.         break;
  167.  
  168.     default:
  169.  
  170.         // feature is busted- try fixing it
  171.         if (MsiReinstallFeature(g_szMyProductCode, g_szEXEFeatureName, 
  172.             REINSTALLMODE_REPAIR 
  173.             + REINSTALLMODE_FILEEQUALVERSION
  174.             + REINSTALLMODE_MACHINEDATA 
  175.             + REINSTALLMODE_USERDATA
  176.             + REINSTALLMODE_SHORTCUT) != ERROR_SUCCESS)
  177.             return FALSE;            // we couldn't fix it
  178.         break;
  179.     }
  180.  
  181.     return TRUE;
  182. }
  183.  
  184.  
  185. // -------------------------------------------------------------------------------------------
  186. // fHandleHelp()
  187. //  Creates a new process to bring up the help
  188. //    Uses FindComponent to load the appropriate help file (based on g_lcidCurrentLocale)
  189.  
  190. BOOL fHandleHelp(HINSTANCE hResourceInstance) 
  191. {
  192.     DWORD    cchHelpFilePath                = MAX_PATH+1;
  193.     UINT    iResult                        = 0;
  194.  
  195.     if (ERROR_SUCCESS != (iResult = FindComponent(g_szHelpComponentCode, g_szHelpFilePath, &cchHelpFilePath))) 
  196.     {
  197.         // we couldn't find the help file
  198.         TCHAR szErrorMsg[MAX_MESSAGE+1];
  199.         TCHAR szErrorCpn[MAX_HEADER+1];
  200.         LoadString(hResourceInstance, IDS_NOHELPMSG, szErrorMsg, MAX_MESSAGE+1);
  201.         LoadString(hResourceInstance, IDS_NOHELPCPN, szErrorCpn, MAX_HEADER+1);
  202.  
  203.         MessageBox(NULL, szErrorMsg, szErrorCpn, MB_OK|MB_ICONEXCLAMATION);
  204.         return FALSE;
  205.     }
  206.  
  207.     //    MsiUseFeature(g_szMyProductCode, g_szHelpFeatureName);
  208.  
  209.     // Launch WinHelp to handle help
  210.     return WinHelp(vmInfo.hwndParent, g_szHelpFilePath, HELP_FINDER, 0);
  211.  
  212. }