INITMSI.CPP

// initmsi.cpp: MSI initialisation functions for msispy 
#include "initmsi.h"
#include "resource.h"
#include "propshts.h"
#include "stdio.h"

// hard-coded component GUIDs and feature Names
TCHARg_szEXEComponentCode[MAX_GUID+1]= TEXT("{5CB2D5F1-19DD-11d1-9A9D-006097C4E489}");
TCHARg_szDLLComponentCode[MAX_GUID+1]= TEXT("{5CB2D5F0-19DD-11d1-9A9D-006097C4E489}");
TCHARg_szIntlDLLComponentCode[MAX_GUID+1]= TEXT("{B62B2CE0-1A98-11d1-9A9E-006097C4E489}");
TCHARg_szHelpComponentCode[MAX_GUID+1]= TEXT("{1F7586D0-20B1-11d1-9AB3-006097C4E489}");
TCHARg_szMyProductCode[MAX_GUID+1]= TEXT("");// will be obtained at runtime
TCHARg_szDLLFeatureName[]= TEXT("SystemInterface");
TCHARg_szEXEFeatureName[]= TEXT("UserInterface");
TCHARg_szDefaultQualifier[]= TEXT("0");
LCIDg_lcidCurrentLocale;
TCHARg_szHelpFilePath[MAX_PATH+1]= TEXT("");

externMSISPYSTRUCTvmInfo;

// This message is displayed if the (localised) resource DLL could not be loaded.
// This string will always appear in English regardless of the User/System LCID.

#define ERRORMESSAGE_UNABLETOLOADDLLTEXT("Msispy was unable to load the resource file.\nComponent Code: %s\nError Code: %d")
#defineERRORCAPTION_UNABLETOLOADDLLTEXT("Msispy: Fatal Error")


// -------------------------------------------------------------------------------------------
// FindComponent()
//Locates and provides the required component calling MsiProvideQualifiedComponent,
//using the global LCID (g_lcidCurrentLocale) as the qualifier. If that fails, it
//tries just the primary lang-ID of g_lcidCurrentLocale. If that fails as well,
//it tries the default qualifier (g_szDefaultQualifier). Finally if this fails as
//well it returns the error code of this attempt, else it returns ERROR_SUCCESS
// The path to the component is returned in szPath

UINT FindComponent(
LPCTSTRszComponentCode,// GUID of the component to Provide
LPTSTRszPath,//Buffer for returned path
DWORD*pcchPath//size of buffer
)
{
DWORDcchPathInitial = *pcchPath;
lstrcpy(szPath, TEXT(""));// set [out] variable to known value

TCHARszQualifier[MAX_PATH+1];
UINTiResult;
for (UINT iCount = 0; 3 > iCount ; iCount++)
{
switch (iCount)
{
case 0:
//Try the full Language ID
wsprintf(szQualifier, TEXT("%4.4x"), LANGIDFROMLCID(g_lcidCurrentLocale));
break;

case 1:
// Full language ID failed, try primary Language ID
wsprintf(szQualifier, TEXT("%2.2x"), PRIMARYLANGID(LANGIDFROMLCID(g_lcidCurrentLocale)));
break;

case 2:
// language IDs failed, try the default qualifier
lstrcpy(szQualifier, g_szDefaultQualifier);
break;
}

*pcchPath = cchPathInitial;
iResult = MsiProvideQualifiedComponent(szComponentCode, szQualifier, 0, szPath, pcchPath);

switch (iResult)
{
case ERROR_SUCCESS:
case ERROR_INSTALL_USEREXIT:
case ERROR_INSTALL_FAILURE:
return iResult;
}
}

// ProvideQualifiedComponent failed
return iResult;
}


// -------------------------------------------------------------------------------------------
// fInitMSI()
//Function to fault in resource DLL and initialise MSI related items
//Returns TRUE if the MSI initialisation succeeded, FALSE if there
//was a fatal error.
//When the function returns, hResourceInstance points to the hInstance
//of the resource DLL if the DLL was loaded successfully

BOOL fInitMSI(HINSTANCE *hResourceInstance)
{

// set [out] variable to known value
*hResourceInstance = 0;

g_lcidCurrentLocale = GetUserDefaultLCID();
// Get the product-code of the product using this component.
// The product-code is not hard-coded in because a component may be
// shared by multiple products.
MsiGetProductCode(g_szEXEComponentCode, g_szMyProductCode);

TCHARszIntlDLLPath[MAX_PATH+1];
DWORDcchIntlDLLPath = MAX_PATH+1;
UINTiResult;

// Try finding the resource DLL- if unsuccessful, inform user and exit
if (ERROR_SUCCESS != (iResult = FindComponent(g_szIntlDLLComponentCode, szIntlDLLPath, &cchIntlDLLPath)))
{
TCHARszErrorMessage[MAX_MESSAGE+1];
wsprintf(szErrorMessage, ERRORMESSAGE_UNABLETOLOADDLL, g_szIntlDLLComponentCode, iResult);

TCHARszErrorCaption[MAX_HEADER+1];
wsprintf(szErrorCaption, ERRORCAPTION_UNABLETOLOADDLL);

MessageBox(NULL, szErrorMessage, szErrorCaption, MB_ICONSTOP|MB_OK);
return FALSE;
}


// Load the international DLL
*hResourceInstance = W32::LoadLibrary(szIntlDLLPath);


// Check if the SystemInterface feature is available for use. If not,
// call SwitchMode to gray out features that depend on it and inform
// user.
if (MsiQueryFeatureState(g_szMyProductCode, g_szDLLFeatureName) == INSTALLSTATE_UNKNOWN)
{
// Switch to Degraded Mode [grays out features that depend on SystemInterface feature]
SwitchMode(MODE_DEGRADED);

TCHARszRestrMsg[MAX_MESSAGE+1];
LoadString(*hResourceInstance, IDS_STARTUPRESTRICTEDMSG, szRestrMsg, MAX_MESSAGE+1);

TCHARszRestrCaption[MAX_HEADER+1];
LoadString(*hResourceInstance, IDS_STARTUPRESTRICTEDCPN, szRestrCaption, MAX_HEADER+1);

// Inform user that Msispy is now in "Restricted Mode"
MessageBox(NULL, szRestrMsg, szRestrCaption, MB_OK|MB_ICONEXCLAMATION);
}
else
SwitchMode(MODE_NORMAL);


// Prepare to use the UserInterface feature: check its current state and increase usage count.
INSTALLSTATE iEXEFeatureState = MsiUseFeature(g_szMyProductCode, g_szEXEFeatureName);

// If feature is not currently usable, try fixing it
switch (iEXEFeatureState)
{
case INSTALLSTATE_DEFAULT:
case INSTALLSTATE_LOCAL:
case INSTALLSTATE_SOURCE:

// feature is installed and usable
return TRUE;

case INSTALLSTATE_ABSENT:

// feature isn't installed, try installing it
if (MsiConfigureFeature(g_szMyProductCode, g_szEXEFeatureName, INSTALLSTATE_LOCAL) != ERROR_SUCCESS)
return FALSE;// installation failed
break;

default:

// feature is busted- try fixing it
if (MsiReinstallFeature(g_szMyProductCode, g_szEXEFeatureName,
REINSTALLMODE_REPAIR
+ REINSTALLMODE_FILEEQUALVERSION
+ REINSTALLMODE_MACHINEDATA
+ REINSTALLMODE_USERDATA
+ REINSTALLMODE_SHORTCUT) != ERROR_SUCCESS)
return FALSE;// we couldn't fix it
break;
}

return TRUE;
}


// -------------------------------------------------------------------------------------------
// fHandleHelp()
// Creates a new process to bring up the help
//Uses FindComponent to load the appropriate help file (based on g_lcidCurrentLocale)

BOOL fHandleHelp(HINSTANCE hResourceInstance)
{
DWORDcchHelpFilePath= MAX_PATH+1;
UINTiResult= 0;

if (ERROR_SUCCESS != (iResult = FindComponent(g_szHelpComponentCode, g_szHelpFilePath, &cchHelpFilePath)))
{
// we couldn't find the help file
TCHAR szErrorMsg[MAX_MESSAGE+1];
TCHAR szErrorCpn[MAX_HEADER+1];
LoadString(hResourceInstance, IDS_NOHELPMSG, szErrorMsg, MAX_MESSAGE+1);
LoadString(hResourceInstance, IDS_NOHELPCPN, szErrorCpn, MAX_HEADER+1);

MessageBox(NULL, szErrorMsg, szErrorCpn, MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

//MsiUseFeature(g_szMyProductCode, g_szHelpFeatureName);

// Launch WinHelp to handle help
return WinHelp(vmInfo.hwndParent, g_szHelpFilePath, HELP_FINDER, 0);

}