Source code of Windows XP (NT5)
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.

435 lines
11 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. AOLFindBundledInstaller_Shim.cpp
  5. Abstract:
  6. This shim is to provide a way to verify existance of
  7. America Online bundled in OEM machines when user runs older
  8. version of AOL/CS program (waol.exe or wcs2000.exe) or setup.
  9. If it exists, it will provide Apphelp dialog to tell user that
  10. there is newer America Online installer available.
  11. If user chose "Run this program", shim will launch the bundled installer.
  12. If user chose "Cancel", then shim will continue with current process.
  13. Apphelp dialog only get displayed if LocateInstaller function says to do so.
  14. History:
  15. 04/30/2001 markder Created
  16. 05/16/2001 andyseti Implemented LocateInstaller and ApphelpShowDialog.
  17. --*/
  18. #include "precomp.h"
  19. #include "LegalStr.h"
  20. #include <Softpub.h>
  21. #include <WinCrypt.h>
  22. #include <WinTrust.h>
  23. #include "AOLFindBundledInstaller_AOLCode.h"
  24. IMPLEMENT_SHIM_BEGIN(AOLFindBundledInstaller)
  25. #include "ShimHookMacro.h"
  26. #include "shimdb.h"
  27. APIHOOK_ENUM_BEGIN
  28. APIHOOK_ENUM_ENTRY(GetCommandLineA)
  29. APIHOOK_ENUM_ENTRY(GetStartupInfoA)
  30. APIHOOK_ENUM_ENTRY(GetModuleFileNameA)
  31. APIHOOK_ENUM_ENTRY(CreateWindowExA)
  32. APIHOOK_ENUM_END
  33. #define MAX_PARAM 4
  34. BOOL g_bDoneIt = FALSE;
  35. CString g_csHTMLHelpID_BundledFound;
  36. CString g_csHTMLHelpID_Incompatible;
  37. DWORD g_dwHTMLHelpID_BundledFound = 0;
  38. DWORD g_dwHTMLHelpID_Incompatible = 0;
  39. CString g_csAppName;
  40. CString g_csGUID;
  41. //
  42. // from apphelp\apphelp.h
  43. //
  44. #define APPTYPE_TYPE_MASK 0x000000FF
  45. #define APPTYPE_INC_NOBLOCK 0x00000001
  46. #define APPTYPE_INC_HARDBLOCK 0x00000002
  47. #define APPTYPE_MINORPROBLEM 0x00000003
  48. #define APPTYPE_REINSTALL 0x00000004
  49. #define APPTYPE_VERSIONSUB 0x00000005
  50. #define APPTYPE_SHIM 0x00000006
  51. #define APPTYPE_NONE 0x00000000
  52. enum ShimAppHelpSeverityType
  53. {
  54. APPHELP_MINORPROBLEM = APPTYPE_MINORPROBLEM,
  55. APPHELP_HARDBLOCK = APPTYPE_INC_HARDBLOCK,
  56. APPHELP_NOBLOCK = APPTYPE_INC_NOBLOCK,
  57. APPHELP_VERSIONSUB = APPTYPE_VERSIONSUB,
  58. APPHELP_SHIM = APPTYPE_SHIM,
  59. APPHELP_REINSTALL = APPTYPE_REINSTALL,
  60. APPHELP_NONE = APPTYPE_NONE
  61. };
  62. #define APPHELP_DIALOG_FAILED ((DWORD)-1)
  63. // from sdbapi\shimdb.w
  64. /*
  65. typedef struct _APPHELP_INFO {
  66. //
  67. // html help id mode
  68. //
  69. DWORD dwHtmlHelpID; // html help id
  70. DWORD dwSeverity; // must have
  71. LPCTSTR lpszAppName;
  72. GUID guidID; // entry guid
  73. //
  74. // Conventional mode
  75. //
  76. TAGID tiExe; // the TAGID of the exe entry within the DB
  77. GUID guidDB; // the guid of the DB that has the EXE entry
  78. BOOL bOfflineContent;
  79. BOOL bUseHTMLHelp;
  80. LPCTSTR lpszChmFile;
  81. LPCTSTR lpszDetailsFile;
  82. } APPHELP_INFO, *PAPPHELP_INFO;
  83. */
  84. typedef BOOL (*_pfn_ApphelpShowDialog)(
  85. IN PAPPHELP_INFO pAHInfo, // the info necessary to find the apphelp data
  86. IN PHANDLE phProcess // [optional] returns the process handle of
  87. // the process displaying the apphelp.
  88. // When the process completes, the return value
  89. // (from GetExitCodeProcess()) will be zero
  90. // if the app should not run, or non-zero
  91. // if it should run.
  92. );
  93. /*++
  94. Parse the command line.
  95. The format of the command line is:
  96. MODE:AOL|CS;APPNAME:xxxxxx;HTMLHELPID:99999;GUID:xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx
  97. --*/
  98. BOOL
  99. ParseCommandLine(
  100. LPCSTR lpCommandLine
  101. )
  102. {
  103. int iTotalParam = 0;
  104. CSTRING_TRY
  105. {
  106. CStringToken csTok(lpCommandLine, L" ;");
  107. CString token;
  108. while (csTok.GetToken(token))
  109. {
  110. CStringToken csSingleTok(token, L":");
  111. CString csParam;
  112. CString csValue;
  113. csSingleTok.GetToken(csParam);
  114. csSingleTok.GetToken(csValue);
  115. if (csParam.CompareNoCase(L"APPNAME") == 0)
  116. {
  117. g_csAppName = csValue;
  118. ++iTotalParam;
  119. }
  120. if (csParam.CompareNoCase(L"HTMLHELPID_BUNDLED") == 0)
  121. {
  122. g_csHTMLHelpID_BundledFound = csValue;
  123. g_dwHTMLHelpID_BundledFound = _wtol(csValue.Get());
  124. ++iTotalParam;
  125. }
  126. if (csParam.CompareNoCase(L"HTMLHELPID_INCOMPAT") == 0)
  127. {
  128. g_csHTMLHelpID_Incompatible = csValue;
  129. g_dwHTMLHelpID_Incompatible = _wtol(csValue.Get());
  130. ++iTotalParam;
  131. }
  132. if (csParam.CompareNoCase(L"GUID") == 0)
  133. {
  134. g_csGUID = csValue;
  135. ++iTotalParam;
  136. }
  137. }
  138. }
  139. CSTRING_CATCH
  140. {
  141. DPF("FindAOL", eDbgLevelInfo, "Error in CString.Exiting\n");
  142. return FALSE;
  143. }
  144. if (iTotalParam < MAX_PARAM)
  145. {
  146. DPF("FindAOL", eDbgLevelInfo, "Total Parameter = %d is less than = %d\n",iTotalParam, MAX_PARAM);
  147. return FALSE;
  148. }
  149. //
  150. // Dump results of command line parse
  151. //
  152. DPF("FindAOL", eDbgLevelInfo, "===================================\n");
  153. DPF("FindAOL", eDbgLevelInfo, " FindAOL \n");
  154. DPF("FindAOL", eDbgLevelInfo, "===================================\n");
  155. DPF("FindAOL", eDbgLevelInfo, "COMMAND_LINE(%s)", lpCommandLine);
  156. DPF("FindAOL", eDbgLevelInfo, "-----------------------------------\n");
  157. DPF("FindAOL", eDbgLevelInfo, "APPNAME = %S\n", g_csAppName);
  158. DPF("FindAOL", eDbgLevelInfo, "HTMLHELPID_BUNDLED = %S\n", g_csHTMLHelpID_BundledFound);
  159. DPF("FindAOL", eDbgLevelInfo, "HTMLHELPID_INCOMPAT = %S\n", g_csHTMLHelpID_Incompatible);
  160. DPF("FindAOL", eDbgLevelInfo, "GUID = %S\n", g_csGUID);
  161. DPF("FindAOL", eDbgLevelInfo, "-----------------------------------\n");
  162. return TRUE;
  163. }
  164. BOOL InvokeApphelpShowDialog(DWORD dwHTMLHelpID)
  165. {
  166. _pfn_ApphelpShowDialog pfnApphelpShowDialog = NULL;
  167. APPHELP_INFO AHInfo = { 0 };
  168. HMODULE hAppHelpDLL = NULL;
  169. hAppHelpDLL = LoadLibrary(L"APPHELP.DLL");
  170. DPF("FindAOL", eDbgLevelWarning, "Apphelp:%d\n",hAppHelpDLL );
  171. if (hAppHelpDLL)
  172. {
  173. pfnApphelpShowDialog = (_pfn_ApphelpShowDialog) GetProcAddress(hAppHelpDLL, "ApphelpShowDialog");
  174. if (pfnApphelpShowDialog == NULL)
  175. {
  176. DPF("FindAOL", eDbgLevelInfo, "Unable to get APPHELP!ApphelpShowDialog procedure address.\n");
  177. return FALSE;
  178. }
  179. AHInfo.dwHtmlHelpID = dwHTMLHelpID;
  180. AHInfo.dwSeverity = APPHELP_NOBLOCK;
  181. AHInfo.lpszAppName = g_csAppName.Get();
  182. AHInfo.bPreserveChoice = TRUE;
  183. HRESULT hr;
  184. UNICODE_STRING ustrGuid;
  185. NTSTATUS ntstatus;
  186. RtlInitUnicodeString(&ustrGuid, g_csGUID.Get());
  187. ntstatus = RtlGUIDFromString(&ustrGuid, &AHInfo.guidID);
  188. if (NT_SUCCESS(ntstatus)==FALSE)
  189. {
  190. DPF("FindAOL", eDbgLevelInfo, "RtlGUIDFromString failed!\n");
  191. return FALSE;
  192. }
  193. if (pfnApphelpShowDialog(&AHInfo,NULL))
  194. {
  195. DPF("FindAOL", eDbgLevelInfo, "!\n");
  196. }
  197. else
  198. {
  199. DPF("FindAOL", eDbgLevelInfo, "RtlGUIDFromString FAILED!\n");
  200. return FALSE;
  201. }
  202. }
  203. else
  204. {
  205. DPF("FindAOL", eDbgLevelInfo, "LoadLibrary FAILED!\n");
  206. return FALSE;
  207. }
  208. return TRUE;
  209. }
  210. void DoIt()
  211. {
  212. char szModuleName[MAX_PATH];
  213. DWORD dwLen = 0;
  214. CHAR lpszInstaller[MAX_PATH];
  215. BOOL bBundledInstallerFound = FALSE;
  216. BOOL bDisplayAppHelpDialog = FALSE;
  217. BOOL bKillCurrentProcess = FALSE;
  218. BOOL bLaunchBundledInstaller = FALSE;
  219. BOOL bReturnValue = FALSE;
  220. UINT uiWinExecReturned = 0;
  221. if (!g_bDoneIt) {
  222. if (!ParseCommandLine(COMMAND_LINE)) {
  223. goto eh;
  224. }
  225. bBundledInstallerFound = LocateInstaller(lpszInstaller, MAX_PATH, &bDisplayAppHelpDialog);
  226. if (bBundledInstallerFound) {
  227. DPF("FindAOL", eDbgLevelWarning, "Bundled installer found in %s.\n",lpszInstaller);
  228. }
  229. if (bBundledInstallerFound == FALSE && bDisplayAppHelpDialog == FALSE) {
  230. DPF("FindAOL", eDbgLevelWarning, "Bundled installer not found. Let client run normally.\n");
  231. goto eh;
  232. }
  233. if (bBundledInstallerFound == FALSE && bDisplayAppHelpDialog == TRUE) {
  234. bReturnValue = InvokeApphelpShowDialog(g_dwHTMLHelpID_Incompatible);
  235. // if user chose Cancel button, then just kill current process.
  236. if (FALSE == bReturnValue) {
  237. bKillCurrentProcess = TRUE;
  238. }
  239. }
  240. if (bBundledInstallerFound == TRUE && bDisplayAppHelpDialog == TRUE) {
  241. bReturnValue = InvokeApphelpShowDialog(g_dwHTMLHelpID_BundledFound);
  242. // if user chose Continue button, then launch bundled installer.
  243. if (TRUE == bReturnValue) {
  244. bKillCurrentProcess = TRUE;
  245. bLaunchBundledInstaller = TRUE;
  246. }
  247. }
  248. if (bBundledInstallerFound == TRUE && bDisplayAppHelpDialog == FALSE) {
  249. // Launch bundled installer.
  250. bKillCurrentProcess = TRUE;
  251. bLaunchBundledInstaller = TRUE;
  252. }
  253. if (bLaunchBundledInstaller) {
  254. // launch bundled installer instead
  255. uiWinExecReturned = WinExec(lpszInstaller, SW_SHOW);
  256. if (uiWinExecReturned <= 31) {
  257. DPF("FindAOL", eDbgLevelError, "Can not launch program. Error: %d\n",GetLastError());
  258. goto eh;
  259. }
  260. }
  261. if (bKillCurrentProcess) {
  262. ExitProcess(0);
  263. }
  264. }
  265. eh:
  266. g_bDoneIt = TRUE;
  267. }
  268. LPSTR
  269. APIHOOK(GetCommandLineA)()
  270. {
  271. DoIt();
  272. return ORIGINAL_API(GetCommandLineA)();
  273. }
  274. VOID
  275. APIHOOK(GetStartupInfoA)(
  276. LPSTARTUPINFOA lpStartupInfo)
  277. {
  278. DoIt();
  279. ORIGINAL_API(GetStartupInfoA)(lpStartupInfo);
  280. }
  281. DWORD
  282. APIHOOK(GetModuleFileNameA)(
  283. HMODULE hModule, // handle to module
  284. LPSTR lpFilename, // file name of module
  285. DWORD nSize // size of buffer
  286. )
  287. {
  288. DoIt();
  289. return ORIGINAL_API(GetModuleFileNameA)(hModule, lpFilename, nSize);
  290. }
  291. HWND
  292. APIHOOK(CreateWindowExA)(
  293. DWORD dwExStyle,
  294. LPCSTR lpClassName,
  295. LPCSTR lpWindowName,
  296. DWORD dwStyle,
  297. int x,
  298. int y,
  299. int nWidth,
  300. int nHeight,
  301. HWND hWndParent,
  302. HMENU hMenu,
  303. HINSTANCE hInstance,
  304. LPVOID lpParam
  305. )
  306. {
  307. DoIt();
  308. return ORIGINAL_API(CreateWindowExA)(
  309. dwExStyle,
  310. lpClassName,
  311. lpWindowName,
  312. dwStyle,
  313. x,
  314. y,
  315. nWidth,
  316. nHeight,
  317. hWndParent,
  318. hMenu,
  319. hInstance,
  320. lpParam );
  321. }
  322. /*++
  323. Register hooked functions
  324. --*/
  325. HOOK_BEGIN
  326. APIHOOK_ENTRY(KERNEL32.DLL, GetCommandLineA)
  327. APIHOOK_ENTRY(KERNEL32.DLL, GetStartupInfoA)
  328. APIHOOK_ENTRY(KERNEL32.DLL, GetModuleFileNameA)
  329. APIHOOK_ENTRY(USER32.DLL, CreateWindowExA)
  330. HOOK_END
  331. IMPLEMENT_SHIM_END