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.

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