Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

338 lines
10 KiB

  1. // SupTools.cpp : Defines the entry point for the DLL application.
  2. //
  3. #include <windows.h>
  4. #include <stdio.h>
  5. #include <tchar.h>
  6. #include <MsiQuery.h>
  7. #include <psapi.h>
  8. #include "dbgwrap.h"
  9. #define STRSAFE_NO_DEPRECATE
  10. #include "strsafe.h"
  11. #include "objbase.h"
  12. #include "atlbase.h"
  13. //
  14. // CLSID for PCHUpdate
  15. //
  16. const CLSID CLSID_PCHUpdate = { 0x833E4012,0xAFF7,0x4AC3,{ 0xAA,0xC2,0x9F,0x24,0xC1,0x45,0x7B,0xCE } };
  17. //
  18. // dispatch interface entries
  19. //
  20. #define DISPID_HCU_BASE 0x08030000
  21. #define DISPID_HCU_BASE_UPDATE (DISPID_HCU_BASE + 0x0000)
  22. #define DISPID_HCU_BASE_ITEM (DISPID_HCU_BASE + 0x0100)
  23. #define DISPID_HCU_BASE_EVENTS (DISPID_HCU_BASE + 0x0200)
  24. #define DISPID_HCU_LATESTVERSION (DISPID_HCU_BASE_UPDATE + 0x10)
  25. #define DISPID_HCU_CREATEINDEX (DISPID_HCU_BASE_UPDATE + 0x11)
  26. #define DISPID_HCU_UPDATEPKG (DISPID_HCU_BASE_UPDATE + 0x12)
  27. #define DISPID_HCU_REMOVEPKG (DISPID_HCU_BASE_UPDATE + 0x13)
  28. #define DISPID_HCU_REMOVEPKGBYID (DISPID_HCU_BASE_UPDATE + 0x14)
  29. //
  30. // custom macros
  31. //
  32. #define SAFE_RELEASE( pointer ) \
  33. if ( (pointer) != NULL ) \
  34. { \
  35. (pointer)->Release(); \
  36. (pointer) = NULL; \
  37. } \
  38. 1
  39. //
  40. // DLL entry point
  41. //
  42. BOOL APIENTRY DllMain( HANDLE hModule,
  43. DWORD ul_reason_for_call,
  44. LPVOID lpReserved
  45. )
  46. {
  47. return TRUE;
  48. }
  49. // globAL VARIABLES
  50. TCHAR g_tszTitle[1024] = _T("");
  51. ///////////////////////////////////////////////////////////
  52. // IsHSCAppRunningEnum - msi custom action
  53. // Checks if the Help and Support Center app is running
  54. ///////////////////////////////////////////////////////////
  55. BOOL CALLBACK IsHSCAppRunningEnum( HWND hwnd, LPARAM lParam )
  56. {
  57. DWORD dwID;
  58. TCHAR tszTitle[1024] = _T("");
  59. HWND hParent = NULL;
  60. GetWindowThreadProcessId(hwnd, &dwID);
  61. // if this the desired process ID
  62. if(dwID == (DWORD)lParam) {
  63. // get handle to root window
  64. hParent = GetAncestor(hwnd, GA_ROOTOWNER);
  65. if (hParent) {
  66. if ( GetWindowText(hParent, tszTitle, sizeof(tszTitle)) ) {
  67. if SUCCEEDED(StringCchCopy(g_tszTitle, 1024, tszTitle)) {
  68. DEBUGMSG(1, ("\r\nNeed to shutdown app: %s", g_tszTitle));
  69. return FALSE;
  70. }
  71. }
  72. }
  73. }
  74. return TRUE ;
  75. }
  76. ///////////////////////////////////////////////////////////
  77. // IsHSCAppRunning - msi custom action
  78. // Checks if the Help and Support Center app is running
  79. ///////////////////////////////////////////////////////////
  80. UINT __stdcall IsHSCAppRunning(MSIHANDLE hInstall)
  81. {
  82. TCHAR tszHSCAppPath[MAX_PATH + 1];
  83. TCHAR tszHelpDir[] = _T("\\PCHEALTH\\HELPCTR\\Binaries\\");
  84. TCHAR tszProcessName[MAX_PATH+1] = _T("");
  85. TCHAR tszModulePath[MAX_PATH] = _T("");
  86. TCHAR tszHSCApp[] = _T("HelpCtr.exe");
  87. TCHAR tszProperty[] = _T("HSCAPPRUNNING");
  88. TCHAR tszPropTitle[] = _T("HSCAPPTITLE");
  89. DWORD aProcesses[1024], cbNeededTotal, cProcesses;
  90. HMODULE hMod;
  91. DWORD cbNeeded;
  92. HANDLE hProcess = NULL;
  93. HRESULT hr;
  94. unsigned int i;
  95. // Prepare HSCAppPath
  96. if (!(GetWindowsDirectory(tszHSCAppPath, MAX_PATH+1))) { return ERROR_INSTALL_FAILURE; }
  97. hr = StringCchCat(tszHSCAppPath, MAX_PATH, tszHelpDir);
  98. if (FAILED(hr)) { return ERROR_INSTALL_FAILURE; }
  99. hr = StringCchCat(tszHSCAppPath, MAX_PATH, tszHSCApp);
  100. if (FAILED(hr)) { return ERROR_INSTALL_FAILURE; }
  101. // Enumerate all processes
  102. if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeededTotal ) ) {
  103. // return error
  104. return ERROR_INSTALL_FAILURE;
  105. }
  106. // Calculate how many process identifiers were returned.
  107. cProcesses = cbNeededTotal / sizeof(DWORD);
  108. // Iterate through the process list.
  109. for ( i = 0; i < cProcesses; i++ ) {
  110. // Get a handle to the process.
  111. hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i] );
  112. if ( hProcess ) {
  113. // GET MODULE HANDLE
  114. if( EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) {
  115. // Get the process name.
  116. if ( GetModuleBaseName( hProcess, hMod, tszProcessName, sizeof(tszProcessName))) {
  117. // Get process path
  118. if (GetModuleFileNameEx( hProcess, hMod, tszModulePath, sizeof(tszModulePath))) {
  119. // if both process name and path matches
  120. if ( (0 == _tcsicmp(tszProcessName, tszHSCApp)) && (0 == _tcsicmp(tszModulePath, tszHSCAppPath)) ) {
  121. // set msi property and get window title
  122. MsiSetProperty(hInstall, tszProperty, _T("1"));
  123. EnumWindows((WNDENUMPROC)IsHSCAppRunningEnum, (LPARAM)aProcesses[i]);
  124. if ( _tcsicmp(g_tszTitle, _T(""))) {
  125. MsiSetProperty(hInstall, tszPropTitle, g_tszTitle);
  126. } else {
  127. DEBUGMSG(1, ("\r\nDetected HSC running, but failed to obtain window title"));
  128. return ERROR_INSTALL_FAILURE;
  129. }
  130. break;
  131. }
  132. } else { DEBUGMSG(1, ("\r\nGetModuleFileNameEx failed. GetLastError returned %u\n", GetLastError() ));
  133. }
  134. } else { DEBUGMSG(1, ("\r\nGetModuleBaseName failed. GetLastError returned %u\n", GetLastError() ));
  135. }
  136. }else { DEBUGMSG(1, ("\r\nEnumProcessModules failed. GetLastError returned %u\n", GetLastError() ));
  137. }
  138. // done with the handle
  139. CloseHandle(hProcess);
  140. } else { DEBUGMSG(1, ("\r\nOpenProcess failed. GetLastError returned %u\n", GetLastError() ));
  141. }
  142. }
  143. return ERROR_SUCCESS;
  144. }
  145. ///////////////////////////////////////////////////////////
  146. // IsHSCAppRunning - msi custom action
  147. // Checks if the Help and Support Center app is running
  148. ///////////////////////////////////////////////////////////
  149. UINT __stdcall UpdatePackage(MSIHANDLE hInstall)
  150. {
  151. DWORD dwError = 0;
  152. DWORD dwLength = 0;
  153. HRESULT hr = S_OK;
  154. IUnknown* pUnknown = NULL;
  155. IDispatch* pPCHUpdate = NULL;
  156. UINT nResult = ERROR_SUCCESS;
  157. LPTSTR pszCabFileName = NULL;
  158. BOOL bNeedProxySecurity = FALSE;
  159. // method execution specific variables
  160. CComVariant pvars[ 2 ];
  161. DISPPARAMS disp = { pvars, NULL, 2, 0 };
  162. //
  163. // initialize the COM library
  164. hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
  165. if ( FAILED( hr ) )
  166. {
  167. return ERROR_INSTALL_FAILURE;
  168. }
  169. //
  170. // initialize the security of the COM/OLE
  171. //
  172. //////////////////////////////////////////////////////////////////////////////
  173. // *) We don't care which authentication service we use
  174. // *) We want to identify the callers.
  175. // *) For package installation let's use the thread token for outbound calls
  176. //////////////////////////////////////////////////////////////////////////////
  177. hr = CoInitializeSecurity( NULL, -1, NULL, NULL,
  178. RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_DYNAMIC_CLOAKING, NULL );
  179. if ( FAILED( hr ) )
  180. {
  181. //
  182. // since this function will be called by MSI, the calling application would have alredy
  183. // set the security which makes this function to fail -- so, instead of breaking at this
  184. // point, we flag here so that CoSetProxyBlanket will be called
  185. //
  186. bNeedProxySecurity = TRUE;
  187. }
  188. //
  189. // get the interface pointer to the PCHUPDATE interface
  190. hr = CoCreateInstance( CLSID_PCHUpdate, NULL, CLSCTX_ALL, IID_IUnknown, (void **) &pUnknown );
  191. if ( FAILED( hr ) )
  192. {
  193. nResult = ERROR_INSTALL_FAILURE;
  194. goto cleanup;
  195. }
  196. //
  197. // call the CoSetProxyBlanket function -- do this only if needed
  198. if ( bNeedProxySecurity == TRUE )
  199. {
  200. hr = CoSetProxyBlanket( pUnknown,
  201. RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT, COLE_DEFAULT_PRINCIPAL,
  202. RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_DYNAMIC_CLOAKING );
  203. if ( FAILED( hr ) )
  204. {
  205. nResult = ERROR_INSTALL_FAILURE;
  206. goto cleanup;
  207. }
  208. }
  209. //
  210. // get the dispatch interface pointer
  211. hr = pUnknown->QueryInterface(IID_IDispatch, (void **) &pPCHUpdate);
  212. if ( FAILED( hr ) )
  213. {
  214. nResult = ERROR_INSTALL_FAILURE;
  215. goto cleanup;
  216. }
  217. //
  218. // call the CoSetProxyBlanket function -- do this only if needed
  219. if ( bNeedProxySecurity == TRUE )
  220. {
  221. hr = CoSetProxyBlanket( pPCHUpdate,
  222. RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT, COLE_DEFAULT_PRINCIPAL,
  223. RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_DYNAMIC_CLOAKING );
  224. if ( FAILED( hr ) )
  225. {
  226. nResult = ERROR_INSTALL_FAILURE;
  227. goto cleanup;
  228. }
  229. }
  230. //
  231. // default length
  232. dwLength = 255;
  233. get_cabinet_name:
  234. //
  235. // allocate memory to get the cabinet name
  236. pszCabFileName = new TCHAR[ dwLength + 1 ];
  237. if ( pszCabFileName == NULL )
  238. {
  239. nResult = ERROR_INSTALL_FAILURE;
  240. goto cleanup;
  241. }
  242. // ...
  243. ZeroMemory( pszCabFileName, (dwLength + 1) * sizeof( TCHAR ) );
  244. //
  245. // get the appropriate cab file name
  246. dwError = MsiGetProperty( hInstall, _T( "HSCCabinet" ), pszCabFileName, &dwLength );
  247. if ( dwError == ERROR_MORE_DATA && dwLength == 255 )
  248. {
  249. // buffer is not sufficient -- allocate more memory and call again
  250. delete [] pszCabFileName;
  251. pszCabFileName = NULL;
  252. // ...
  253. goto get_cabinet_name;
  254. }
  255. else if ( dwError != ERROR_SUCCESS )
  256. {
  257. nResult = ERROR_INSTALL_FAILURE;
  258. goto cleanup;
  259. }
  260. //
  261. // prepare the input parameters for UpdatePkg method
  262. pvars[ 0 ] = true;
  263. pvars[ 1 ] = pszCabFileName;
  264. //
  265. // execute the function
  266. pPCHUpdate->Invoke( DISPID_HCU_UPDATEPKG, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL );
  267. //
  268. // success
  269. nResult = ERROR_SUCCESS;
  270. //
  271. // cleanup section
  272. //
  273. cleanup:
  274. //
  275. // release the interface pointers
  276. SAFE_RELEASE( pUnknown );
  277. SAFE_RELEASE( pPCHUpdate );
  278. // release memory allocated for cabinet name
  279. if ( pszCabFileName != NULL )
  280. {
  281. delete [] pszCabFileName;
  282. pszCabFileName = NULL;
  283. }
  284. //
  285. // uninitialize the COM library
  286. CoUninitialize();
  287. // return
  288. return nResult;
  289. }