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.

383 lines
12 KiB

  1. // --------------------------------------------------------------------------------
  2. // MSIMN.C
  3. // Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  4. // --------------------------------------------------------------------------------
  5. #include "pch.h"
  6. #define DEFINE_STRCONST
  7. #include <msoeapi.h>
  8. #include "msimnp.h"
  9. #include "res.h"
  10. #include "../msoeres/resource.h"
  11. #include "shared.h"
  12. #include "msoert.h"
  13. #include "shlwapi.h"
  14. #include "shlwapip.h"
  15. #include <mapicode.h>
  16. #include "error.h"
  17. // --------------------------------------------------------------------------------
  18. // String Consts
  19. // --------------------------------------------------------------------------------
  20. static const WCHAR c_wszRegCmd[] = L"/reg";
  21. static const WCHAR c_wszUnRegCmd[] = L"/unreg";
  22. static const WCHAR c_wszEmpty[] = L"";
  23. static const char c_szLangDll[] = "MSOERES.DLL";
  24. static const char c_szOLNewsKey[] = "Software\\Clients\\News\\Microsoft Outlook";
  25. static const char c_szRegOLNews[] = "OLNews";
  26. static const char c_szRegFlat[] = "Software\\Microsoft\\Outlook Express";
  27. static const char c_szDontUpgradeOLNews[] = "NoUpgradeOLNews";
  28. // --------------------------------------------------------------------------------
  29. // Debug Strings
  30. // --------------------------------------------------------------------------------
  31. #ifdef DEBUG
  32. static const TCHAR c_szDebug[] = "mshtmdbg.dll";
  33. static const TCHAR c_szDebugUI[] = "DbgExDoTracePointsDialog";
  34. static const TCHAR c_szRegSpy[] = "DbgExGetMallocSpy";
  35. static const WCHAR c_wszInvokeUI[] = L"/d";
  36. #endif
  37. // --------------------------------------------------------------------------------
  38. // MSHTMDBG.DLL Prototypes
  39. // --------------------------------------------------------------------------------
  40. #ifdef DEBUG
  41. typedef void (STDAPICALLTYPE *PFNDEBUGUI)(BOOL);
  42. typedef void *(STDAPICALLTYPE *PFNREGSPY)(void);
  43. #endif
  44. // --------------------------------------------------------------------------------
  45. // Debug Prototypes
  46. // --------------------------------------------------------------------------------
  47. #ifdef DEBUG
  48. void LoadMSHTMDBG(LPWSTR pwszCmdLine);
  49. #endif
  50. // --------------------------------------------------------------------------------
  51. // Prototypes
  52. // --------------------------------------------------------------------------------
  53. int WinMainT(HINSTANCE hInst, HINSTANCE hInstPrev, LPWSTR pwszCmdLine, int nCmdShow);
  54. // --------------------------------------------------------------------------------
  55. // UpgradeOLNewsReader()
  56. // --------------------------------------------------------------------------------
  57. void UpgradeOLNewsReader(HINSTANCE hInst)
  58. {
  59. HKEY hkey;
  60. BOOL fOK = TRUE;
  61. DWORD dwDont, cb;
  62. // Make sure this functionality hasn't been disabled
  63. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegFlat, 0, KEY_READ, &hkey))
  64. {
  65. cb = sizeof(dwDont);
  66. if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szDontUpgradeOLNews, 0, NULL, (LPBYTE)&dwDont, &cb))
  67. fOK = 0 == dwDont;
  68. RegCloseKey(hkey);
  69. }
  70. if (fOK && ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szOLNewsKey, 0, KEY_READ, &hkey))
  71. {
  72. RegCloseKey(hkey);
  73. CallRegInstall(hInst, hInst, c_szRegOLNews, (LPSTR)c_szOLNewsKey);
  74. }
  75. }
  76. // --------------------------------------------------------------------------------
  77. // ModuleEntry - Stolen from the CRT, used to shirink our code
  78. // --------------------------------------------------------------------------------
  79. int _stdcall ModuleEntry(void)
  80. {
  81. // Locals
  82. int i;
  83. STARTUPINFOA si;
  84. LPWSTR pwszCmdLine;
  85. // Get the command line
  86. pwszCmdLine = GetCommandLineW();
  87. // We don't want the "No disk in drive X:" requesters, so we set the critical error mask such that calls will just silently fail
  88. SetErrorMode(SEM_FAILCRITICALERRORS);
  89. // Parse the command line
  90. if ( *pwszCmdLine == L'\"')
  91. {
  92. // Scan, and skip over, subsequent characters until another double-quote or a null is encountered.
  93. while ( *++pwszCmdLine && (*pwszCmdLine != L'\"'))
  94. {};
  95. // If we stopped on a double-quote (usual case), skip over it.
  96. if (*pwszCmdLine == L'\"')
  97. pwszCmdLine++;
  98. }
  99. else
  100. {
  101. while (*pwszCmdLine > L' ')
  102. pwszCmdLine++;
  103. }
  104. // Skip past any white space preceeding the second token.
  105. while (*pwszCmdLine && (*pwszCmdLine <= L' '))
  106. pwszCmdLine++;
  107. // Get startup information...
  108. si.dwFlags = 0;
  109. GetStartupInfoA(&si);
  110. // Call the real winmain
  111. i = WinMainT(GetModuleHandle(NULL), NULL, pwszCmdLine, (si.dwFlags & STARTF_USESHOWWINDOW) ? si.wShowWindow : SW_SHOWDEFAULT);
  112. // Since we now have a way for an extension to tell us when it is finished, we will terminate all processes when the main thread goes away.
  113. ExitProcess(i);
  114. // Done
  115. return i;
  116. }
  117. // --------------------------------------------------------------------------------
  118. // WinMain
  119. // --------------------------------------------------------------------------------
  120. int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR pszCmdLine, int nCmdShow)
  121. {
  122. // Just call ModuleEntry
  123. return(ModuleEntry());
  124. }
  125. // --------------------------------------------------------------------------------
  126. // WinMainT
  127. // --------------------------------------------------------------------------------
  128. int WinMainT(HINSTANCE hInst, HINSTANCE hInstPrev, LPWSTR pwszCmdLine, int nCmdShow)
  129. {
  130. // Locals
  131. HANDLE hMutex=NULL;
  132. HWND hwnd;
  133. DWORD dwWait, dwError;
  134. INT nErrorIds=0;
  135. PFNSTART pfnStart;
  136. HINSTANCE hInstMSOEDLL=NULL;
  137. HRESULT hrOE;
  138. HINSTANCE hInstUSER=NULL;
  139. static BOOL fFirstID=TRUE;
  140. // Register
  141. if (0 == StrCmpIW(c_wszRegCmd, pwszCmdLine))
  142. {
  143. CallRegInstall(hInst, hInst, c_szReg, NULL);
  144. // It not great to do this here, but we've only just written the OEOL keys,
  145. // and it would be worst to hit the reg during startup
  146. UpgradeOLNewsReader(hInst);
  147. return(1);
  148. }
  149. // Unregister
  150. else if (0 == StrCmpIW(c_wszUnRegCmd, pwszCmdLine))
  151. {
  152. CallRegInstall(hInst, hInst, c_szUnReg, NULL);
  153. return(1);
  154. }
  155. // Create the start shared mutex
  156. hMutex = CreateMutex(NULL, FALSE, STR_MSOEAPI_INSTANCEMUTEX);
  157. if (NULL == hMutex)
  158. {
  159. nErrorIds = idsStartupCantCreateMutex;
  160. goto exit;
  161. }
  162. // Wait for any current startups/shutdowns to finish
  163. dwWait = WaitForSingleObject(hMutex, (1000 * 60));
  164. if (dwWait != WAIT_OBJECT_0)
  165. {
  166. nErrorIds = idsStartupCantWaitForMutex;
  167. goto exit;
  168. }
  169. // Look for a current instance of the application
  170. hwnd = FindWindowWrapW(STRW_MSOEAPI_INSTANCECLASS, NULL);
  171. // is there another instance running already?
  172. if (NULL != hwnd)
  173. {
  174. // Locals
  175. COPYDATASTRUCT cds;
  176. DWORD_PTR dwResult;
  177. // Some friendly output
  178. IF_DEBUG(OutputDebugString("Another instance of Athena was found...\n\n");)
  179. // Initialize the Copy data structure
  180. cds.dwData = MSOEAPI_ACDM_CMDLINE;
  181. cds.cbData = pwszCmdLine ? (lstrlenW(pwszCmdLine)+1)*sizeof(*pwszCmdLine) : 0;
  182. cds.lpData = pwszCmdLine;
  183. // On NT5, we need to call this to allow our window in the other process to take the foreground
  184. hInstUSER = LoadLibrary("USER32.DLL");
  185. if (hInstUSER)
  186. {
  187. FARPROC pfn = GetProcAddress(hInstUSER, "AllowSetForegroundWindow");
  188. if (pfn)
  189. {
  190. DWORD dwProcessId;
  191. GetWindowThreadProcessId(hwnd, &dwProcessId);
  192. (*pfn)(dwProcessId);
  193. }
  194. FreeLibrary(hInstUSER);
  195. }
  196. // Show the window into the foreground
  197. SetForegroundWindow(hwnd);
  198. SendMessageTimeout(hwnd, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds, SMTO_ABORTIFHUNG, 1500, &dwResult);
  199. }
  200. // Lets load msoe.dll
  201. else
  202. {
  203. // Load Debug DLL
  204. IF_DEBUG(LoadMSHTMDBG(pwszCmdLine);)
  205. // Get the proc address of MSOE.DLL
  206. hInstMSOEDLL = LoadLibrary(STR_MSOEAPI_DLLNAME);
  207. // Did we load the dll
  208. if (NULL == hInstMSOEDLL)
  209. {
  210. dwError = GetLastError();
  211. if (dwError == ERROR_MOD_NOT_FOUND)
  212. {
  213. if (0xffffffff == GetFileAttributes(STR_MSOEAPI_DLLNAME))
  214. nErrorIds = idsStartupCantFindMSOEDLL;
  215. else
  216. nErrorIds = idsStartupModNotFoundMSOEDLL;
  217. }
  218. else if (dwError == ERROR_DLL_INIT_FAILED)
  219. {
  220. if (0xffffffff == GetFileAttributes(c_szLangDll))
  221. nErrorIds = idsStartupCantFindResMSOEDLL;
  222. else
  223. nErrorIds = idsStartupDllInitFailedMSOEDLL;
  224. }
  225. else
  226. {
  227. nErrorIds = idsStartupCantLoadMSOEDLL;
  228. }
  229. goto exit;
  230. }
  231. // Unlikely that this will fail
  232. pfnStart = (PFNSTART)GetProcAddress(hInstMSOEDLL, STR_MSOEAPI_START);
  233. // Did that Fail
  234. if (NULL == pfnStart)
  235. {
  236. nErrorIds = idsStartupCantLoadMSOEDLL;
  237. goto exit;
  238. }
  239. hrOE = S_RESTART_OE;
  240. while (S_RESTART_OE == hrOE)
  241. {
  242. hrOE = pfnStart(MSOEAPI_START_APPLICATION, (fFirstID ? pwszCmdLine : c_wszEmpty), nCmdShow);
  243. fFirstID = FALSE;
  244. }
  245. // NB: pfnInit will not return until the main message pump terminates
  246. if (SUCCEEDED(hrOE))
  247. {
  248. CloseHandle(hMutex);
  249. hMutex = NULL;
  250. }
  251. // The dll couldn't be loaded, as long as it wasn't due to need for ICW, display error
  252. else if (hrOE != hrUserCancel && hrOE != MAPI_E_USER_CANCEL)
  253. {
  254. nErrorIds = idsStartupCantInitMSOEDLL;
  255. goto exit;
  256. }
  257. }
  258. exit:
  259. // Cleanup
  260. if (hMutex)
  261. {
  262. ReleaseMutex(hMutex);
  263. CloseHandle(hMutex);
  264. }
  265. // Free msoe.dll
  266. if (hInstMSOEDLL)
  267. FreeLibrary(hInstMSOEDLL);
  268. // Show an error ?
  269. if (0 != nErrorIds)
  270. {
  271. // Locals
  272. CHAR szRes[255];
  273. CHAR szTitle[100];
  274. // Load the
  275. LoadString(hInst, idsOutlookExpress, szTitle, ARRAYSIZE(szTitle));
  276. // Load the
  277. LoadString(hInst, nErrorIds, szRes, ARRAYSIZE(szRes));
  278. // Show the error message
  279. MessageBox(NULL, szRes, szTitle, MB_OK | MB_SETFOREGROUND | MB_ICONEXCLAMATION);
  280. }
  281. IF_DEBUG(CoRevokeMallocSpy());
  282. // Done
  283. return nErrorIds;
  284. }
  285. #ifdef DEBUG
  286. // --------------------------------------------------------------------------------
  287. // LoadMSHTMDBG
  288. // --------------------------------------------------------------------------------
  289. void LoadMSHTMDBG(LPWSTR pwszCmdLine)
  290. {
  291. // Load mshtmdbg.dll
  292. HINSTANCE hInstDebug = LoadLibrary(c_szDebug);
  293. // Did it load ?
  294. if (NULL != hInstDebug)
  295. {
  296. // Locals
  297. PFNREGSPY pfnRegSpy;
  298. // If the user passed /d on the command line, lets configure mshtmdbg.dll
  299. if (0 == StrCmpIW(pwszCmdLine, c_wszInvokeUI))
  300. {
  301. // Locals
  302. PFNDEBUGUI pfnDebugUI;
  303. // Get the proc address of the UI
  304. pfnDebugUI = (PFNDEBUGUI)GetProcAddress(hInstDebug, c_szDebugUI);
  305. if (NULL != pfnDebugUI)
  306. {
  307. (*pfnDebugUI)(TRUE);
  308. goto exit;
  309. }
  310. }
  311. // Get the process address of the registration
  312. pfnRegSpy = (PFNREGSPY)GetProcAddress(hInstDebug, c_szRegSpy);
  313. if (NULL != pfnRegSpy)
  314. {
  315. LPMALLOCSPY pSpy = (IMallocSpy *)(*pfnRegSpy)();
  316. SideAssert(SUCCEEDED(CoRegisterMallocSpy(pSpy)));
  317. }
  318. }
  319. exit:
  320. // Done
  321. return;
  322. }
  323. #endif // DEBUG