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.

855 lines
25 KiB

  1. #include "pch.hxx"
  2. #include "util.h"
  3. #include "shared.h"
  4. #include "strings.h"
  5. // Copied from nt\shell\shlwapi\reg.c
  6. DWORD
  7. DeleteKeyRecursively(
  8. IN HKEY hkey,
  9. IN LPCSTR pszSubKey)
  10. {
  11. DWORD dwRet;
  12. HKEY hkSubKey;
  13. // Open the subkey so we can enumerate any children
  14. dwRet = RegOpenKeyExA(hkey, pszSubKey, 0, MAXIMUM_ALLOWED, &hkSubKey);
  15. if (ERROR_SUCCESS == dwRet)
  16. {
  17. DWORD dwIndex;
  18. CHAR szSubKeyName[MAX_PATH + 1];
  19. DWORD cchSubKeyName = ARRAYSIZE(szSubKeyName);
  20. // I can't just call RegEnumKey with an ever-increasing index, because
  21. // I'm deleting the subkeys as I go, which alters the indices of the
  22. // remaining subkeys in an implementation-dependent way. In order to
  23. // be safe, I have to count backwards while deleting the subkeys.
  24. // Find out how many subkeys there are
  25. dwRet = RegQueryInfoKeyA(hkSubKey, NULL, NULL, NULL,
  26. &dwIndex, // The # of subkeys -- all we need
  27. NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  28. if (NO_ERROR == dwRet)
  29. {
  30. // dwIndex is now the count of subkeys, but it needs to be
  31. // zero-based for RegEnumKey, so I'll pre-decrement, rather
  32. // than post-decrement.
  33. while (ERROR_SUCCESS == RegEnumKeyA(hkSubKey, --dwIndex, szSubKeyName, cchSubKeyName))
  34. {
  35. DeleteKeyRecursively(hkSubKey, szSubKeyName);
  36. }
  37. }
  38. RegCloseKey(hkSubKey);
  39. if (pszSubKey)
  40. {
  41. dwRet = RegDeleteKeyA(hkey, pszSubKey);
  42. }
  43. else
  44. {
  45. // we want to delete all the values by hand
  46. cchSubKeyName = ARRAYSIZE(szSubKeyName);
  47. while (ERROR_SUCCESS == RegEnumValueA(hkey, 0, szSubKeyName, &cchSubKeyName, NULL, NULL, NULL, NULL))
  48. {
  49. // avoid looping infinitely when we cant delete the value
  50. if (RegDeleteValueA(hkey, szSubKeyName))
  51. break;
  52. cchSubKeyName = ARRAYSIZE(szSubKeyName);
  53. }
  54. }
  55. }
  56. return dwRet;
  57. }
  58. //--------------------------------------------------------------------------
  59. // GetWindowsDirectoryWrap
  60. //
  61. // Returns the system's Windows directory
  62. // Based on code from SHLWAPI's util.cpp by TNoonan
  63. //--------------------------------------------------------------------------
  64. typedef UINT (__stdcall * PFNGETSYSTEMWINDOWSDIRECTORYA)(LPSTR pszBuffer, UINT cchBuff);
  65. UINT GetSystemWindowsDirectoryWrap(LPTSTR pszBuffer, UINT uSize)
  66. {
  67. // On NT?
  68. if (VER_PLATFORM_WIN32_NT == si.osv.dwPlatformId)
  69. {
  70. static PFNGETSYSTEMWINDOWSDIRECTORYA s_pfn = (PFNGETSYSTEMWINDOWSDIRECTORYA)-1;
  71. if (((PFNGETSYSTEMWINDOWSDIRECTORYA)-1) == s_pfn)
  72. {
  73. HINSTANCE hinst = GetModuleHandle(TEXT("KERNEL32.DLL"));
  74. Assert(NULL != hinst); // YIKES!
  75. if (hinst)
  76. s_pfn = (PFNGETSYSTEMWINDOWSDIRECTORYA)GetProcAddress(hinst, "GetSystemWindowsDirectoryA");
  77. else
  78. s_pfn = NULL;
  79. }
  80. if (s_pfn)
  81. {
  82. // we use the new API so we dont get lied to by hydra
  83. return s_pfn(pszBuffer, uSize);
  84. }
  85. else
  86. {
  87. // Get System directory is not munged by Hydra
  88. GetSystemDirectory(pszBuffer, uSize);
  89. PathRemoveFileSpec(pszBuffer);
  90. return lstrlen(pszBuffer);
  91. }
  92. }
  93. else
  94. {
  95. // Okay to call GetWindowsDirectory as we are on 9x
  96. return GetWindowsDirectory(pszBuffer, uSize);
  97. }
  98. }
  99. /****************************************************************************
  100. NAME: GoodEnough
  101. SYNOPSIS: Returns true if pwVerGot is newer or equal to pwVerNeed
  102. ****************************************************************************/
  103. BOOL GoodEnough(WORD *pwVerGot, WORD *pwVerNeed)
  104. {
  105. BOOL fOK = FALSE;
  106. Assert(pwVerGot);
  107. Assert(pwVerNeed);
  108. if (pwVerGot[0] > pwVerNeed[0])
  109. fOK = TRUE;
  110. else if (pwVerGot[0] == pwVerNeed[0])
  111. {
  112. if (pwVerGot[1] > pwVerNeed[1])
  113. fOK = TRUE;
  114. else if (pwVerGot[1] == pwVerNeed[1])
  115. {
  116. if (pwVerGot[2] > pwVerNeed[2])
  117. fOK = TRUE;
  118. else if (pwVerGot[2] == pwVerNeed[2])
  119. {
  120. if (pwVerGot[3] >= pwVerNeed[3])
  121. fOK = TRUE;
  122. }
  123. }
  124. }
  125. return fOK;
  126. }
  127. /****************************************************************************
  128. NAME: OEFileBackedUp - HACK
  129. ****************************************************************************/
  130. BOOL OEFileBackedUp(LPTSTR pszFullPath, int cch)
  131. {
  132. BOOL bFound = FALSE;
  133. HKEY hkeyOE;
  134. TCHAR szINI[MAX_PATH], szTemp[MAX_PATH];
  135. DWORD cb, dwType;
  136. Assert(pszFullPath);
  137. Assert(cch > 0);
  138. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegAdvInfoOE, 0, KEY_READ, &hkeyOE))
  139. {
  140. cb = sizeof(szINI);
  141. if (ERROR_SUCCESS == RegQueryValueEx(hkeyOE, c_szBackupFileName, 0, &dwType, (LPBYTE)szINI, &cb))
  142. {
  143. if (REG_EXPAND_SZ == dwType)
  144. {
  145. ZeroMemory(szTemp, ARRAYSIZE(szTemp));
  146. ExpandEnvironmentStrings(szINI, szTemp, ARRAYSIZE(szTemp));
  147. StrCpyN(szINI, szTemp, ARRAYSIZE(szINI));
  148. // Get ready to change the extension to INI (4 = lstrlen(".DAT"))
  149. cb = lstrlen(szINI)-4;
  150. }
  151. else
  152. // 5 = 4 + 1 (RegQueryValue returns length including NULL)
  153. cb -= 5;
  154. StrCpyN(&szINI[cb], c_szDotINI, ARRAYSIZE(szINI) - cb);
  155. // On Win95, shorten the name
  156. if (VER_PLATFORM_WIN32_WINDOWS == si.osv.dwPlatformId)
  157. GetShortPathName(pszFullPath, pszFullPath, cch);
  158. // See if we can find it
  159. if (1 < GetPrivateProfileString(c_szBackupSection, pszFullPath, c_szEmpty, szTemp, ARRAYSIZE(szTemp), szINI))
  160. {
  161. // We are only interested in the first two characters
  162. szTemp[2] = 0;
  163. if (!lstrcmp(szTemp, c_szBackedup))
  164. bFound = TRUE;
  165. else
  166. AssertSz(!lstrcmp(szTemp, c_szNotBackedup), "SETUP: Advpack back up info has unknown status flag");
  167. }
  168. }
  169. RegCloseKey(hkeyOE);
  170. }
  171. return bFound;
  172. }
  173. /****************************************************************************
  174. NAME: MsgBox
  175. ****************************************************************************/
  176. int MsgBox(HWND hWnd, UINT nMsgID, UINT uIcon, UINT uButtons)
  177. {
  178. TCHAR szMsgBuf[CCHMAX_STRINGRES];
  179. if (!si.fPrompt)
  180. return 0;
  181. LoadString(g_hInstance, nMsgID, szMsgBuf, ARRAYSIZE(szMsgBuf));
  182. LOG("[MSGBOX] ");
  183. LOG2(szMsgBuf);
  184. return(MessageBox(hWnd, szMsgBuf, si.szAppName, uIcon | uButtons | MB_SETFOREGROUND));
  185. }
  186. /*******************************************************************
  187. NAME: ConvertVerToEnum
  188. ********************************************************************/
  189. SETUPVER ConvertVerToEnum(WORD *pwVer)
  190. {
  191. SETUPVER sv;
  192. Assert(pwVer);
  193. switch (pwVer[0])
  194. {
  195. case 0:
  196. sv = VER_NONE;
  197. break;
  198. case 1:
  199. if (0 == pwVer[1])
  200. sv = VER_1_0;
  201. else
  202. sv = VER_1_1;
  203. break;
  204. case 4:
  205. sv = VER_4_0;
  206. break;
  207. case 5:
  208. sv = VER_5_0;
  209. break;
  210. case 6:
  211. sv = VER_6_0;
  212. break;
  213. default:
  214. sv = VER_MAX;
  215. }
  216. return sv;
  217. }
  218. /*******************************************************************
  219. NAME: ConvertStrToVer
  220. ********************************************************************/
  221. void ConvertStrToVer(LPCSTR pszStr, WORD *pwVer)
  222. {
  223. int i;
  224. Assert(pszStr);
  225. Assert(pwVer);
  226. ZeroMemory(pwVer, 4 * sizeof(WORD));
  227. for (i=0; i<4; i++)
  228. {
  229. while (*pszStr && (*pszStr != ',') && (*pszStr != '.'))
  230. {
  231. pwVer[i] *= 10;
  232. pwVer[i] += *pszStr - '0';
  233. pszStr++;
  234. }
  235. if (*pszStr)
  236. pszStr++;
  237. }
  238. return;
  239. }
  240. /*******************************************************************
  241. NAME: GetVers
  242. ********************************************************************/
  243. void GetVers(WORD *pwVerCurr, WORD *pwVerPrev)
  244. {
  245. HKEY hkeyT;
  246. DWORD cb;
  247. CHAR szVer[VERLEN];
  248. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, si.pszVerInfo, 0, KEY_QUERY_VALUE, &hkeyT))
  249. {
  250. if (pwVerCurr)
  251. {
  252. cb = sizeof(szVer);
  253. RegQueryValueExA(hkeyT, c_szRegCurrVer, NULL, NULL, (LPBYTE)szVer, &cb);
  254. ConvertStrToVer(szVer, pwVerCurr);
  255. }
  256. if (pwVerPrev)
  257. {
  258. cb = sizeof(szVer);
  259. RegQueryValueExA(hkeyT, c_szRegPrevVer, NULL, NULL, (LPBYTE)szVer, &cb);
  260. ConvertStrToVer(szVer, pwVerPrev);
  261. }
  262. RegCloseKey(hkeyT);
  263. }
  264. }
  265. /*******************************************************************
  266. NAME: GetVerInfo
  267. ********************************************************************/
  268. void GetVerInfo(SETUPVER *psvCurr, SETUPVER *psvPrev)
  269. {
  270. WORD wVerCurr[4];
  271. WORD wVerPrev[4];
  272. GetVers(wVerCurr, wVerPrev);
  273. if (psvCurr)
  274. *psvCurr = ConvertVerToEnum(wVerCurr);
  275. if (psvPrev)
  276. *psvPrev = ConvertVerToEnum(wVerPrev);
  277. }
  278. /*******************************************************************
  279. NAME: InterimBuild
  280. ********************************************************************/
  281. BOOL InterimBuild(SETUPVER *psv)
  282. {
  283. HKEY hkeyT;
  284. DWORD cb;
  285. BOOL fInterim = FALSE;
  286. Assert(psv);
  287. ZeroMemory(psv, sizeof(SETUPVER));
  288. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, si.pszVerInfo, 0, KEY_QUERY_VALUE, &hkeyT))
  289. {
  290. cb = sizeof(SETUPVER);
  291. fInterim = (ERROR_SUCCESS == RegQueryValueExA(hkeyT, c_szRegInterimVer, NULL, NULL, (LPBYTE)psv, &cb));
  292. RegCloseKey(hkeyT);
  293. }
  294. return fInterim;
  295. }
  296. /*******************************************************************
  297. NAME: GetASetupVer
  298. ********************************************************************/
  299. BOOL GetASetupVer(LPCTSTR pszGUID, WORD *pwVer, LPTSTR pszVer, int cch)
  300. {
  301. HKEY hkey;
  302. TCHAR szPath[MAX_PATH], szVer[64];
  303. BOOL fInstalled = FALSE;
  304. DWORD dwValue, cb;
  305. Assert(pszGUID);
  306. if (pszVer)
  307. pszVer[0] = 0;
  308. if (pwVer)
  309. ZeroMemory(pwVer, 4 * sizeof(WORD));
  310. wnsprintf(szPath, ARRAYSIZE(szPath), c_szPathFileFmt, c_szRegASetup, pszGUID);
  311. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szPath, 0, KEY_QUERY_VALUE, &hkey))
  312. {
  313. cb = sizeof(dwValue);
  314. if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szIsInstalled, 0, NULL, (LPBYTE)&dwValue, &cb))
  315. {
  316. if (1 == dwValue)
  317. {
  318. cb = sizeof(szVer);
  319. if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szValueVersion, 0, NULL, (LPBYTE)szVer, &cb))
  320. {
  321. if (pwVer)
  322. ConvertStrToVer(szVer, pwVer);
  323. if (pszVer)
  324. StrCpyN(pszVer, szVer, cch);
  325. fInstalled = TRUE;
  326. }
  327. }
  328. }
  329. RegCloseKey(hkey);
  330. }
  331. return fInstalled;
  332. }
  333. /*******************************************************************
  334. NAME: GetFileVer
  335. ********************************************************************/
  336. HRESULT GetFileVer(LPCTSTR pszExePath, LPTSTR pszVer, DWORD cch)
  337. {
  338. DWORD dwVerInfoSize, dwVerHnd;
  339. HRESULT hr = S_OK;
  340. LPSTR pszInfo = NULL;
  341. LPSTR pszVersion;
  342. LPWORD pwTrans;
  343. TCHAR szGet[MAX_PATH];
  344. UINT uLen;
  345. // Validate Parameters
  346. Assert(pszExePath);
  347. Assert(pszVer);
  348. Assert(cch);
  349. // Validate global state
  350. Assert(g_pMalloc);
  351. // Initialize out parameters
  352. pszVer[0] = TEXT('\0');
  353. // Allocate space for version info block
  354. if (0 == (dwVerInfoSize = GetFileVersionInfoSize(const_cast<LPTSTR> (pszExePath), &dwVerHnd)))
  355. {
  356. hr = E_FAIL;
  357. TraceResult(hr);
  358. goto exit;
  359. }
  360. IF_NULLEXIT(pszInfo = (LPTSTR)g_pMalloc->Alloc(dwVerInfoSize));
  361. ZeroMemory(pszInfo, dwVerInfoSize);
  362. // Get Version info block
  363. IF_FALSEEXIT(GetFileVersionInfo(const_cast<LPTSTR> (pszExePath), dwVerHnd, dwVerInfoSize, pszInfo), E_FAIL);
  364. // Figure out language for version info
  365. IF_FALSEEXIT(VerQueryValue(pszInfo, "\\VarFileInfo\\Translation", (LPVOID *)&pwTrans, &uLen) && uLen >= (2 * sizeof(WORD)), E_FAIL);
  366. // Set up buffer with correct language and get version
  367. wnsprintf(szGet, ARRAYSIZE(szGet), "\\StringFileInfo\\%04X%04X\\FileVersion", pwTrans[0], pwTrans[1]);
  368. IF_FALSEEXIT(VerQueryValue(pszInfo, szGet, (LPVOID *)&pszVersion, &uLen) && uLen, E_FAIL);
  369. // Copy version out of version block, into out param
  370. Assert(pszVersion);
  371. StrCpyN(pszVer, pszVersion, cch);
  372. exit:
  373. if (pszInfo)
  374. g_pMalloc->Free(pszInfo);
  375. return hr;
  376. }
  377. /*******************************************************************
  378. NAME: GetExeVer
  379. ********************************************************************/
  380. HRESULT GetExeVer(LPCTSTR pszExeName, WORD *pwVer, LPTSTR pszVer, int cch)
  381. {
  382. HRESULT hr = S_OK;
  383. TCHAR szPath[MAX_PATH];
  384. TCHAR szVer[64];
  385. // Validate params
  386. Assert(pszExeName);
  387. // Initialize out params
  388. if (pszVer)
  389. {
  390. Assert(cch);
  391. pszVer[0] = 0;
  392. }
  393. if (pwVer)
  394. // Version is an array of 4 words
  395. ZeroMemory(pwVer, 4 * sizeof(WORD));
  396. // Find the exe
  397. IF_FALSEEXIT(GetExePath(pszExeName, szPath, ARRAYSIZE(szPath), FALSE), E_FAIL);
  398. // Get the string representation of the version
  399. IF_FAILEXIT(hr = GetFileVer(szPath, szVer, ARRAYSIZE(szVer)));
  400. // Fill in out params
  401. if (pwVer)
  402. ConvertStrToVer(szVer, pwVer);
  403. if (pszVer)
  404. StrCpyN(pszVer, szVer, cch);
  405. exit:
  406. return hr;
  407. }
  408. /****************************************************************************
  409. NAME: IsNTAdmin
  410. ****************************************************************************/
  411. BOOL IsNTAdmin(void)
  412. {
  413. static int fIsAdmin = 2;
  414. HANDLE hAccessToken;
  415. PTOKEN_GROUPS ptgGroups;
  416. DWORD dwReqSize;
  417. UINT i;
  418. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  419. PSID AdministratorsGroup;
  420. BOOL bRet;
  421. //
  422. // If we have cached a value, return the cached value. Note I never
  423. // set the cached value to false as I want to retry each time in
  424. // case a previous failure was just a temp. problem (ie net access down)
  425. //
  426. bRet = FALSE;
  427. ptgGroups = NULL;
  428. if( fIsAdmin != 2 )
  429. return (BOOL)fIsAdmin;
  430. if (si.osv.dwPlatformId != VER_PLATFORM_WIN32_NT)
  431. {
  432. fIsAdmin = TRUE; // If we are not running under NT return TRUE.
  433. return (BOOL)fIsAdmin;
  434. }
  435. if(!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hAccessToken ) )
  436. return FALSE;
  437. // See how big of a buffer we need for the token information
  438. if(!GetTokenInformation( hAccessToken, TokenGroups, NULL, 0, &dwReqSize))
  439. {
  440. // GetTokenInfo should the buffer size we need - Alloc a buffer
  441. if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  442. MemAlloc((void **)&ptgGroups, dwReqSize);
  443. }
  444. // ptgGroups could be NULL for a coupla reasons here:
  445. // 1. The alloc above failed
  446. // 2. GetTokenInformation actually managed to succeed the first time (possible?)
  447. // 3. GetTokenInfo failed for a reason other than insufficient buffer
  448. // Any of these seem justification for bailing.
  449. // So, make sure it isn't null, then get the token info
  450. if(ptgGroups && GetTokenInformation(hAccessToken, TokenGroups, ptgGroups, dwReqSize, &dwReqSize))
  451. {
  452. if(AllocateAndInitializeSid( &NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
  453. DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup) )
  454. {
  455. // Search thru all the groups this process belongs to looking for the
  456. // Admistrators Group.
  457. for( i=0; i < ptgGroups->GroupCount; i++ )
  458. {
  459. if( EqualSid(ptgGroups->Groups[i].Sid, AdministratorsGroup) )
  460. {
  461. // Yea! This guy looks like an admin
  462. fIsAdmin = TRUE;
  463. bRet = TRUE;
  464. break;
  465. }
  466. }
  467. FreeSid(AdministratorsGroup);
  468. }
  469. }
  470. // BUGBUG: Close handle here? doc's aren't clear whether this is needed.
  471. CloseHandle(hAccessToken);
  472. if(ptgGroups)
  473. MemFree(ptgGroups);
  474. return bRet;
  475. }
  476. const LPCTSTR c_rgszExes[] = { c_szMainExe };
  477. /****************************************************************************
  478. NAME: RegisterExes
  479. ****************************************************************************/
  480. void RegisterExes(BOOL fReg)
  481. {
  482. int i;
  483. STARTUPINFO sti;
  484. DWORD dw,cb;
  485. PROCESS_INFORMATION pi;
  486. TCHAR szPath[MAX_PATH], szUnreg[MAX_PATH + 32], szExpanded[MAX_PATH];
  487. LPTSTR pszPath;
  488. HKEY hkey;
  489. LOG("Reg/Unreg Exes: ");
  490. // Use InstallRoot as directory
  491. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegFlat, 0, KEY_QUERY_VALUE, &hkey))
  492. {
  493. cb = sizeof(szPath);
  494. if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szInstallRoot, 0, &dw, (LPBYTE)szPath, &cb))
  495. {
  496. if (REG_EXPAND_SZ == dw)
  497. {
  498. ZeroMemory(szExpanded, ARRAYSIZE(szExpanded));
  499. ExpandEnvironmentStrings(szPath, szExpanded, ARRAYSIZE(szExpanded));
  500. pszPath = szExpanded;
  501. }
  502. else
  503. pszPath = szPath;
  504. for (i = 0; i < ARRAYSIZE(c_rgszExes); i++)
  505. {
  506. wnsprintf(szUnreg, ARRAYSIZE(szUnreg), fReg ? c_szRegFmt : c_szUnregFmt, pszPath, c_rgszExes[i]);
  507. ZeroMemory(&sti, sizeof(STARTUPINFO));
  508. sti.cb = sizeof(STARTUPINFO);
  509. LOG2(szUnreg);
  510. if (CreateProcess(NULL, szUnreg, NULL, NULL, FALSE, 0, NULL, NULL, &sti, &pi))
  511. {
  512. WaitForSingleObject(pi.hProcess, INFINITE);
  513. GetExitCodeProcess(pi.hProcess, &dw);
  514. CloseHandle(pi.hThread);
  515. CloseHandle(pi.hProcess);
  516. }
  517. }
  518. }
  519. RegCloseKey(hkey);
  520. }
  521. }
  522. #ifdef SETUP_LOG
  523. /****************************************************************************
  524. NAME: OpenLogFile
  525. ****************************************************************************/
  526. void OpenLogFile()
  527. {
  528. TCHAR szPath[MAX_PATH];
  529. BOOL fOK = FALSE;
  530. DWORD cb;
  531. SYSTEMTIME systime;
  532. // On Term server, this will be stored in user's windows dir - this is fine.
  533. cb = GetWindowsDirectory(szPath, ARRAYSIZE(szPath));
  534. if (*CharPrev(szPath, szPath+cb) != '\\')
  535. szPath[cb++] = '\\';
  536. StrCpyN(&szPath[cb], c_szFileLog, ARRAYSIZE(szPath)-cb);
  537. si.hLogFile = CreateFile(szPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
  538. FILE_FLAG_SEQUENTIAL_SCAN | FILE_ATTRIBUTE_NORMAL, NULL);
  539. if (INVALID_HANDLE_VALUE == si.hLogFile)
  540. return;
  541. cb = GetFileSize(si.hLogFile, NULL);
  542. if (0xFFFFFFFF == cb)
  543. cb = 0;
  544. // If file is getting kind of large
  545. if (cb >= 102400)
  546. {
  547. // Seek to the end of the file...
  548. SetFilePointer(si.hLogFile, 0, NULL, FILE_BEGIN);
  549. // Set End Of File
  550. SetEndOfFile(si.hLogFile);
  551. }
  552. // Seek to the end of the file...
  553. SetFilePointer(si.hLogFile, 0, NULL, FILE_END);
  554. GetLocalTime(&systime);
  555. wnsprintf(szLogBuffer, ARRAYSIZE(szLogBuffer), "\r\n\r\n-----[START]: OE / WAB Setup 5.0 started on %02d/%02d/%04d at %02d:%02d\r\n",
  556. systime.wMonth, systime.wDay, systime.wYear, systime.wHour, systime.wMinute);
  557. LogMessage(szLogBuffer, TRUE);
  558. }
  559. /****************************************************************************
  560. NAME: CloseLogFile
  561. ****************************************************************************/
  562. void CloseLogFile()
  563. {
  564. if (INVALID_HANDLE_VALUE != si.hLogFile)
  565. {
  566. LogMessage("\r\n-----[END]", TRUE);
  567. CloseHandle(si.hLogFile);
  568. }
  569. }
  570. /****************************************************************************
  571. NAME: LogMessage
  572. ****************************************************************************/
  573. void LogMessage(LPSTR pszMsg, BOOL fNewLine)
  574. {
  575. if (INVALID_HANDLE_VALUE != si.hLogFile)
  576. {
  577. DWORD cb;
  578. CHAR szBuffer[256];
  579. if (fNewLine)
  580. {
  581. szBuffer[0] = '\r';
  582. szBuffer[1] = '\n';
  583. cb = 2;
  584. }
  585. else
  586. cb = 0;
  587. StrCpyN(&szBuffer[cb], pszMsg, ARRAYSIZE(szBuffer)-cb);
  588. WriteFile(si.hLogFile, (LPCVOID)szBuffer, lstrlen(szBuffer)+1, &cb, NULL);
  589. }
  590. }
  591. /****************************************************************************
  592. NAME: LogRegistryKey
  593. ****************************************************************************/
  594. void LogRegistryKey(HKEY hkeyMain, LPTSTR pszSub)
  595. {
  596. if (INVALID_HANDLE_VALUE != si.hLogFile)
  597. {
  598. LogMessage("Registry Dump: ", TRUE);
  599. if (HKEY_LOCAL_MACHINE == hkeyMain)
  600. LogMessage("HKLM, ", FALSE);
  601. else if (HKEY_CURRENT_USER == hkeyMain)
  602. LogMessage("HKCU, ", FALSE);
  603. else if (HKEY_CLASSES_ROOT == hkeyMain)
  604. LogMessage("HKCR, ", FALSE);
  605. else
  606. LogMessage("????, ", FALSE);
  607. LogMessage(pszSub, TRUE);
  608. }
  609. }
  610. /****************************************************************************
  611. NAME: LogRegistry
  612. ****************************************************************************/
  613. void LogRegistry(HKEY hkeyMain, LPTSTR pszSub)
  614. {
  615. if (INVALID_HANDLE_VALUE != si.hLogFile)
  616. {
  617. DWORD i;
  618. HKEY hkey;
  619. LONG lStatus;
  620. DWORD dwClassLength=0;
  621. DWORD dwSubKeys;
  622. DWORD dwMaxSubKey;
  623. DWORD dwMaxClass;
  624. DWORD dwValues;
  625. DWORD dwMaxValueName;
  626. DWORD dwMaxValueData;
  627. DWORD dwSecurityLength;
  628. FILETIME ftLastWrite;
  629. LPTSTR szNameBuffer;
  630. //
  631. // First open the given key so we can enumerate its subkeys
  632. //
  633. if (ERROR_SUCCESS != RegOpenKeyEx(hkeyMain, pszSub, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hkey))
  634. {
  635. LogRegistryKey(hkeyMain, pszSub);
  636. }
  637. //
  638. // Use RegQueryInfoKey to determine how big to allocate the buffer
  639. // for the subkey names.
  640. //
  641. if (ERROR_SUCCESS != RegQueryInfoKey(hkey, NULL, &dwClassLength, 0, &dwSubKeys, &dwMaxSubKey, &dwMaxClass, &dwValues,
  642. &dwMaxValueName, &dwMaxValueData, &dwSecurityLength, &ftLastWrite))
  643. {
  644. RegCloseKey(hkey);
  645. return;
  646. }
  647. if (!MemAlloc((void **)&szNameBuffer, sizeof(TCHAR) * (dwMaxSubKey + 1)))
  648. {
  649. RegCloseKey(hkey);
  650. return;
  651. }
  652. //
  653. // Enumerate subkeys and apply ourselves to each one.
  654. //
  655. i = 0;
  656. do {
  657. if (ERROR_SUCCESS == (lStatus = RegEnumKey(hkey, i, szNameBuffer, dwMaxSubKey+1)))
  658. LogRegistry(hkey, szNameBuffer);
  659. else
  660. ++i;
  661. } while ( (lStatus != ERROR_NO_MORE_ITEMS) && (i < dwSubKeys) );
  662. MemFree(szNameBuffer);
  663. RegCloseKey(hkey);
  664. LogRegistryKey(hkey, pszSub);
  665. }
  666. }
  667. #endif