|
|
// SupTools.cpp : Defines the entry point for the DLL application.
//
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <MsiQuery.h>
#include <psapi.h>
#include "dbgwrap.h"
#define STRSAFE_NO_DEPRECATE
#include "strsafe.h"
#include "objbase.h"
#include "atlbase.h"
//
// CLSID for PCHUpdate
//
const CLSID CLSID_PCHUpdate = { 0x833E4012,0xAFF7,0x4AC3,{ 0xAA,0xC2,0x9F,0x24,0xC1,0x45,0x7B,0xCE } };
//
// dispatch interface entries
//
#define DISPID_HCU_BASE 0x08030000
#define DISPID_HCU_BASE_UPDATE (DISPID_HCU_BASE + 0x0000)
#define DISPID_HCU_BASE_ITEM (DISPID_HCU_BASE + 0x0100)
#define DISPID_HCU_BASE_EVENTS (DISPID_HCU_BASE + 0x0200)
#define DISPID_HCU_LATESTVERSION (DISPID_HCU_BASE_UPDATE + 0x10)
#define DISPID_HCU_CREATEINDEX (DISPID_HCU_BASE_UPDATE + 0x11)
#define DISPID_HCU_UPDATEPKG (DISPID_HCU_BASE_UPDATE + 0x12)
#define DISPID_HCU_REMOVEPKG (DISPID_HCU_BASE_UPDATE + 0x13)
#define DISPID_HCU_REMOVEPKGBYID (DISPID_HCU_BASE_UPDATE + 0x14)
//
// custom macros
//
#define SAFE_RELEASE( pointer ) \
if ( (pointer) != NULL ) \ { \ (pointer)->Release(); \ (pointer) = NULL; \ } \ 1
//
// DLL entry point
//
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { return TRUE; }
// globAL VARIABLES
TCHAR g_tszTitle[1024] = _T("");
///////////////////////////////////////////////////////////
// IsHSCAppRunningEnum - msi custom action
// Checks if the Help and Support Center app is running
///////////////////////////////////////////////////////////
BOOL CALLBACK IsHSCAppRunningEnum( HWND hwnd, LPARAM lParam ) { DWORD dwID; TCHAR tszTitle[1024] = _T(""); HWND hParent = NULL; GetWindowThreadProcessId(hwnd, &dwID); // if this the desired process ID
if(dwID == (DWORD)lParam) { // get handle to root window
hParent = GetAncestor(hwnd, GA_ROOTOWNER); if (hParent) { if ( GetWindowText(hParent, tszTitle, sizeof(tszTitle)) ) { if SUCCEEDED(StringCchCopy(g_tszTitle, 1024, tszTitle)) { DEBUGMSG(1, ("\r\nNeed to shutdown app: %s", g_tszTitle)); return FALSE; } } } }
return TRUE ; }
///////////////////////////////////////////////////////////
// IsHSCAppRunning - msi custom action
// Checks if the Help and Support Center app is running
///////////////////////////////////////////////////////////
UINT __stdcall IsHSCAppRunning(MSIHANDLE hInstall) { TCHAR tszHSCAppPath[MAX_PATH + 1]; TCHAR tszHelpDir[] = _T("\\PCHEALTH\\HELPCTR\\Binaries\\"); TCHAR tszProcessName[MAX_PATH+1] = _T(""); TCHAR tszModulePath[MAX_PATH] = _T(""); TCHAR tszHSCApp[] = _T("HelpCtr.exe"); TCHAR tszProperty[] = _T("HSCAPPRUNNING"); TCHAR tszPropTitle[] = _T("HSCAPPTITLE"); DWORD aProcesses[1024], cbNeededTotal, cProcesses; HMODULE hMod; DWORD cbNeeded; HANDLE hProcess = NULL; HRESULT hr; unsigned int i; // Prepare HSCAppPath
if (!(GetWindowsDirectory(tszHSCAppPath, MAX_PATH+1))) { return ERROR_INSTALL_FAILURE; } hr = StringCchCat(tszHSCAppPath, MAX_PATH, tszHelpDir); if (FAILED(hr)) { return ERROR_INSTALL_FAILURE; } hr = StringCchCat(tszHSCAppPath, MAX_PATH, tszHSCApp); if (FAILED(hr)) { return ERROR_INSTALL_FAILURE; } // Enumerate all processes
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeededTotal ) ) { // return error
return ERROR_INSTALL_FAILURE; }
// Calculate how many process identifiers were returned.
cProcesses = cbNeededTotal / sizeof(DWORD); // Iterate through the process list.
for ( i = 0; i < cProcesses; i++ ) { // Get a handle to the process.
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i] ); if ( hProcess ) { // GET MODULE HANDLE
if( EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) { // Get the process name.
if ( GetModuleBaseName( hProcess, hMod, tszProcessName, sizeof(tszProcessName))) { // Get process path
if (GetModuleFileNameEx( hProcess, hMod, tszModulePath, sizeof(tszModulePath))) { // if both process name and path matches
if ( (0 == _tcsicmp(tszProcessName, tszHSCApp)) && (0 == _tcsicmp(tszModulePath, tszHSCAppPath)) ) { // set msi property and get window title
MsiSetProperty(hInstall, tszProperty, _T("1")); EnumWindows((WNDENUMPROC)IsHSCAppRunningEnum, (LPARAM)aProcesses[i]); if ( _tcsicmp(g_tszTitle, _T(""))) { MsiSetProperty(hInstall, tszPropTitle, g_tszTitle); } else { DEBUGMSG(1, ("\r\nDetected HSC running, but failed to obtain window title")); return ERROR_INSTALL_FAILURE; } break; } } else { DEBUGMSG(1, ("\r\nGetModuleFileNameEx failed. GetLastError returned %u\n", GetLastError() )); } } else { DEBUGMSG(1, ("\r\nGetModuleBaseName failed. GetLastError returned %u\n", GetLastError() )); } }else { DEBUGMSG(1, ("\r\nEnumProcessModules failed. GetLastError returned %u\n", GetLastError() )); } // done with the handle
CloseHandle(hProcess); } else { DEBUGMSG(1, ("\r\nOpenProcess failed. GetLastError returned %u\n", GetLastError() )); } } return ERROR_SUCCESS; }
///////////////////////////////////////////////////////////
// IsHSCAppRunning - msi custom action
// Checks if the Help and Support Center app is running
///////////////////////////////////////////////////////////
UINT __stdcall UpdatePackage(MSIHANDLE hInstall) { DWORD dwError = 0; DWORD dwLength = 0; HRESULT hr = S_OK; IUnknown* pUnknown = NULL; IDispatch* pPCHUpdate = NULL; UINT nResult = ERROR_SUCCESS; LPTSTR pszCabFileName = NULL; BOOL bNeedProxySecurity = FALSE;
// method execution specific variables
CComVariant pvars[ 2 ]; DISPPARAMS disp = { pvars, NULL, 2, 0 };
//
// initialize the COM library
hr = CoInitializeEx( NULL, COINIT_MULTITHREADED ); if ( FAILED( hr ) ) { return ERROR_INSTALL_FAILURE; }
//
// initialize the security of the COM/OLE
//
//////////////////////////////////////////////////////////////////////////////
// *) We don't care which authentication service we use
// *) We want to identify the callers.
// *) For package installation let's use the thread token for outbound calls
//////////////////////////////////////////////////////////////////////////////
hr = CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_DYNAMIC_CLOAKING, NULL ); if ( FAILED( hr ) ) { //
// since this function will be called by MSI, the calling application would have alredy
// set the security which makes this function to fail -- so, instead of breaking at this
// point, we flag here so that CoSetProxyBlanket will be called
//
bNeedProxySecurity = TRUE; }
//
// get the interface pointer to the PCHUPDATE interface
hr = CoCreateInstance( CLSID_PCHUpdate, NULL, CLSCTX_ALL, IID_IUnknown, (void **) &pUnknown ); if ( FAILED( hr ) ) { nResult = ERROR_INSTALL_FAILURE; goto cleanup; }
//
// call the CoSetProxyBlanket function -- do this only if needed
if ( bNeedProxySecurity == TRUE ) { hr = CoSetProxyBlanket( pUnknown, RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT, COLE_DEFAULT_PRINCIPAL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_DYNAMIC_CLOAKING ); if ( FAILED( hr ) ) { nResult = ERROR_INSTALL_FAILURE; goto cleanup; } }
//
// get the dispatch interface pointer
hr = pUnknown->QueryInterface(IID_IDispatch, (void **) &pPCHUpdate); if ( FAILED( hr ) ) { nResult = ERROR_INSTALL_FAILURE; goto cleanup; }
//
// call the CoSetProxyBlanket function -- do this only if needed
if ( bNeedProxySecurity == TRUE ) { hr = CoSetProxyBlanket( pPCHUpdate, RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT, COLE_DEFAULT_PRINCIPAL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_DYNAMIC_CLOAKING ); if ( FAILED( hr ) ) { nResult = ERROR_INSTALL_FAILURE; goto cleanup; } }
//
// default length
dwLength = 255;
get_cabinet_name: //
// allocate memory to get the cabinet name
pszCabFileName = new TCHAR[ dwLength + 1 ]; if ( pszCabFileName == NULL ) { nResult = ERROR_INSTALL_FAILURE; goto cleanup; }
// ...
ZeroMemory( pszCabFileName, (dwLength + 1) * sizeof( TCHAR ) );
//
// get the appropriate cab file name
dwError = MsiGetProperty( hInstall, _T( "HSCCabinet" ), pszCabFileName, &dwLength ); if ( dwError == ERROR_MORE_DATA && dwLength == 255 ) { // buffer is not sufficient -- allocate more memory and call again
delete [] pszCabFileName; pszCabFileName = NULL;
// ...
goto get_cabinet_name; } else if ( dwError != ERROR_SUCCESS ) { nResult = ERROR_INSTALL_FAILURE; goto cleanup; }
//
// prepare the input parameters for UpdatePkg method
pvars[ 0 ] = true; pvars[ 1 ] = pszCabFileName;
//
// execute the function
pPCHUpdate->Invoke( DISPID_HCU_UPDATEPKG, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL );
//
// success
nResult = ERROR_SUCCESS;
//
// cleanup section
//
cleanup:
//
// release the interface pointers
SAFE_RELEASE( pUnknown ); SAFE_RELEASE( pPCHUpdate );
// release memory allocated for cabinet name
if ( pszCabFileName != NULL ) { delete [] pszCabFileName; pszCabFileName = NULL; }
//
// uninitialize the COM library
CoUninitialize();
// return
return nResult; }
|