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.

819 lines
24 KiB

  1. #include "iernonce.h"
  2. #include "resource.h"
  3. //==================================================================
  4. // AddPath()
  5. //
  6. void AddPath(LPTSTR szPath, LPCTSTR szName)
  7. {
  8. LPTSTR szTmp;
  9. // Find end of the string
  10. szTmp = szPath + lstrlen(szPath);
  11. // If no trailing backslash then add one
  12. if (szTmp > szPath && *(CharPrev(szPath, szTmp)) != TEXT('\\'))
  13. *szTmp++ = TEXT('\\');
  14. // Add new name to existing path string
  15. while (*szName == TEXT(' '))
  16. szName = CharNext(szName);
  17. lstrcpy(szTmp, szName);
  18. }
  19. // function will upated the given buffer to parent dir
  20. //
  21. BOOL GetParentDir( LPTSTR szFolder )
  22. {
  23. LPTSTR lpTmp;
  24. BOOL bRet = FALSE;
  25. // remove the trailing '\\'
  26. lpTmp = CharPrev( szFolder, (szFolder + lstrlen(szFolder)) );
  27. lpTmp = CharPrev( szFolder, lpTmp );
  28. while ( (lpTmp > szFolder) && (*lpTmp != TEXT('\\') ) )
  29. {
  30. lpTmp = CharPrev( szFolder, lpTmp );
  31. }
  32. if ( *lpTmp == TEXT('\\') )
  33. {
  34. if ( (lpTmp == szFolder) || (*CharPrev(szFolder, lpTmp)==TEXT(':') ) )
  35. lpTmp = CharNext( lpTmp );
  36. *lpTmp = TEXT('\0');
  37. bRet = TRUE;
  38. }
  39. return bRet;
  40. }
  41. // This is the value for the major version 4.71
  42. #define IE4_MS_VER 0x00040047
  43. BOOL RunningOnIE4()
  44. {
  45. static BOOL fIsIE4 = 2;
  46. TCHAR szFile[MAX_PATH];
  47. #ifdef UNICODE
  48. char szANSIFile[MAX_PATH];
  49. #endif
  50. DWORD dwMSVer;
  51. DWORD dwLSVer;
  52. if (fIsIE4 != 2)
  53. return fIsIE4;
  54. GetSystemDirectory(szFile, ARRAYSIZE(szFile));
  55. AddPath(szFile, TEXT("shell32.dll"));
  56. #ifdef UNICODE
  57. WideCharToMultiByte(CP_ACP, 0, szFile, -1, szANSIFile, sizeof(szANSIFile), NULL, NULL);
  58. #endif
  59. GetVersionFromFile(
  60. #ifdef UNICODE
  61. szANSIFile,
  62. #else
  63. szFile,
  64. #endif
  65. &dwMSVer, &dwLSVer, TRUE);
  66. fIsIE4 = dwMSVer >= IE4_MS_VER;
  67. return fIsIE4;
  68. }
  69. /****************************************************\
  70. FUNCTION: MsgWaitForMultipleObjectsLoop
  71. PARAMETERS:
  72. HANDLE hEvent - Pointer to the object-handle array of Objects
  73. DWORD dwTimeout - Time out duration
  74. DWORD return - Return is WAIT_FAILED or WAIT_OBJECT_0
  75. DESCRIPTION:
  76. Waits for the object (Process) to complete.
  77. \***************************************************/
  78. DWORD MsgWaitForMultipleObjectsLoop(HANDLE hEvent, DWORD dwTimeout)
  79. {
  80. MSG msg;
  81. DWORD dwObject;
  82. while (1)
  83. {
  84. // NB We need to let the run dialog become active so we have to half handle sent
  85. // messages but we don't want to handle any input events or we'll swallow the
  86. // type-ahead.
  87. dwObject = MsgWaitForMultipleObjects(1, &hEvent, FALSE, dwTimeout, QS_ALLINPUT);
  88. // Are we done waiting?
  89. switch (dwObject) {
  90. case WAIT_OBJECT_0:
  91. case WAIT_FAILED:
  92. return dwObject;
  93. case WAIT_OBJECT_0 + 1:
  94. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  95. DispatchMessage(&msg);
  96. break;
  97. }
  98. }
  99. // never gets here
  100. // return dwObject;
  101. }
  102. void LogOff(BOOL bRestart)
  103. {
  104. if (g_bRunningOnNT)
  105. {
  106. HANDLE hToken;
  107. TOKEN_PRIVILEGES tkp;
  108. // get a token from this process
  109. if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
  110. {
  111. // get the LUID for the shutdown privilege
  112. LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
  113. tkp.PrivilegeCount = 1;
  114. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  115. //get the shutdown privilege for this proces
  116. AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
  117. }
  118. }
  119. ExitWindowsEx(bRestart?EWX_REBOOT|EWX_FORCE:EWX_LOGOFF, 0);
  120. // this is a hack to prevent explorer from continue starting (In Integrated Shell)
  121. // and runonce from continue processing other items.
  122. // If we use a timer wait (which contains a messageloop), in browser only mode our
  123. // process gets terminated before explorer and explorer would try and continue
  124. // processing runonce items. With the while loop below this seem to not happen.
  125. if (bRestart)
  126. while (true) ;
  127. }
  128. //
  129. // Performs a message box with the text and title string loaded from the string table.
  130. void ReportError(DWORD dwFlags, UINT uiResourceNum, ...)
  131. {
  132. TCHAR szResourceStr[1024] = TEXT("");
  133. va_list vaListOfMessages;
  134. LPTSTR pszErrorString = NULL;
  135. LoadString(g_hinst, uiResourceNum, szResourceStr, ARRAYSIZE(szResourceStr));
  136. va_start(vaListOfMessages, uiResourceNum); // Initialize variable arguments.
  137. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_STRING,
  138. (LPCVOID) szResourceStr, 0, 0, (LPTSTR) &pszErrorString, 0, &vaListOfMessages);
  139. va_end(vaListOfMessages);
  140. if (pszErrorString != NULL)
  141. {
  142. if (!(RRAEX_NO_ERROR_DIALOGS & dwFlags)) // Display Error dialog
  143. {
  144. if (*g_szTitleString == TEXT('\0')) // Initialize this only once
  145. LoadString(g_hinst, IDS_RUNONCEEX_TITLE, g_szTitleString, ARRAYSIZE(g_szTitleString));
  146. MessageBox(NULL, pszErrorString, g_szTitleString, MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
  147. }
  148. // If there is a cllback then callback with error string
  149. if (g_pCallbackProc)
  150. g_pCallbackProc(0, 0, pszErrorString);
  151. WriteToLog(pszErrorString);
  152. WriteToLog(TEXT("\r\n"));
  153. LocalFree(pszErrorString);
  154. }
  155. }
  156. // copied from msdev\crt\src\atox.c
  157. /***
  158. *long AtoL(char *nptr) - Convert string to long
  159. *
  160. *Purpose:
  161. * Converts ASCII string pointed to by nptr to binary.
  162. * Overflow is not detected.
  163. *
  164. *Entry:
  165. * nptr = ptr to string to convert
  166. *
  167. *Exit:
  168. * return long int value of the string
  169. *
  170. *Exceptions:
  171. * None - overflow is not detected.
  172. *
  173. *******************************************************************************/
  174. long AtoL(const char *nptr)
  175. {
  176. int c; /* current char */
  177. long total; /* current total */
  178. int sign; /* if '-', then negative, otherwise positive */
  179. // NOTE: no need to worry about DBCS chars here because IsSpace(c), IsDigit(c),
  180. // '+' and '-' are "pure" ASCII chars, i.e., they are neither DBCS Leading nor
  181. // DBCS Trailing bytes -- pritvi
  182. /* skip whitespace */
  183. while ( IsSpace((int)(unsigned char)*nptr) )
  184. ++nptr;
  185. c = (int)(unsigned char)*nptr++;
  186. sign = c; /* save sign indication */
  187. if (c == '-' || c == '+')
  188. c = (int)(unsigned char)*nptr++; /* skip sign */
  189. total = 0;
  190. while (IsDigit(c)) {
  191. total = 10 * total + (c - '0'); /* accumulate digit */
  192. c = (int)(unsigned char)*nptr++; /* get next char */
  193. }
  194. if (sign == '-')
  195. return -total;
  196. else
  197. return total; /* return result, negated if necessary */
  198. }
  199. // returns a pointer to the arguments in a cmd type path or pointer to
  200. // NULL if no args exist
  201. //
  202. // "foo.exe bar.txt" -> "bar.txt"
  203. // "foo.exe" -> ""
  204. //
  205. // Spaces in filenames must be quoted.
  206. // " "A long name.txt" bar.txt " -> "bar.txt"
  207. STDAPI_(LPTSTR)
  208. LocalPathGetArgs(
  209. LPCTSTR pszPath) // copied from \\trango\slmadd\src\shell\shlwapi\path.c
  210. {
  211. BOOL fInQuotes = FALSE;
  212. if (!pszPath)
  213. return NULL;
  214. while (*pszPath)
  215. {
  216. if (*pszPath == TEXT('"'))
  217. fInQuotes = !fInQuotes;
  218. else if (!fInQuotes && *pszPath == TEXT(' '))
  219. return (LPTSTR)pszPath+1;
  220. pszPath = CharNext(pszPath);
  221. }
  222. return (LPTSTR)pszPath;
  223. }
  224. /*----------------------------------------------------------
  225. Purpose: If a path is contained in quotes then remove them.
  226. Returns: --
  227. Cond: --
  228. */
  229. STDAPI_(void)
  230. LocalPathUnquoteSpaces(
  231. LPTSTR lpsz) // copied from \\trango\slmadd\src\shell\shlwapi\path.c
  232. {
  233. int cch;
  234. cch = lstrlen(lpsz);
  235. // Are the first and last chars quotes?
  236. if (lpsz[0] == TEXT('"') && lpsz[cch-1] == TEXT('"'))
  237. {
  238. // Yep, remove them.
  239. lpsz[cch-1] = TEXT('\0');
  240. hmemcpy(lpsz, lpsz+1, (cch-1) * sizeof(TCHAR));
  241. }
  242. }
  243. #ifdef UNICODE
  244. LPWSTR FAR PASCAL LocalStrChrW(LPCWSTR lpStart, WORD wMatch)
  245. // copied from \\trango\slmadd\src\shell\shlwapi\strings.c
  246. {
  247. for ( ; *lpStart; lpStart++)
  248. {
  249. // Need a tmp word since casting ptr to WORD * will
  250. // fault on MIPS, ALPHA
  251. WORD wTmp;
  252. memcpy(&wTmp, lpStart, sizeof(WORD));
  253. if (!ChrCmpW_inline(wTmp, wMatch))
  254. {
  255. return((LPWSTR)lpStart);
  256. }
  257. }
  258. return (NULL);
  259. }
  260. __inline BOOL ChrCmpW_inline(WORD w1, WORD wMatch)
  261. // copied from \\trango\slmadd\src\shell\shlwapi\strings.c
  262. {
  263. return(!(w1 == wMatch));
  264. }
  265. #else
  266. /*
  267. * StrChr - Find first occurrence of character in string
  268. * Assumes lpStart points to start of null terminated string
  269. * wMatch is the character to match
  270. * returns ptr to the first occurrence of ch in str, NULL if not found.
  271. */
  272. LPSTR FAR PASCAL LocalStrChrA(LPCSTR lpStart, WORD wMatch)
  273. // copied from \\trango\slmadd\src\shell\shlwapi\strings.c
  274. {
  275. for ( ; *lpStart; lpStart = AnsiNext(lpStart))
  276. {
  277. if (!ChrCmpA_inline(*(UNALIGNED WORD FAR *)lpStart, wMatch))
  278. return((LPSTR)lpStart);
  279. }
  280. return (NULL);
  281. }
  282. /*
  283. * ChrCmp - Case sensitive character comparison for DBCS
  284. * Assumes w1, wMatch are characters to be compared
  285. * Return FALSE if they match, TRUE if no match
  286. */
  287. __inline BOOL ChrCmpA_inline(WORD w1, WORD wMatch)
  288. // copied from \\trango\slmadd\src\shell\shlwapi\strings.c
  289. {
  290. /* Most of the time this won't match, so test it first for speed.
  291. */
  292. if (LOBYTE(w1) == LOBYTE(wMatch))
  293. {
  294. if (IsDBCSLeadByte(LOBYTE(w1)))
  295. {
  296. return(w1 != wMatch);
  297. }
  298. return FALSE;
  299. }
  300. return TRUE;
  301. }
  302. #endif
  303. #ifdef UNICODE
  304. /*----------------------------------------------------------
  305. Purpose: Recursively delete the key, including all child values
  306. and keys.
  307. Returns:
  308. Cond: --
  309. */
  310. STDAPI_(DWORD)
  311. LocalSHDeleteKeyW(
  312. HKEY hkey,
  313. LPCWSTR pwszSubKey) // copied from \\trango\slmadd\src\shell\shlwapi\reg.c
  314. {
  315. DWORD dwRet;
  316. CHAR sz[MAX_PATH];
  317. WideCharToMultiByte(CP_ACP, 0, pwszSubKey, -1, sz, ARRAYSIZE(sz), NULL, NULL);
  318. if (g_bRunningOnNT)
  319. {
  320. dwRet = DeleteKeyRecursively(hkey, sz);
  321. }
  322. else
  323. {
  324. // On Win95, RegDeleteKey does what we want
  325. dwRet = RegDeleteKeyA(hkey, sz);
  326. }
  327. RegFlushKey(hkey);
  328. return dwRet;
  329. }
  330. #else
  331. /*----------------------------------------------------------
  332. Purpose: Recursively delete the key, including all child values
  333. and keys.
  334. Returns:
  335. Cond: --
  336. */
  337. STDAPI_(DWORD)
  338. LocalSHDeleteKeyA(
  339. HKEY hkey,
  340. LPCSTR pszSubKey) // copied from \\trango\slmadd\src\shell\shlwapi\reg.c
  341. {
  342. DWORD dwRet;
  343. if (g_bRunningOnNT)
  344. {
  345. dwRet = DeleteKeyRecursively(hkey, pszSubKey);
  346. }
  347. else
  348. {
  349. // On Win95, RegDeleteKey does what we want
  350. dwRet = RegDeleteKeyA(hkey, pszSubKey);
  351. }
  352. RegFlushKey(hkey);
  353. return dwRet;
  354. }
  355. #endif
  356. /*----------------------------------------------------------
  357. Purpose: Recursively delete the key, including all child values
  358. and keys. Mimics what RegDeleteKey does in Win95.
  359. Returns:
  360. Cond: --
  361. */
  362. DWORD
  363. DeleteKeyRecursively(
  364. HKEY hkey,
  365. LPCSTR pszSubKey) // copied from \\trango\slmadd\src\shell\shlwapi\reg.c
  366. {
  367. DWORD dwRet;
  368. HKEY hkSubKey;
  369. // Open the subkey so we can enumerate any children
  370. dwRet = RegOpenKeyExA(hkey, pszSubKey, 0, KEY_READ | KEY_WRITE, &hkSubKey);
  371. if (ERROR_SUCCESS == dwRet)
  372. {
  373. DWORD dwIndex;
  374. CHAR szSubKeyName[MAX_PATH + 1];
  375. DWORD cchSubKeyName = ARRAYSIZE(szSubKeyName);
  376. CHAR szClass[MAX_PATH];
  377. DWORD cbClass = ARRAYSIZE(szClass);
  378. // I can't just call RegEnumKey with an ever-increasing index, because
  379. // I'm deleting the subkeys as I go, which alters the indices of the
  380. // remaining subkeys in an implementation-dependent way. In order to
  381. // be safe, I have to count backwards while deleting the subkeys.
  382. // Find out how many subkeys there are
  383. dwRet = RegQueryInfoKeyA(hkSubKey,
  384. szClass,
  385. &cbClass,
  386. NULL,
  387. &dwIndex, // The # of subkeys -- all we need
  388. NULL,
  389. NULL,
  390. NULL,
  391. NULL,
  392. NULL,
  393. NULL,
  394. NULL);
  395. if (NO_ERROR == dwRet)
  396. {
  397. // dwIndex is now the count of subkeys, but it needs to be
  398. // zero-based for RegEnumKey, so I'll pre-decrement, rather
  399. // than post-decrement.
  400. while (ERROR_SUCCESS == RegEnumKeyA(hkSubKey, --dwIndex, szSubKeyName, cchSubKeyName))
  401. {
  402. DeleteKeyRecursively(hkSubKey, szSubKeyName);
  403. }
  404. }
  405. RegCloseKey(hkSubKey);
  406. dwRet = RegDeleteKeyA(hkey, pszSubKey);
  407. }
  408. return dwRet;
  409. }
  410. #ifdef UNICODE
  411. /*----------------------------------------------------------
  412. Purpose: Deletes a registry value. This opens and closes the
  413. key in which the value resides.
  414. On Win95, this function thunks and calls the ansi
  415. version. On NT, this function calls the unicode
  416. registry APIs directly.
  417. Perf: if your code involves setting/getting a series
  418. of values in the same key, it is better to open
  419. the key once and set/get the values with the regular
  420. Win32 registry functions, rather than using this
  421. function repeatedly.
  422. Returns:
  423. Cond: --
  424. */
  425. LocalSHDeleteValueW(
  426. HKEY hkey,
  427. LPCWSTR pwszSubKey,
  428. LPCWSTR pwszValue) // copied from \\trango\slmadd\src\shell\shlwapi\reg.c
  429. {
  430. DWORD dwRet;
  431. HKEY hkeyNew;
  432. if (g_bRunningOnNT)
  433. {
  434. dwRet = RegOpenKeyExW(hkey, pwszSubKey, 0, KEY_SET_VALUE, &hkeyNew);
  435. if (NO_ERROR == dwRet)
  436. {
  437. dwRet = RegDeleteValueW(hkeyNew, pwszValue);
  438. RegFlushKey(hkeyNew);
  439. RegCloseKey(hkeyNew);
  440. }
  441. }
  442. else
  443. {
  444. CHAR szSubKey[MAX_PATH];
  445. CHAR szValue[MAX_PATH];
  446. LPSTR pszSubKey = NULL;
  447. LPSTR pszValue = NULL;
  448. if (pwszSubKey)
  449. {
  450. WideCharToMultiByte(CP_ACP, 0, pwszSubKey, -1, szSubKey, ARRAYSIZE(szSubKey), NULL, NULL);
  451. pszSubKey = szSubKey;
  452. }
  453. if (pwszValue)
  454. {
  455. WideCharToMultiByte(CP_ACP, 0, pwszValue, -1, szValue, ARRAYSIZE(szValue), NULL, NULL);
  456. pszValue = szValue;
  457. }
  458. dwRet = LocalSHDeleteValueA(hkey, pszSubKey, pszValue);
  459. }
  460. return dwRet;
  461. }
  462. #endif
  463. /*----------------------------------------------------------
  464. Purpose: Deletes a registry value. This opens and closes the
  465. key in which the value resides.
  466. Perf: if your code involves setting/getting a series
  467. of values in the same key, it is better to open
  468. the key once and set/get the values with the regular
  469. Win32 registry functions, rather than using this
  470. function repeatedly.
  471. Returns:
  472. Cond: --
  473. */
  474. STDAPI_(DWORD)
  475. LocalSHDeleteValueA(
  476. HKEY hkey,
  477. LPCSTR pszSubKey,
  478. LPCSTR pszValue) // copied from \\trango\slmadd\src\shell\shlwapi\reg.c
  479. {
  480. DWORD dwRet;
  481. HKEY hkeyNew;
  482. dwRet = RegOpenKeyExA(hkey, pszSubKey, 0, KEY_SET_VALUE, &hkeyNew);
  483. if (NO_ERROR == dwRet)
  484. {
  485. dwRet = RegDeleteValueA(hkeyNew, pszValue);
  486. RegFlushKey(hkeyNew);
  487. RegCloseKey(hkeyNew);
  488. }
  489. return dwRet;
  490. }
  491. LPTSTR GetLogFileName(LPCTSTR pcszLogFileKeyName, LPTSTR pszLogFileName, DWORD dwSizeInChars)
  492. {
  493. TCHAR szBuf[MAX_PATH];
  494. *pszLogFileName = TEXT('\0');
  495. szBuf[0] = TEXT('\0');
  496. // get the name for the log file
  497. GetProfileString(TEXT("IE4Setup"), pcszLogFileKeyName, TEXT(""), szBuf, ARRAYSIZE(szBuf));
  498. if (*szBuf == TEXT('\0')) // check in the registry
  499. {
  500. HKEY hkSubKey;
  501. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\IE Setup\\Setup"), 0, KEY_READ, &hkSubKey) == ERROR_SUCCESS)
  502. {
  503. DWORD dwDataLen = sizeof(szBuf);
  504. RegQueryValueEx(hkSubKey, pcszLogFileKeyName, NULL, NULL, (LPBYTE) szBuf, &dwDataLen);
  505. RegCloseKey(hkSubKey);
  506. }
  507. }
  508. if (*szBuf)
  509. {
  510. // crude way of determining if fully qualified path is specified or not.
  511. if (szBuf[1] != TEXT(':'))
  512. {
  513. GetWindowsDirectory(pszLogFileName, dwSizeInChars); // default to windows dir
  514. AddPath(pszLogFileName, szBuf);
  515. }
  516. else
  517. lstrcpy(pszLogFileName, szBuf);
  518. }
  519. return pszLogFileName;
  520. }
  521. VOID StartLogging(LPCTSTR pcszLogFileName, DWORD dwCreationFlags)
  522. {
  523. if (*pcszLogFileName && (g_hLogFile = CreateFile(pcszLogFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, dwCreationFlags, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
  524. {
  525. SetFilePointer(g_hLogFile, 0, NULL, FILE_END);
  526. WriteToLog(TEXT("\r\n"));
  527. WriteToLog(TEXT("************************"));
  528. WriteToLog(TEXT(" Begin logging "));
  529. WriteToLog(TEXT("************************"));
  530. WriteToLog(TEXT("\r\n"));
  531. LogDateAndTime();
  532. WriteToLog(TEXT("\r\n"));
  533. }
  534. }
  535. VOID WriteToLog(LPCTSTR pcszFormatString, ...)
  536. {
  537. if (g_hLogFile != INVALID_HANDLE_VALUE)
  538. {
  539. va_list vaArgs;
  540. LPTSTR pszFullErrMsg = NULL;
  541. LPSTR pszANSIFullErrMsg;
  542. DWORD dwBytesWritten;
  543. #ifdef UNICODE
  544. DWORD dwANSILen;
  545. #endif
  546. va_start(vaArgs, pcszFormatString);
  547. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_STRING,
  548. (LPCVOID) pcszFormatString, 0, 0, (LPTSTR) &pszFullErrMsg, 0, &vaArgs);
  549. va_end(vaArgs);
  550. if (pszFullErrMsg != NULL)
  551. {
  552. #ifdef UNICODE
  553. dwANSILen = lstrlen(pszFullErrMsg) + 1;
  554. if ((pszANSIFullErrMsg = (LPSTR) LocalAlloc(LPTR, dwANSILen)) != NULL)
  555. WideCharToMultiByte(CP_ACP, 0, pszFullErrMsg, -1, pszANSIFullErrMsg, dwANSILen, NULL, NULL);
  556. #else
  557. pszANSIFullErrMsg = pszFullErrMsg;
  558. #endif
  559. if (pszANSIFullErrMsg != NULL)
  560. {
  561. WriteFile(g_hLogFile, pszANSIFullErrMsg, lstrlen(pszANSIFullErrMsg), &dwBytesWritten, NULL);
  562. #ifdef UNICODE
  563. LocalFree(pszANSIFullErrMsg);
  564. #endif
  565. }
  566. LocalFree(pszFullErrMsg);
  567. }
  568. }
  569. }
  570. VOID StopLogging()
  571. {
  572. LogDateAndTime();
  573. WriteToLog(TEXT("************************"));
  574. WriteToLog(TEXT(" End logging "));
  575. WriteToLog(TEXT("************************"));
  576. WriteToLog(TEXT("\r\n"));
  577. if (g_hLogFile != INVALID_HANDLE_VALUE)
  578. {
  579. CloseHandle(g_hLogFile);
  580. g_hLogFile = INVALID_HANDLE_VALUE;
  581. }
  582. }
  583. VOID LogDateAndTime()
  584. {
  585. if (g_hLogFile != INVALID_HANDLE_VALUE)
  586. {
  587. SYSTEMTIME SystemTime;
  588. GetLocalTime(&SystemTime);
  589. WriteToLog(TEXT("Date: %1!02d!/%2!02d!/%3!04d! (mm/dd/yyyy)\tTime: %4!02d!:%5!02d!:%6!02d! (hh:mm:ss)\r\n"),
  590. SystemTime.wMonth, SystemTime.wDay, SystemTime.wYear,
  591. SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond);
  592. }
  593. }
  594. VOID LogFlags(DWORD dwFlags)
  595. {
  596. if (g_hLogFile != INVALID_HANDLE_VALUE)
  597. {
  598. WriteToLog(TEXT("RRA_DELETE = %1!lu!\r\n"), (dwFlags & RRA_DELETE) ? 1 : 0);
  599. WriteToLog(TEXT("RRA_WAIT = %1!lu!\r\n"), (dwFlags & RRA_WAIT) ? 1 : 0);
  600. WriteToLog(TEXT("RRAEX_NO_ERROR_DIALOGS = %1!lu!\r\n"), (dwFlags & RRAEX_NO_ERROR_DIALOGS) ? 1 : 0);
  601. WriteToLog(TEXT("RRAEX_ERRORFILE = %1!lu!\r\n"), (dwFlags & RRAEX_ERRORFILE) ? 1 : 0);
  602. WriteToLog(TEXT("RRAEX_LOG_FILE = %1!lu!\r\n"), (dwFlags & RRAEX_LOG_FILE) ? 1 : 0);
  603. WriteToLog(TEXT("RRAEX_NO_EXCEPTION_TRAPPING = %1!lu!\r\n"), (dwFlags & RRAEX_NO_EXCEPTION_TRAPPING) ? 1 : 0);
  604. WriteToLog(TEXT("RRAEX_NO_STATUS_DIALOG = %1!lu!\r\n"), (dwFlags & RRAEX_NO_STATUS_DIALOG) ? 1 : 0);
  605. WriteToLog(TEXT("RRAEX_IGNORE_REG_FLAGS = %1!lu!\r\n"), (dwFlags & RRAEX_IGNORE_REG_FLAGS) ? 1 : 0);
  606. WriteToLog(TEXT("RRAEX_CHECK_NT_ADMIN = %1!lu!\r\n"), (dwFlags & RRAEX_CHECK_NT_ADMIN) ? 1 : 0);
  607. WriteToLog(TEXT("RRAEX_QUIT_IF_REBOOT_NEEDED = %1!lu!\r\n"), (dwFlags & RRAEX_QUIT_IF_REBOOT_NEEDED) ? 1 : 0);
  608. #if 0
  609. /****
  610. WriteToLog(TEXT("RRAEX_BACKUP_SYSTEM_DAT = %1!lu!\r\n"), (dwFlags & RRAEX_BACKUP_SYSTEM_DAT) ? 1 : 0);
  611. WriteToLog(TEXT("RRAEX_DELETE_SYSTEM_IE4 = %1!lu!\r\n"), (dwFlags & RRAEX_DELETE_SYSTEM_IE4) ? 1 : 0);
  612. ****/
  613. #endif
  614. #if 0
  615. /**** enable this when explorer.exe is fixed (bug #30866)
  616. WriteToLog(TEXT("RRAEX_CREATE_REGFILE = %1!lu!\r\n"), (dwFlags & RRAEX_CREATE_REGFILE) ? 1 : 0);
  617. ****/
  618. #endif
  619. }
  620. }
  621. // CRT stubs
  622. //=--------------------------------------------------------------------------=
  623. // these two things are here so the CRTs aren't needed. this is good.
  624. //
  625. // basically, the CRTs define this to pull in a bunch of stuff. we'll just
  626. // define them here so we don't get an unresolved external.
  627. //
  628. // TODO: if you are going to use the CRTs, then remove this line.
  629. //
  630. extern "C" int _fltused = 1;
  631. extern "C" int _cdecl _purecall(void)
  632. {
  633. // FAIL("Pure virtual function called.");
  634. return 0;
  635. }
  636. void * _cdecl operator new
  637. (
  638. size_t size
  639. )
  640. {
  641. return HeapAlloc(g_hHeap, 0, size);
  642. }
  643. //=---------------------------------------------------------------------------=
  644. // overloaded delete
  645. //=---------------------------------------------------------------------------=
  646. // retail case just uses win32 Local* heap mgmt functions
  647. //
  648. // Parameters:
  649. // void * - [in] free me!
  650. //
  651. // Notes:
  652. //
  653. void _cdecl operator delete ( void *ptr)
  654. {
  655. HeapFree(g_hHeap, 0, ptr);
  656. }
  657. void * _cdecl malloc(size_t n)
  658. {
  659. #ifdef _MALLOC_ZEROINIT
  660. return HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, n);
  661. #else
  662. return HeapAlloc(g_hHeap, 0, n);
  663. #endif
  664. }
  665. void * _cdecl calloc(size_t n, size_t s)
  666. {
  667. return HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, n * s);
  668. }
  669. void* _cdecl realloc(void* p, size_t n)
  670. {
  671. if (p == NULL)
  672. return malloc(n);
  673. return HeapReAlloc(g_hHeap, 0, p, n);
  674. }
  675. void _cdecl free(void* p)
  676. {
  677. if (p == NULL)
  678. return;
  679. HeapFree(g_hHeap, 0, p);
  680. }