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.

694 lines
16 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: errlog.cpp
  8. //
  9. // Contents: generic error logging
  10. //
  11. // History: 19-Jun-00 reidk created
  12. //
  13. //--------------------------------------------------------------------------
  14. #include <windows.h>
  15. #include <string.h>
  16. #include "errlog.h"
  17. #include "unicode.h"
  18. #define WSZ_ERROR_LOGFILE L"%SystemRoot%\\System32\\CatRoot2\\dberr.txt"
  19. #define REG_CRYPTOGRAPHY_KEY L"Software\\Microsoft\\Cryptography"
  20. #define REG_CATDB_LOGGING_VALUE L"CatDBLogging"
  21. #define CATDB_LOG_ERRORS_TO_FILE 0x00000001
  22. #define CATDB_LOG_ERRORS_TO_DEBUGGER 0x00000002
  23. #define CATDB_LOG_WARNINGS 0x00000004
  24. #define MAX_LOGFILE_SIZE 100000
  25. #define TIME_DATE_SIZE 256
  26. BOOL g_fErrLogInitialized = FALSE;
  27. BOOL g_fLogErrorsToFile = TRUE;
  28. BOOL g_fLogErrorsToDebugger = FALSE;
  29. BOOL g_fLogWarnings = FALSE;
  30. #define WSZ_TIME_STAMP_FILE L"TimeStamp"
  31. #define TIME_ALLOWANCE ((ULONGLONG) 10000000 * (ULONGLONG) 60 * (ULONGLONG) 5) // 5 minutes
  32. #define TIMESTAMP_LOGERR_LASTERR() ErrLog_LogError(NULL, \
  33. ERRLOG_CLIENT_ID_TIMESTAMP, \
  34. __LINE__, \
  35. 0, \
  36. FALSE, \
  37. FALSE);
  38. #define NAME_VALUE_SIZE 28
  39. void
  40. ErrLog_Initialize()
  41. {
  42. HKEY hKey;
  43. DWORD dwDisposition;
  44. WCHAR wszValueName[NAME_VALUE_SIZE];
  45. DWORD dwValueNameSize = NAME_VALUE_SIZE;
  46. DWORD dwType;
  47. DWORD dwValue;
  48. DWORD dwValueSize = sizeof(DWORD);
  49. DWORD dwIndex;
  50. LONG lRet;
  51. g_fErrLogInitialized = TRUE;
  52. //
  53. // See if there is a CatDBLogging value
  54. //
  55. if (RegCreateKeyExU(
  56. HKEY_LOCAL_MACHINE,
  57. REG_CRYPTOGRAPHY_KEY,
  58. 0,
  59. NULL,
  60. REG_OPTION_NON_VOLATILE,
  61. KEY_READ,
  62. NULL,
  63. &hKey,
  64. &dwDisposition) == ERROR_SUCCESS)
  65. {
  66. dwIndex = 0;
  67. lRet = RegEnumValueU(
  68. hKey,
  69. dwIndex,
  70. wszValueName,
  71. &dwValueNameSize,
  72. NULL,
  73. &dwType,
  74. (BYTE *) &dwValue,
  75. &dwValueSize);
  76. while ((lRet == ERROR_SUCCESS) || (lRet == ERROR_MORE_DATA))
  77. {
  78. if ((lRet == ERROR_SUCCESS) &&
  79. (dwType == REG_DWORD) &&
  80. (_wcsicmp(wszValueName, REG_CATDB_LOGGING_VALUE) == 0))
  81. {
  82. g_fLogErrorsToFile = (dwValue & CATDB_LOG_ERRORS_TO_FILE) != 0;
  83. g_fLogErrorsToDebugger = (dwValue & CATDB_LOG_ERRORS_TO_DEBUGGER) != 0;
  84. g_fLogWarnings = (dwValue & CATDB_LOG_WARNINGS) != 0;
  85. break;
  86. }
  87. else
  88. {
  89. dwValueNameSize = NAME_VALUE_SIZE;
  90. dwValueSize = sizeof(DWORD);
  91. dwIndex++;
  92. lRet = RegEnumValueU(
  93. hKey,
  94. dwIndex,
  95. wszValueName,
  96. &dwValueNameSize,
  97. NULL,
  98. &dwType,
  99. (BYTE *) &dwValue,
  100. &dwValueSize);
  101. }
  102. }
  103. RegCloseKey(hKey);
  104. }
  105. }
  106. void
  107. _WriteErrorOut(
  108. LPWSTR pwszLogFileName,
  109. LPSTR pwszError,
  110. BOOL fLogToFileOnly)
  111. {
  112. LPWSTR pwszFileNameToExpand = pwszLogFileName;
  113. LPWSTR pwszExpandedFileName = NULL;
  114. DWORD dwExpanded = 0;
  115. HANDLE hFile = INVALID_HANDLE_VALUE;
  116. DWORD dwFileSize = 0;
  117. DWORD dwNumBytesWritten = 0;
  118. //
  119. // Output the error string to the debugger
  120. //
  121. if (g_fLogErrorsToDebugger && !fLogToFileOnly)
  122. {
  123. OutputDebugStringA(pwszError);
  124. }
  125. //
  126. // Log string to file
  127. //
  128. if (g_fLogErrorsToFile)
  129. {
  130. if (pwszFileNameToExpand == NULL)
  131. {
  132. pwszFileNameToExpand = WSZ_ERROR_LOGFILE;
  133. }
  134. //
  135. // expand the filename if needed
  136. //
  137. dwExpanded = ExpandEnvironmentStringsU(pwszFileNameToExpand, NULL, 0);
  138. pwszExpandedFileName = (LPWSTR) malloc(dwExpanded * sizeof(WCHAR));
  139. if (pwszExpandedFileName == NULL)
  140. {
  141. goto Return;
  142. }
  143. if (0 == ExpandEnvironmentStringsU(
  144. pwszFileNameToExpand,
  145. pwszExpandedFileName,
  146. dwExpanded))
  147. {
  148. goto Return;
  149. }
  150. //
  151. // Get a handle to the file and make sure it isn't took big
  152. //
  153. hFile = CreateFileU(
  154. pwszExpandedFileName,
  155. GENERIC_READ | GENERIC_WRITE,
  156. 0, //dwShareMode
  157. NULL,
  158. OPEN_ALWAYS,
  159. FILE_ATTRIBUTE_NORMAL,
  160. NULL);
  161. if (hFile == INVALID_HANDLE_VALUE)
  162. {
  163. goto Return;
  164. }
  165. dwFileSize = GetFileSize(hFile, NULL);
  166. if (dwFileSize >= MAX_LOGFILE_SIZE)
  167. {
  168. //
  169. // Just nuke the whole thing
  170. //
  171. if (SetFilePointer(
  172. hFile,
  173. 0,
  174. NULL,
  175. FILE_BEGIN) == INVALID_SET_FILE_POINTER)
  176. {
  177. goto Return;
  178. }
  179. if (!SetEndOfFile(hFile))
  180. {
  181. goto Return;
  182. }
  183. }
  184. //
  185. // Write the new error
  186. //
  187. if (SetFilePointer(hFile, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)
  188. {
  189. goto Return;
  190. }
  191. WriteFile(
  192. hFile,
  193. (void *) pwszError,
  194. strlen(pwszError),
  195. &dwNumBytesWritten,
  196. NULL);
  197. }
  198. Return:
  199. if (pwszExpandedFileName != NULL)
  200. {
  201. free(pwszExpandedFileName);
  202. }
  203. if (hFile != INVALID_HANDLE_VALUE)
  204. {
  205. CloseHandle(hFile);
  206. }
  207. }
  208. void
  209. ErrLog_LogError(
  210. LPWSTR pwszLogFileName,
  211. DWORD dwClient,
  212. DWORD dwLine,
  213. DWORD dwErr,
  214. BOOL fWarning,
  215. BOOL fLogToFileOnly)
  216. {
  217. DWORD dwLastError = GetLastError();
  218. int numChars = 0;
  219. char szTimeDate[TIME_DATE_SIZE];
  220. char szWriteBuffer[512];
  221. SYSTEMTIME st;
  222. if (!g_fErrLogInitialized)
  223. {
  224. ErrLog_Initialize();
  225. }
  226. //
  227. // Get out if this is a warning and we are not logging warnings
  228. //
  229. if (!g_fLogWarnings && fWarning)
  230. {
  231. return;
  232. }
  233. //
  234. // Create the error string to log
  235. //
  236. GetLocalTime(&st);
  237. numChars = GetTimeFormatA(
  238. LOCALE_USER_DEFAULT,
  239. 0,
  240. &st,
  241. NULL,
  242. szTimeDate,
  243. TIME_DATE_SIZE);
  244. szTimeDate[numChars-1] = ' ';
  245. GetDateFormatA(
  246. LOCALE_USER_DEFAULT,
  247. DATE_SHORTDATE,
  248. &st,
  249. NULL,
  250. &szTimeDate[numChars],
  251. TIME_DATE_SIZE-numChars);
  252. wsprintf(
  253. szWriteBuffer,
  254. "CatalogDB: %s: File #%u at line #%u encountered error 0x%.8lx\r\n",
  255. szTimeDate,
  256. dwClient,
  257. dwLine,
  258. (dwErr == 0) ? dwLastError : dwErr);
  259. //
  260. // Log it
  261. //
  262. _WriteErrorOut(pwszLogFileName, szWriteBuffer, fLogToFileOnly);
  263. //
  264. // Make sure last error is the same as when we were called
  265. //
  266. SetLastError(dwLastError);
  267. }
  268. void
  269. ErrLog_LogString(
  270. LPWSTR pwszLogFileName,
  271. LPWSTR pwszMessageString,
  272. LPWSTR pwszExtraString,
  273. BOOL fLogToFileOnly)
  274. {
  275. DWORD dwLastError = GetLastError();
  276. int numChars = 0;
  277. char szTimeDate[TIME_DATE_SIZE];
  278. SYSTEMTIME st;
  279. char szWriteBuffer[1024];
  280. if (!g_fErrLogInitialized)
  281. {
  282. ErrLog_Initialize();
  283. }
  284. //
  285. // Create the error string to log
  286. //
  287. GetLocalTime(&st);
  288. numChars = GetTimeFormatA(
  289. LOCALE_USER_DEFAULT,
  290. 0,
  291. &st,
  292. NULL,
  293. szTimeDate,
  294. TIME_DATE_SIZE);
  295. szTimeDate[numChars-1] = ' ';
  296. GetDateFormatA(
  297. LOCALE_USER_DEFAULT,
  298. DATE_SHORTDATE,
  299. &st,
  300. NULL,
  301. &szTimeDate[numChars],
  302. TIME_DATE_SIZE-numChars);
  303. if (pwszExtraString != NULL)
  304. {
  305. wsprintf(
  306. szWriteBuffer,
  307. "CatalogDB: %s: %S %S\r\n",
  308. szTimeDate,
  309. pwszMessageString,
  310. pwszExtraString);
  311. }
  312. else
  313. {
  314. wsprintf(
  315. szWriteBuffer,
  316. "CatalogDB: %s: %S\r\n",
  317. szTimeDate,
  318. pwszMessageString);
  319. }
  320. //
  321. // Log it
  322. //
  323. _WriteErrorOut(pwszLogFileName, szWriteBuffer, fLogToFileOnly);
  324. //
  325. // Make sure last error is the same as when we were called
  326. //
  327. SetLastError(dwLastError);
  328. }
  329. BOOL
  330. TimeStampFile_Touch(
  331. LPWSTR pwszDir)
  332. {
  333. BOOL fRet = TRUE;
  334. LPWSTR pwszFile = NULL;
  335. HANDLE hFile = INVALID_HANDLE_VALUE;
  336. DWORD dwNumBytesWritten = 0;
  337. SYSTEMTIME st;
  338. FILETIME ft;
  339. DWORD dwErr;
  340. //
  341. // Create fully qaulified file name
  342. //
  343. if (NULL == (pwszFile = (LPWSTR) malloc((
  344. wcslen(pwszDir) +
  345. wcslen(WSZ_TIME_STAMP_FILE)
  346. + 2) * sizeof(WCHAR))))
  347. {
  348. SetLastError(E_OUTOFMEMORY);
  349. TIMESTAMP_LOGERR_LASTERR()
  350. goto ErrorReturn;
  351. }
  352. wcscpy(pwszFile, pwszDir);
  353. if (pwszFile[wcslen(pwszFile)-1] != L'\\')
  354. {
  355. wcscat(pwszFile, L"\\");
  356. }
  357. wcscat(pwszFile, WSZ_TIME_STAMP_FILE);
  358. //
  359. // Get a handle to the file
  360. //
  361. hFile = CreateFileU(
  362. pwszFile,
  363. GENERIC_READ | GENERIC_WRITE,
  364. 0, //dwShareMode
  365. NULL,
  366. OPEN_ALWAYS,
  367. FILE_ATTRIBUTE_NORMAL,
  368. NULL);
  369. if (hFile == INVALID_HANDLE_VALUE)
  370. {
  371. TIMESTAMP_LOGERR_LASTERR()
  372. goto ErrorReturn;
  373. }
  374. SetLastError(0);
  375. //
  376. // Get the current time
  377. //
  378. GetLocalTime(&st);
  379. if (!SystemTimeToFileTime(&st, &ft))
  380. {
  381. TIMESTAMP_LOGERR_LASTERR()
  382. goto ErrorReturn;
  383. }
  384. //
  385. // Write the time
  386. //
  387. if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
  388. {
  389. TIMESTAMP_LOGERR_LASTERR()
  390. goto ErrorReturn;
  391. }
  392. if (!SetEndOfFile(hFile))
  393. {
  394. TIMESTAMP_LOGERR_LASTERR()
  395. goto ErrorReturn;
  396. }
  397. if (!WriteFile(
  398. hFile,
  399. (void *) &ft,
  400. sizeof(ft),
  401. &dwNumBytesWritten,
  402. NULL))
  403. {
  404. TIMESTAMP_LOGERR_LASTERR()
  405. goto ErrorReturn;
  406. }
  407. CommonReturn:
  408. if (hFile != INVALID_HANDLE_VALUE)
  409. {
  410. CloseHandle(hFile);
  411. }
  412. if (pwszFile != NULL)
  413. {
  414. free(pwszFile);
  415. }
  416. return (fRet);
  417. ErrorReturn:
  418. dwErr = GetLastError();
  419. if (pwszFile != NULL)
  420. {
  421. DeleteFileW(pwszFile);
  422. }
  423. SetLastError(dwErr);
  424. fRet = FALSE;
  425. goto CommonReturn;
  426. }
  427. BOOL
  428. TimeStampFile_InSync(
  429. LPWSTR pwszDir1,
  430. LPWSTR pwszDir2,
  431. BOOL *pfInSync)
  432. {
  433. BOOL fRet = TRUE;
  434. LPWSTR pwszFile1 = NULL;
  435. HANDLE hFile1 = INVALID_HANDLE_VALUE;
  436. LPWSTR pwszFile2 = NULL;
  437. HANDLE hFile2 = INVALID_HANDLE_VALUE;
  438. DWORD dwNumBytesRead;
  439. FILETIME ft1;
  440. FILETIME ft2;
  441. ULARGE_INTEGER ul1;
  442. ULARGE_INTEGER ul2;
  443. //
  444. // Initialize out param
  445. //
  446. *pfInSync = FALSE;
  447. //
  448. // Create fully qaulified file names
  449. //
  450. if (NULL == (pwszFile1 = (LPWSTR) malloc((
  451. wcslen(pwszDir1) +
  452. wcslen(WSZ_TIME_STAMP_FILE)
  453. + 2) * sizeof(WCHAR))))
  454. {
  455. SetLastError(E_OUTOFMEMORY);
  456. TIMESTAMP_LOGERR_LASTERR()
  457. goto ErrorReturn;
  458. }
  459. wcscpy(pwszFile1, pwszDir1);
  460. if (pwszFile1[wcslen(pwszFile1)-1] != L'\\')
  461. {
  462. wcscat(pwszFile1, L"\\");
  463. }
  464. wcscat(pwszFile1, WSZ_TIME_STAMP_FILE);
  465. if (NULL == (pwszFile2 = (LPWSTR) malloc((
  466. wcslen(pwszDir2) +
  467. wcslen(WSZ_TIME_STAMP_FILE)
  468. + 2) * sizeof(WCHAR))))
  469. {
  470. SetLastError(E_OUTOFMEMORY);
  471. TIMESTAMP_LOGERR_LASTERR()
  472. goto ErrorReturn;
  473. }
  474. wcscpy(pwszFile2, pwszDir2);
  475. if (pwszFile2[wcslen(pwszFile2)-1] != L'\\')
  476. {
  477. wcscat(pwszFile2, L"\\");
  478. }
  479. wcscat(pwszFile2, WSZ_TIME_STAMP_FILE);
  480. //
  481. // Get handles to the files
  482. //
  483. hFile1 = CreateFileU(
  484. pwszFile1,
  485. GENERIC_READ,
  486. FILE_SHARE_READ | FILE_SHARE_WRITE,
  487. NULL,
  488. OPEN_EXISTING,
  489. FILE_ATTRIBUTE_NORMAL,
  490. NULL);
  491. if (hFile1 == INVALID_HANDLE_VALUE)
  492. {
  493. if (GetLastError() == ERROR_FILE_NOT_FOUND)
  494. {
  495. SetLastError(0);
  496. goto CommonReturn; // not an error, a legitimate out of sync
  497. }
  498. else
  499. {
  500. TIMESTAMP_LOGERR_LASTERR()
  501. goto ErrorReturn;
  502. }
  503. }
  504. if (SetFilePointer(hFile1, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
  505. {
  506. TIMESTAMP_LOGERR_LASTERR()
  507. goto ErrorReturn;
  508. }
  509. hFile2 = CreateFileU(
  510. pwszFile2,
  511. GENERIC_READ,
  512. FILE_SHARE_READ | FILE_SHARE_WRITE,
  513. NULL,
  514. OPEN_EXISTING,
  515. FILE_ATTRIBUTE_NORMAL,
  516. NULL);
  517. if (hFile2 == INVALID_HANDLE_VALUE)
  518. {
  519. if (GetLastError() == ERROR_FILE_NOT_FOUND)
  520. {
  521. SetLastError(0);
  522. goto CommonReturn; // not an error, a legitimate out of sync
  523. }
  524. else
  525. {
  526. TIMESTAMP_LOGERR_LASTERR()
  527. goto ErrorReturn;
  528. }
  529. }
  530. if (SetFilePointer(hFile2, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
  531. {
  532. TIMESTAMP_LOGERR_LASTERR()
  533. goto ErrorReturn;
  534. }
  535. //
  536. // Get the times out of the files
  537. //
  538. if (!ReadFile(
  539. hFile1,
  540. &ft1,
  541. sizeof(ft1),
  542. &dwNumBytesRead,
  543. NULL))
  544. {
  545. TIMESTAMP_LOGERR_LASTERR()
  546. goto ErrorReturn;
  547. }
  548. if (dwNumBytesRead != sizeof(ft1))
  549. {
  550. TIMESTAMP_LOGERR_LASTERR()
  551. goto ErrorReturn;
  552. }
  553. if (!ReadFile(
  554. hFile2,
  555. &ft2,
  556. sizeof(ft2),
  557. &dwNumBytesRead,
  558. NULL))
  559. {
  560. TIMESTAMP_LOGERR_LASTERR()
  561. goto ErrorReturn;
  562. }
  563. if (dwNumBytesRead != sizeof(ft2))
  564. {
  565. TIMESTAMP_LOGERR_LASTERR()
  566. goto ErrorReturn;
  567. }
  568. memcpy(&ul1, &ft1, sizeof(ft1));
  569. memcpy(&ul2, &ft2, sizeof(ft2));
  570. if ((ul1.QuadPart <= (ul2.QuadPart + TIME_ALLOWANCE)) &&
  571. (ul2.QuadPart <= (ul1.QuadPart + TIME_ALLOWANCE)))
  572. {
  573. *pfInSync = TRUE;
  574. }
  575. CommonReturn:
  576. if (hFile1 != INVALID_HANDLE_VALUE)
  577. {
  578. CloseHandle(hFile1);
  579. }
  580. if (pwszFile1 != NULL)
  581. {
  582. free(pwszFile1);
  583. }
  584. if (hFile2 != INVALID_HANDLE_VALUE)
  585. {
  586. CloseHandle(hFile2);
  587. }
  588. if (pwszFile2 != NULL)
  589. {
  590. free(pwszFile2);
  591. }
  592. return (fRet);
  593. ErrorReturn:
  594. fRet = FALSE;
  595. goto CommonReturn;
  596. }