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.

2795 lines
72 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. debug.c
  5. Abstract:
  6. This routine reads input from STDIN and initializes the debug structure.
  7. It reads a list of subsystems to debug and a severity level.
  8. Author:
  9. Billy Fuller
  10. Environment
  11. User mode, winnt32
  12. */
  13. #include <ntreppch.h>
  14. #pragma hdrstop
  15. #include "debug.h"
  16. // #include <imagehlp.h>
  17. #include <dbghelp.h>
  18. #include <frs.h>
  19. #include <winbase.h>
  20. #include <mapi.h>
  21. #include <ntfrsapi.h>
  22. #include <info.h>
  23. extern PCHAR LatestChanges[];
  24. extern ULONG MaxCoRetryTimeoutCount;
  25. extern ULONG MaxCoRetryTimeoutMinutes;
  26. extern DWORD CommTimeoutInMilliSeconds;
  27. extern ULONG DsPollingLongInterval;
  28. extern ULONG DsPollingShortInterval;
  29. extern DWORD PartnerClockSkew;
  30. extern ULONG ChangeOrderAgingDelay;
  31. extern DWORD ReplicaTombstone;
  32. //
  33. // Track the thread IDs of known threads for the debug log header.
  34. //
  35. typedef struct _KNOWN_THREAD {
  36. PWCHAR Name; // print Name of thread.
  37. DWORD Id; // Id returned by CreateThread()
  38. PTHREAD_START_ROUTINE EntryPoint; // entry point
  39. } KNOWN_THREAD, *PKNOWN_THREAD;
  40. KNOWN_THREAD KnownThreadArray[20];
  41. //
  42. // Send mail will not work if the Default User is unable to send
  43. // mail on this machine.
  44. //
  45. MapiRecipDesc Recips =
  46. {0, MAPI_TO, 0, 0, 0, NULL};
  47. MapiMessage Message =
  48. { 0, 0, 0, NULL, NULL, NULL, 0, 0, 1, &Recips, 0, 0 };
  49. LPMAPILOGON MailLogon;
  50. LPMAPILOGOFF MailLogoff;
  51. LPMAPISENDMAIL MailSend;
  52. HANDLE MailLib;
  53. LHANDLE MailSession;
  54. WCHAR DbgExePathW[MAX_PATH+1];
  55. CHAR DbgExePathA[MAX_PATH+1];
  56. CHAR DbgSearchPath[MAX_PATH+1];
  57. //
  58. // Flush the trace log every so many lines.
  59. //
  60. LONG DbgFlushInterval = 100000;
  61. #define DEFAULT_DEBUG_MAX_LOG (20000)
  62. LONG StackTraceCount = 100;
  63. LONG DbgRaiseCount = 50;
  64. OSVERSIONINFOEXW OsInfo;
  65. SYSTEM_INFO SystemInfo;
  66. PCHAR ProcessorArchName[12] = {"INTEL", "MIPS", "Alpha", "PPC", "SHX",
  67. "ARM", "IA64", "Alpha64", "MSIL", "AMD64",
  68. "IA32-on-WIN64", "unknown"};
  69. //
  70. // Suffixes for saved log files and saved assertion files
  71. // E.g., (ntfrs_0005.log)
  72. // (DebugInfo.LogFile, DebugInfo.LogFiles, LOG_FILE_SUFFIX)
  73. //
  74. #define LOG_FILE_FORMAT L"%ws_%04d%ws"
  75. #define LOG_FILE_SUFFIX L".log"
  76. #define ASSERT_FILE_SUFFIX L"_assert.log"
  77. //
  78. // Disable the generation of compressed staging files for any local changes.
  79. //
  80. BOOL DisableCompressionStageFiles;
  81. ULONG GOutLogRepeatInterval;
  82. //
  83. // Client side ldap search timeout in minutes. Reg value "Ldap Search Timeout In Minutes". Default is 10 minutes.
  84. //
  85. DWORD LdapSearchTimeoutInMinutes;
  86. //
  87. // Client side ldap_connect timeout in seconds. Reg value "Ldap Bind Timeout In Seconds". Default is 30 seconds.
  88. //
  89. DWORD LdapBindTimeoutInSeconds;
  90. SC_HANDLE
  91. FrsOpenServiceHandle(
  92. IN PTCHAR MachineName,
  93. IN PTCHAR ServiceName
  94. );
  95. VOID
  96. FrsPrintRpcStats(
  97. IN ULONG Severity,
  98. IN PNTFRSAPI_INFO Info, OPTIONAL
  99. IN DWORD Tabs
  100. );
  101. #if DBG
  102. //
  103. // Collection of debug info from the registry and the CLI
  104. //
  105. DEBUGARG DebugInfo;
  106. //
  107. // allow multiple servers on one machine
  108. //
  109. PWCHAR ServerName = NULL;
  110. PWCHAR IniFileName = NULL;
  111. GUID *ServerGuid = NULL;
  112. VOID
  113. DbgLogDisable(
  114. VOID
  115. )
  116. /*++
  117. Routine Description:
  118. Disable DPRINT log.
  119. Arguments:
  120. None.
  121. Return Value:
  122. None.
  123. --*/
  124. {
  125. #undef DEBSUB
  126. #define DEBSUB "DbgLogDisable:"
  127. DebLock();
  128. if (HANDLE_IS_VALID(DebugInfo.LogFILE)) {
  129. FrsFlushFile(L"LogFILE", DebugInfo.LogFILE);
  130. DbgFlushInterval = DebugInfo.LogFlushInterval;
  131. FRS_CLOSE(DebugInfo.LogFILE);
  132. }
  133. DebugInfo.LogFILE = INVALID_HANDLE_VALUE;
  134. DebUnLock();
  135. }
  136. VOID
  137. DbgOpenLogFile(
  138. VOID
  139. )
  140. /*++
  141. Routine Description:
  142. Open the log file by creating names like ntfrs0001.log.
  143. NumFiles as a 4 digit decimal number and Suffix is like ".log".
  144. DebLock() must be held (DO NOT CALL DPRINT IN THIS FUNCTION!)
  145. Arguments:
  146. Base
  147. Suffix
  148. NumFiles
  149. Return Value:
  150. None.
  151. --*/
  152. {
  153. #undef DEBSUB
  154. #define DEBSUB "DbgOpenLogFile:"
  155. WCHAR LogPath[MAX_PATH + 1];
  156. SECURITY_ATTRIBUTES SecurityAttributes;
  157. if (DebugInfo.Disabled) {
  158. DebugInfo.LogFILE = INVALID_HANDLE_VALUE;
  159. return;
  160. }
  161. if (_snwprintf(LogPath, MAX_PATH, LOG_FILE_FORMAT, DebugInfo.LogFile,
  162. DebugInfo.LogFiles, LOG_FILE_SUFFIX) < 0) {
  163. DebugInfo.LogFILE = INVALID_HANDLE_VALUE;
  164. return;
  165. }
  166. //
  167. // Set this handle to be inheritable so that it can be passed
  168. // to new processes that ntfrs starts (lodctr, unlodctr) and cause
  169. // them to write their errors in the ntfrs debug logs.
  170. //
  171. SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
  172. SecurityAttributes.bInheritHandle = TRUE;
  173. SecurityAttributes.lpSecurityDescriptor = NULL; // not same as NULL DACL
  174. DebugInfo.LogFILE = CreateFile(LogPath, // lpszName
  175. GENERIC_READ | GENERIC_WRITE, // fdwAccess
  176. FILE_SHARE_READ, // fdwShareMode
  177. &SecurityAttributes, // lpsa
  178. CREATE_ALWAYS, // fdwCreate
  179. FILE_FLAG_BACKUP_SEMANTICS, // fdwAttrAndFlags
  180. NULL); // hTemplateFile
  181. }
  182. VOID
  183. DbgShiftLogFiles(
  184. IN PWCHAR Base,
  185. IN PWCHAR Suffix,
  186. IN PWCHAR RemoteBase,
  187. IN ULONG NumFiles
  188. )
  189. /*++
  190. Routine Description:
  191. Shift the files through the range of log/assert file names
  192. (Base_5_Suffix -> Base_4_Suffix -> ... Base_0_Suffix
  193. DebLock() must be held (DO NOT CALL DPRINT IN THIS FUNCTION!)
  194. Arguments:
  195. Base
  196. Suffix
  197. NumFiles
  198. Return Value:
  199. None.
  200. --*/
  201. {
  202. #undef DEBSUB
  203. #define DEBSUB "DbgShiftLogFiles:"
  204. ULONG i;
  205. WCHAR FromPath[MAX_PATH + 1];
  206. WCHAR ToPath[MAX_PATH + 1];
  207. ULONGLONG Now;
  208. //
  209. // No history
  210. //
  211. if ((NumFiles < 2) || DebugInfo.Disabled) {
  212. return;
  213. }
  214. //
  215. // Save the log file as an assert file
  216. //
  217. for (i = 2; i <= NumFiles; ++i) {
  218. if (_snwprintf(ToPath, MAX_PATH, LOG_FILE_FORMAT, Base, i-1, Suffix) > 0) {
  219. if (_snwprintf(FromPath, MAX_PATH, LOG_FILE_FORMAT, Base, i, Suffix) > 0) {
  220. MoveFileEx(FromPath, ToPath, MOVEFILE_REPLACE_EXISTING |
  221. MOVEFILE_WRITE_THROUGH);
  222. }
  223. }
  224. }
  225. //
  226. // Copy the last log file to a remote share
  227. // WARN - the system time is used to create a unique file
  228. // name. This means that the remote share can
  229. // fill up!
  230. //
  231. if (!RemoteBase) {
  232. return;
  233. }
  234. GetSystemTimeAsFileTime((FILETIME *)&Now);
  235. if (_snwprintf(FromPath, MAX_PATH, LOG_FILE_FORMAT, Base, NumFiles-1, Suffix) > 0) {
  236. if (_snwprintf(ToPath,
  237. MAX_PATH,
  238. L"%ws%ws%08x%_%08x",
  239. RemoteBase,
  240. Suffix,
  241. PRINTQUAD(Now)) > 0) {
  242. CopyFileEx(FromPath, ToPath, NULL, NULL, FALSE, 0);
  243. }
  244. }
  245. }
  246. VOID
  247. DbgSendMail(
  248. IN PCHAR Subject,
  249. IN PCHAR Content
  250. )
  251. /*++
  252. Routine Description:
  253. Send mail as the default user.
  254. Arguments:
  255. Subject
  256. Message
  257. Return Value:
  258. None.
  259. --*/
  260. {
  261. #undef DEBSUB
  262. #define DEBSUB "DbgSendMail:"
  263. DWORD MStatus;
  264. WCHAR FullPathToDll[MAX_PATH + 1];
  265. //
  266. // Nobody to send mail to
  267. //
  268. if (!DebugInfo.Recipients) {
  269. return;
  270. }
  271. //
  272. // Load the mail library and find our entry points
  273. //
  274. FullPathToDll[0] = L'\0';
  275. GetSystemDirectory(FullPathToDll,sizeof(FullPathToDll)/sizeof(FullPathToDll[0]));
  276. if ((wcslen(FullPathToDll) == 0 )||
  277. (wcslen(FullPathToDll) + wcslen(L"\\mapi32.dll"))
  278. >= sizeof(FullPathToDll)) {
  279. return;
  280. }
  281. wcscat(FullPathToDll,L"\\mapi32.dll");
  282. MailLib = LoadLibrary(FullPathToDll);
  283. if(!HANDLE_IS_VALID(MailLib)) {
  284. DPRINT_WS(0, ":S: Load mapi32.dll failed;", GetLastError());
  285. return;
  286. }
  287. MailLogon = (LPMAPILOGON)GetProcAddress(MailLib, "MAPILogon");
  288. MailLogoff = (LPMAPILOGOFF)GetProcAddress(MailLib, "MAPILogoff");
  289. MailSend = (LPMAPISENDMAIL)GetProcAddress(MailLib, "MAPISendMail");
  290. if (!MailLogon || !MailLogoff || !MailSend) {
  291. DPRINT(0, ":S: ERROR - Could not find mail symbols in mapi32.dll\n");
  292. FreeLibrary(MailLib);
  293. return;
  294. }
  295. //
  296. // Log on with the specified profile
  297. //
  298. MStatus = MailLogon(0, DebugInfo.Profile, 0, 0, 0, &MailSession);
  299. if(MStatus) {
  300. DPRINT1_WS(0, ":S: ERROR - MailLogon failed; MStatus %d;",
  301. MStatus, GetLastError());
  302. FreeLibrary(MailLib);
  303. return;
  304. }
  305. //
  306. // Send the mail
  307. //
  308. Recips.lpszName = DebugInfo.Recipients;
  309. Message.lpszSubject = Subject;
  310. Message.lpszNoteText = Content;
  311. MStatus = MailSend(MailSession, 0, &Message, 0, 0);
  312. if(MStatus) {
  313. DPRINT1_WS(0, ":S: ERROR - MailSend failed MStatus %d;", MStatus, GetLastError());
  314. }
  315. //
  316. // Log off and free the library
  317. //
  318. MailLogoff(MailSession, 0, 0, 0);
  319. FreeLibrary(MailLib);
  320. }
  321. VOID
  322. DbgSymbolPrint(
  323. IN ULONG Severity,
  324. IN PCHAR Debsub,
  325. IN UINT LineNo,
  326. IN ULONG_PTR Addr
  327. )
  328. /*++
  329. Routine Description:
  330. Print a symbol
  331. Arguments:
  332. Addr
  333. Return Value:
  334. None.
  335. --*/
  336. {
  337. #undef DEBSUB
  338. #define DEBSUB "DbgSymbolPrint:"
  339. ULONG_PTR Displacement = 0;
  340. struct MyMymbol {
  341. IMAGEHLP_SYMBOL Symbol;
  342. char Path[MAX_PATH];
  343. } MySymbol;
  344. try {
  345. ZeroMemory(&MySymbol, sizeof(MySymbol));
  346. MySymbol.Symbol.SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
  347. MySymbol.Symbol.MaxNameLength = MAX_PATH;
  348. if (!SymGetSymFromAddr(ProcessHandle, Addr, &Displacement, &MySymbol.Symbol)) {
  349. DebPrint(Severity, "++ \t 0x%08x: Unknown Symbol (WStatus %s)\n",
  350. Debsub, LineNo, Addr, ErrLabelW32(GetLastError()));
  351. } else
  352. DebPrint(Severity, "++ \t 0x%08x: %s\n",
  353. Debsub, LineNo, Addr, MySymbol.Symbol.Name);
  354. } except (EXCEPTION_EXECUTE_HANDLER) {
  355. DebPrint(Severity, "++ \t 0x%08x: Unknown Symbol (WStatus %s)\n",
  356. Debsub, LineNo, Addr, ErrLabelW32(GetExceptionCode()));
  357. /* FALL THROUGH */
  358. }
  359. }
  360. VOID
  361. DbgModulePrint(
  362. IN PWCHAR Prepense,
  363. IN ULONG Addr
  364. )
  365. /*++
  366. Routine Description:
  367. Print info about a module containing Addr
  368. Arguments:
  369. Prepense - prettypring; printed at the beginning of each line
  370. Addr
  371. Return Value:
  372. None.
  373. --*/
  374. {
  375. #undef DEBSUB
  376. #define DEBSUB "DbgModulePrint:"
  377. IMAGEHLP_MODULE mi;
  378. try {
  379. ZeroMemory(&mi, sizeof(mi));
  380. mi.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
  381. if (!SymGetModuleInfo(ProcessHandle, Addr, &mi)) {
  382. DPRINT1_WS(0, "++ %ws <unknown module;", Prepense, GetLastError());
  383. } else
  384. DPRINT2(0, "++ %ws Module is %ws\n", Prepense, mi.ModuleName);
  385. } except (EXCEPTION_EXECUTE_HANDLER) {
  386. /* FALL THROUGH */
  387. }
  388. }
  389. VOID
  390. DbgStackPrint(
  391. IN ULONG Severity,
  392. IN PCHAR Debsub,
  393. IN UINT LineNo,
  394. IN PULONG_PTR Stack,
  395. IN ULONG Depth
  396. )
  397. /*++
  398. Routine Description:
  399. Print the previously acquired stack trace.
  400. Arguments:
  401. Prepense - prettypring; printed at the beginning of each line
  402. Stack - "return PC" from each frame
  403. Depth - Only this many frames
  404. Return Value:
  405. None.
  406. --*/
  407. {
  408. #undef DEBSUB
  409. #define DEBSUB "DbgStackPrint:"
  410. ULONG i;
  411. try {
  412. for (i = 0; i < Depth && *Stack; ++i, ++Stack) {
  413. DbgSymbolPrint(Severity, Debsub, LineNo, *Stack);
  414. }
  415. } except (EXCEPTION_EXECUTE_HANDLER) {
  416. /* FALL THROUGH */
  417. }
  418. }
  419. VOID
  420. DbgStackTrace(
  421. IN PULONG_PTR Stack,
  422. IN ULONG Depth
  423. )
  424. /*++
  425. Routine Description:
  426. Trace the stack back up to Depth frames. The current frame is included.
  427. Arguments:
  428. Stack - Saves the "return PC" from each frame
  429. Depth - Only this many frames
  430. Return Value:
  431. None.
  432. --*/
  433. {
  434. #undef DEBSUB
  435. #define DEBSUB "DbgStackTrace:"
  436. ULONG WStatus;
  437. HANDLE ThreadHandle;
  438. STACKFRAME Frame;
  439. ULONG i = 0;
  440. CONTEXT Context;
  441. ULONG FrameAddr;
  442. //
  443. // I don't know how to generate a stack for an alpha, yet. So, just
  444. // to get into the build, disable the stack trace on alphas.
  445. //
  446. if (Stack) {
  447. *Stack = 0;
  448. }
  449. #if ALPHA
  450. return;
  451. #elif IA64
  452. //
  453. // Need stack dump init for IA64.
  454. //
  455. return;
  456. #else
  457. //
  458. // init
  459. //
  460. ZeroMemory(&Context, sizeof(Context));
  461. ThreadHandle = GetCurrentThread();
  462. try { try {
  463. Context.ContextFlags = CONTEXT_FULL;
  464. if (!GetThreadContext(ThreadHandle, &Context)) {
  465. DPRINT_WS(0, "++ Can't get context;", GetLastError());
  466. }
  467. //
  468. // let's start clean
  469. //
  470. ZeroMemory(&Frame, sizeof(STACKFRAME));
  471. //
  472. // from nt\private\windows\screg\winreg\server\stkwalk.c
  473. //
  474. Frame.AddrPC.Segment = 0;
  475. Frame.AddrPC.Mode = AddrModeFlat;
  476. #ifdef _M_IX86
  477. Frame.AddrFrame.Offset = Context.Ebp;
  478. Frame.AddrFrame.Mode = AddrModeFlat;
  479. Frame.AddrStack.Offset = Context.Esp;
  480. Frame.AddrStack.Mode = AddrModeFlat;
  481. Frame.AddrPC.Offset = (DWORD)Context.Eip;
  482. #elif defined(_M_MRX000)
  483. Frame.AddrPC.Offset = (DWORD)Context.Fir;
  484. #elif defined(_M_ALPHA)
  485. Frame.AddrPC.Offset = (DWORD)Context.Fir;
  486. #endif
  487. #if 0
  488. //
  489. // setup the program counter
  490. //
  491. Frame.AddrPC.Mode = AddrModeFlat;
  492. Frame.AddrPC.Segment = (WORD)Context.SegCs;
  493. Frame.AddrPC.Offset = (ULONG)Context.Eip;
  494. //
  495. // setup the frame pointer
  496. //
  497. Frame.AddrFrame.Mode = AddrModeFlat;
  498. Frame.AddrFrame.Segment = (WORD)Context.SegSs;
  499. Frame.AddrFrame.Offset = (ULONG)Context.Ebp;
  500. //
  501. // setup the stack pointer
  502. //
  503. Frame.AddrStack.Mode = AddrModeFlat;
  504. Frame.AddrStack.Segment = (WORD)Context.SegSs;
  505. Frame.AddrStack.Offset = (ULONG)Context.Esp;
  506. #endif
  507. for (i = 0; i < (Depth - 1); ++i) {
  508. if (!StackWalk(
  509. IMAGE_FILE_MACHINE_I386, // DWORD MachineType
  510. ProcessHandle, // HANDLE hProcess
  511. ThreadHandle, // HANDLE hThread
  512. &Frame, // LPSTACKFRAME StackFrame
  513. NULL, //(PVOID)&Context, // PVOID ContextRecord
  514. NULL, // PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine
  515. SymFunctionTableAccess, // PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine
  516. SymGetModuleBase, // PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine
  517. NULL)) { // PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
  518. WStatus = GetLastError();
  519. //DPRINT1_WS(0, "++ Can't get stack address for level %d;", i, WStatus);
  520. break;
  521. }
  522. if (StackTraceCount-- > 0) {
  523. DPRINT1(5, "++ Frame.AddrReturn.Offset: %08x \n", Frame.AddrReturn.Offset);
  524. DbgSymbolPrint(5, DEBSUB, __LINE__, Frame.AddrReturn.Offset);
  525. //DPRINT1(5, "++ Frame.AddrPC.Offset: %08x \n", Frame.AddrPC.Offset);
  526. //DbgSymbolPrint(5, DEBSUB, __LINE__, Frame.AddrPC.Offset);
  527. }
  528. *Stack++ = Frame.AddrReturn.Offset;
  529. *Stack = 0;
  530. //
  531. // Base of stack?
  532. //
  533. if (!Frame.AddrReturn.Offset) {
  534. break;
  535. }
  536. }
  537. } except (EXCEPTION_EXECUTE_HANDLER) {
  538. /* FALL THROUGH */
  539. } } finally {
  540. FRS_CLOSE(ThreadHandle);
  541. }
  542. return;
  543. #endif ALPHA
  544. }
  545. VOID
  546. DbgPrintStackTrace(
  547. IN ULONG Severity,
  548. IN PCHAR Debsub,
  549. IN UINT LineNo
  550. )
  551. /*++
  552. Routine Description:
  553. Acquire and print the stack
  554. Arguments:
  555. Severity
  556. Debsub
  557. Return Value:
  558. None.
  559. --*/
  560. {
  561. #undef DEBSUB
  562. #define DEBSUB "DbgPrintStackTrace:"
  563. ULONG_PTR Stack[32];
  564. DbgStackTrace(Stack, ARRAY_SZ(Stack) );
  565. DbgStackPrint(Severity, Debsub, LineNo, Stack, ARRAY_SZ(Stack) );
  566. }
  567. VOID
  568. DbgStackInit(
  569. VOID
  570. )
  571. /*++
  572. Routine Description:
  573. Initialize anything necessary to get a stack trace
  574. Arguments:
  575. None.
  576. Return Value:
  577. None.
  578. --*/
  579. {
  580. #undef DEBSUB
  581. #define DEBSUB "DbgStackInit:"
  582. //
  583. // Initialize the symbol subsystem
  584. //
  585. if (!SymInitialize(ProcessHandle, NULL, FALSE)) {
  586. DPRINT_WS(0, ":S: Could not initialize symbol subsystem (imagehlp)" ,GetLastError());
  587. }
  588. //
  589. // Load our symbols
  590. //
  591. if (!SymLoadModule(ProcessHandle, NULL, DbgExePathA, "FRS", 0, 0)) {
  592. DPRINT1_WS(0, ":S: Could not load symbols for %s", DbgExePathA ,GetLastError());
  593. }
  594. //
  595. // Search path
  596. //
  597. if (!SymGetSearchPath(ProcessHandle, DbgSearchPath, MAX_PATH)) {
  598. DPRINT_WS(0, ":S: Can't get search path; error %s", GetLastError());
  599. } else {
  600. DPRINT1(0, ":S: Symbol search path is %s\n", DbgSearchPath);
  601. }
  602. }
  603. void
  604. DbgShowConfig(
  605. VOID
  606. )
  607. /*++
  608. Routine Description:
  609. Display the OS Version info and the Processor Architecture info.
  610. Arguments:
  611. None.
  612. Return Value:
  613. None.
  614. --*/
  615. {
  616. #undef DEBSUB
  617. #define DEBSUB "DbgShowConfig:"
  618. ULONG ProductType;
  619. ULONG Arch;
  620. if (DebugInfo.BuildLab != NULL) {
  621. DPRINT1(0, ":H: BuildLab : %s\n", DebugInfo.BuildLab);
  622. }
  623. DPRINT4(0, ":H: OS Version %d.%d (%d) - %w\n",
  624. OsInfo.dwMajorVersion,OsInfo.dwMinorVersion,OsInfo.dwBuildNumber,OsInfo.szCSDVersion);
  625. ProductType = (ULONG) OsInfo.wProductType;
  626. DPRINT4(0, ":H: SP (%hd.%hd) SM: 0x%04hx PT: 0x%02x\n",
  627. OsInfo.wServicePackMajor,OsInfo.wServicePackMinor,OsInfo.wSuiteMask, ProductType);
  628. Arch = SystemInfo.wProcessorArchitecture;
  629. if (Arch >= ARRAY_SZ(ProcessorArchName)) {
  630. Arch = ARRAY_SZ(ProcessorArchName)-1;
  631. }
  632. DPRINT5(0, ":H: Processor: %s Level: 0x%04hx Revision: 0x%04hx Processor num/mask: %d/%08x\n",
  633. ProcessorArchName[Arch], SystemInfo.wProcessorLevel,
  634. SystemInfo.wProcessorRevision, SystemInfo.dwNumberOfProcessors,
  635. SystemInfo.dwActiveProcessorMask);
  636. }
  637. VOID
  638. DbgCaptureThreadInfo(
  639. PWCHAR ArgName,
  640. PTHREAD_START_ROUTINE EntryPoint
  641. )
  642. /*++
  643. Routine Description:
  644. Search the KnownThreadArray for an entry with a matching name. If not found,
  645. Search the FRS Thread list for the thread with the matching entry point.
  646. If found make an entry in the KnownThreadArray so it is available when
  647. printing out the debug log header.
  648. Arguments:
  649. ArgName -- Printable name of thread.
  650. Main -- Entry point of thread.
  651. Return Value:
  652. None.
  653. --*/
  654. {
  655. #undef DEBSUB
  656. #define DEBSUB "DbgCaptureThreadInfo:"
  657. PFRS_THREAD FrsThread;
  658. ULONG i;
  659. if (ArgName == NULL) {
  660. return;
  661. }
  662. for (i = 0; i < ARRAY_SZ(KnownThreadArray); i++) {
  663. //
  664. // Any room left?
  665. //
  666. if ((KnownThreadArray[i].Name == NULL) ||
  667. (WSTR_EQ(ArgName, KnownThreadArray[i].Name))) {
  668. FrsThread = ThSupGetThread(EntryPoint);
  669. if (FrsThread == NULL) {
  670. return;
  671. }
  672. KnownThreadArray[i].EntryPoint = FrsThread->Main;
  673. KnownThreadArray[i].Id = FrsThread->Id;
  674. KnownThreadArray[i].Name = ArgName;
  675. ThSupReleaseRef(FrsThread);
  676. break;
  677. }
  678. }
  679. }
  680. VOID
  681. DbgCaptureThreadInfo2(
  682. PWCHAR ArgName,
  683. PTHREAD_START_ROUTINE EntryPoint,
  684. ULONG ThreadId
  685. )
  686. /*++
  687. Routine Description:
  688. Search the KnownThreadArray for an entry with a matching name.
  689. If found make an entry in the KnownThreadArray so it is available when
  690. printing out the debug log header.
  691. Arguments:
  692. ArgName -- Printable name of thread.
  693. Main -- Entry point of thread.
  694. ThreadId - Thread ID of the thread to add to the list.
  695. Return Value:
  696. None.
  697. --*/
  698. {
  699. #undef DEBSUB
  700. #define DEBSUB "DbgCaptureThreadInfo2:"
  701. ULONG i;
  702. if (ArgName == NULL) {
  703. return;
  704. }
  705. for (i = 0; i < ARRAY_SZ(KnownThreadArray); i++) {
  706. //
  707. // Any room left or
  708. // See if we already have this one and update the thread ID if so.
  709. // If it was a cmd server thread it may have exited after timeout.
  710. //
  711. if ((KnownThreadArray[i].Name == NULL) ||
  712. (WSTR_EQ(ArgName, KnownThreadArray[i].Name))) {
  713. KnownThreadArray[i].EntryPoint = EntryPoint;
  714. KnownThreadArray[i].Id = ThreadId;
  715. KnownThreadArray[i].Name = ArgName;
  716. break;
  717. }
  718. }
  719. }
  720. VOID
  721. DbgPrintThreadIds(
  722. IN ULONG Severity
  723. )
  724. /*++
  725. Routine Description:
  726. Print the known thread IDs.
  727. Arguments:
  728. Severity
  729. Return Value:
  730. None.
  731. --*/
  732. {
  733. #undef DEBSUB
  734. #define DEBSUB "DbgPrintThreadIds:"
  735. ULONG i;
  736. DPRINT(Severity, ":H: Known thread IDs -\n");
  737. //
  738. // Dump the known thread IDs.
  739. //
  740. for (i = 0; i < ARRAY_SZ(KnownThreadArray); i++) {
  741. if (KnownThreadArray[i].Name != NULL) {
  742. DPRINT2(Severity, ":H: %-20ws : %d\n",
  743. KnownThreadArray[i].Name, KnownThreadArray[i].Id);
  744. }
  745. }
  746. }
  747. VOID
  748. DbgPrintInfo(
  749. IN ULONG Severity
  750. )
  751. /*++
  752. Routine Description:
  753. Print the debug info struct
  754. Arguments:
  755. Severity
  756. Return Value:
  757. None.
  758. --*/
  759. {
  760. #undef DEBSUB
  761. #define DEBSUB "DbgPrintInfo:"
  762. SYSTEMTIME SystemTime;
  763. ULONG Unamesize = MAX_PATH + 1;
  764. ULONG i;
  765. WCHAR Uname[MAX_PATH + 1];
  766. CHAR TimeBuf[MAX_PATH];
  767. //
  768. // Username
  769. //
  770. if (!GetUserName(Uname, &Unamesize)) {
  771. Uname[0] = L'\0';
  772. }
  773. TimeBuf[0] = '\0';
  774. GetLocalTime(&SystemTime);
  775. if (_snprintf(TimeBuf, MAX_PATH, "%2d/%2d-%02d:%02d:%02d ",
  776. SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour,
  777. SystemTime.wMinute, SystemTime.wSecond) < 0) {
  778. TimeBuf[0] = '\0';
  779. }
  780. DPRINT3(Severity, ":H: Service running on %ws as %ws at %s\n",
  781. ComputerName, Uname, TimeBuf);
  782. DPRINT(Severity, "\n");
  783. DPRINT(Severity, ":H: ***** COMPILE INFORMATION:\n");
  784. DPRINT1(Severity, ":H: \tModule %s\n", NtFrsModule);
  785. DPRINT2(Severity, ":H: \tCompile Date %s %s\n", NtFrsDate, NtFrsTime);
  786. i = 0;
  787. while (LatestChanges[i] != NULL) {
  788. DPRINT1(Severity, ":H: %s\n", LatestChanges[i]);
  789. i++;
  790. }
  791. DPRINT(Severity, "\n");
  792. DbgShowConfig();
  793. DPRINT(Severity, "\n");
  794. DPRINT(Severity, ":H: ***** DEBUG INFORMATION:\n");
  795. DPRINT1(Severity, ":H: Assert Files : %d\n", DebugInfo.AssertFiles);
  796. if (DebugInfo.AssertSeconds) {
  797. DPRINT1(Severity, ":H: Assert Seconds : Assert after %d seconds\n", DebugInfo.AssertSeconds);
  798. } else {
  799. DPRINT(Severity, ":H: Assert Seconds : Don't force an assert\n");
  800. }
  801. DPRINT1(Severity, ":H: Assert Share : %ws\n", DebugInfo.AssertShare);
  802. DPRINT1(Severity, ":H: ChangeOrderAgingDelay (ms) : %d\n", ChangeOrderAgingDelay);
  803. DPRINT1(Severity, ":H: Check Mem : %s\n", (DebugInfo.Mem) ? "TRUE" : "FALSE");
  804. DPRINT1(Severity, ":H: Check Queues : %s\n", (DebugInfo.Queues) ? "TRUE" : "FALSE");
  805. DPRINT1(Severity, ":H: CommTimeoutInMilliSeconds : %d\n", CommTimeoutInMilliSeconds);
  806. DPRINT1(Severity, ":H: Compact Mem : %s\n", (DebugInfo.MemCompact) ? "TRUE" : "FALSE");
  807. DPRINT1(Severity, ":H: CompressStagingFiles : %s\n", (!DisableCompressionStageFiles) ? "TRUE" : "FALSE");
  808. DPRINT1(Severity, ":H: Copy Logs : %s\n", (DebugInfo.CopyLogs) ? "TRUE" : "FALSE");
  809. DPRINT1(Severity, ":H: Disabled : %s\n", (DebugInfo.Disabled) ? "TRUE" : "FALSE");
  810. DPRINT1(Severity, ":H: DsPollingLongInterval (ms) : %d\n", DsPollingLongInterval);
  811. DPRINT1(Severity, ":H: DsPollingShortInterval(ms) : %d\n", DsPollingShortInterval);
  812. DPRINT1(Severity, ":H: EnableInstallOverride : %s\n", (DebugInfo.EnableInstallOverride) ? "TRUE" : "FALSE");
  813. DPRINT1(Severity, ":H: EnableJrnlWrapAutoRestore : %s\n", (DebugInfo.EnableJrnlWrapAutoRestore) ? "TRUE" : "FALSE");
  814. DPRINT1(Severity, ":H: EnableRenameUpdates : %s\n", (DebugInfo.EnableRenameUpdates) ? "TRUE" : "FALSE");
  815. DPRINT1(Severity, ":H: FetchRetryReset : %d\n", DebugInfo.FetchRetryReset);
  816. DPRINT1(Severity, ":H: FetchRetryResetInc : %d\n", DebugInfo.FetchRetryInc);
  817. DPRINT1(Severity, ":H: FetchRetryTrigger : %d\n", DebugInfo.FetchRetryTrigger);
  818. DPRINT1(Severity, ":H: Force VvJoin : %s\n", (DebugInfo.ForceVvJoin) ? "TRUE" : "FALSE");
  819. DPRINT1(Severity, ":H: Interval : %d\n", DebugInfo.Interval);
  820. DPRINT1(Severity, ":H: Log Dir : %ws\n", DebugInfo.LogDir ? DebugInfo.LogDir : L"<null>");
  821. DPRINT1(Severity, ":H: Log File : %ws\n", DebugInfo.LogFile);
  822. DPRINT1(Severity, ":H: Log Files : %d\n", DebugInfo.LogFiles);
  823. DPRINT1(Severity, ":H: Log Flush Int. : %d\n", DebugInfo.LogFlushInterval);
  824. DPRINT1(Severity, ":H: Log Lines : %d\n", DebugInfo.LogLines);
  825. DPRINT1(Severity, ":H: Log Severity : %d\n", DebugInfo.LogSeverity);
  826. DPRINT1(Severity, ":H: Max Log Lines : %d\n", DebugInfo.MaxLogLines);
  827. DPRINT1(Severity, ":H: MaxCoRetryTimeoutCount : %d\n", MaxCoRetryTimeoutCount);
  828. DPRINT1(Severity, ":H: MaxCoRetryTimeoutMinutes : %d\n", MaxCoRetryTimeoutMinutes);
  829. DPRINT1(Severity, ":H: OutlogChangeHistory : %d\n", DebugInfo.OutlogChangeHistory);
  830. DPRINT1(Severity, ":H: PartnerClockSkew (m) : %d\n", PartnerClockSkew);
  831. DPRINT1(Severity, ":H: Profile : %s\n", DebugInfo.Profile);
  832. DPRINT1(Severity, ":H: Recipients : %s\n", DebugInfo.Recipients);
  833. DPRINT1(Severity, ":H: ReclaimStagingSpace : %s\n", (DebugInfo.ReclaimStagingSpace) ? "TRUE" : "FALSE");
  834. DPRINT1(Severity, ":H: ReplicaTombstone (d) : %d\n", ReplicaTombstone);
  835. DPRINT1(Severity, ":H: Restart : %s\n", (DebugInfo.Restart) ? "TRUE" : "FALSE");
  836. if (DebugInfo.RestartSeconds) {
  837. DPRINT1(Severity, ":H: Restart Seconds : Restart if assert after "
  838. "%d seconds\n", DebugInfo.RestartSeconds);
  839. } else {
  840. DPRINT(Severity, ":H: Restart Seconds: Don't Restart\n");
  841. }
  842. DPRINT1(Severity, ":H: SaveOutlogChangeHistory : %s\n", (DebugInfo.SaveOutlogChangeHistory) ? "TRUE" : "FALSE");
  843. DPRINT1(Severity, ":H: Severity : %d\n", DebugInfo.Severity);
  844. DPRINT1(Severity, ":H: StagingLimitInKb : %d\n", StagingLimitInKb);
  845. DPRINT1(Severity, ":H: Suppress : %s\n", (DebugInfo.Suppress) ? "TRUE" : "FALSE");
  846. DPRINT1(Severity, ":H: SuppressIdenticalUpdt : %s\n", (DebugInfo.SuppressIdenticalUpdt) ? "TRUE" : "FALSE");
  847. DPRINT1(Severity, ":H: Systems : %ws\n", DebugInfo.Systems);
  848. DPRINT1(Severity, ":H: TestFid : %d\n", DebugInfo.TestFid);
  849. if (DebugInfo.TestCodeName != NULL) {
  850. DPRINT1(Severity, ":H: TestCodeName : %s\n", DebugInfo.TestCodeName ? DebugInfo.TestCodeName : "<null>");
  851. DPRINT1(Severity, ":H: TestSubCodeNumber : %d\n", DebugInfo.TestSubCodeNumber);
  852. DPRINT1(Severity, ":H: TestTriggerCount : %d\n", DebugInfo.TestTriggerCount);
  853. DPRINT1(Severity, ":H: TestTriggerRefresh : %d\n", DebugInfo.TestTriggerRefresh);
  854. }
  855. DPRINT1(Severity, ":H: Thread Id : %d\n", DebugInfo.ThreadId);
  856. DPRINT1(Severity, ":H: Total Log Lines : %d\n", DebugInfo.TotalLogLines);
  857. DPRINT1(Severity, ":H: UnjoinTrigger : %d\n", DebugInfo.UnjoinTrigger);
  858. DPRINT1(Severity, ":H: VvJoinTests : %s\n", (DebugInfo.VvJoinTests) ? "TRUE" : "FALSE");
  859. // DPRINT1(Severity, ":H: Command Line : %ws\n", DebugInfo.CommandLine);
  860. DPRINT(Severity, "\n");
  861. DbgPrintThreadIds(Severity);
  862. DEBUG_FLUSH();
  863. }
  864. VOID
  865. DbgPrintAllStats(
  866. VOID
  867. )
  868. /*++
  869. Routine Description:
  870. Print the stats we know about
  871. Arguments:
  872. None.
  873. Return Value:
  874. None.
  875. --*/
  876. {
  877. #undef DEBSUB
  878. #define DEBSUB "DbgPrintAllStats:"
  879. DbgPrintInfo(DebugInfo.LogSeverity);
  880. FrsPrintAllocStats(DebugInfo.LogSeverity, NULL, 0);
  881. FrsPrintRpcStats(DebugInfo.LogSeverity, NULL, 0);
  882. }
  883. VOID
  884. DbgFlush(
  885. VOID
  886. )
  887. /*++
  888. Routine Description:
  889. Flush the output buffers
  890. Arguments:
  891. None.
  892. Return Value:
  893. None.
  894. --*/
  895. {
  896. #undef DEBSUB
  897. #define DEBSUB "DbgFlush:"
  898. DebLock();
  899. try {
  900. if (HANDLE_IS_VALID(DebugInfo.LogFILE)) {
  901. FrsFlushFile(L"LogFILE", DebugInfo.LogFILE);
  902. DbgFlushInterval = DebugInfo.LogFlushInterval;
  903. }
  904. } finally{
  905. DebUnLock();
  906. }
  907. }
  908. VOID
  909. DbgStartService(
  910. IN PWCHAR ServiceName
  911. )
  912. /*++
  913. Routine Description:
  914. Start a service on this machine.
  915. Arguments:
  916. ServiceName - the service to start
  917. Return Value:
  918. None.
  919. --*/
  920. {
  921. #undef DEBSUB
  922. #define DEBSUB "DbgStartService:"
  923. SC_HANDLE ServiceHandle;
  924. //
  925. // Open the service.
  926. //
  927. ServiceHandle = FrsOpenServiceHandle(NULL, ServiceName);
  928. if (!HANDLE_IS_VALID(ServiceHandle)) {
  929. DPRINT1(0, ":S: Couldn't open service %ws\n", ServiceName);
  930. return;
  931. }
  932. //
  933. // Start the service
  934. //
  935. if (!StartService(ServiceHandle, 0, NULL)) {
  936. DPRINT1_WS(0, ":S: Couldn't start %ws;", ServiceName, GetLastError());
  937. CloseServiceHandle(ServiceHandle);
  938. return;
  939. }
  940. CloseServiceHandle(ServiceHandle);
  941. DPRINT1(4, ":S: Started %ws\n", ServiceName);
  942. }
  943. VOID
  944. DbgStopService(
  945. IN PWCHAR ServiceName
  946. )
  947. /*++
  948. Routine Description:
  949. Stop a service on this machine.
  950. Arguments:
  951. ServiceName - the service to stop
  952. Return Value:
  953. None.
  954. --*/
  955. {
  956. #undef DEBSUB
  957. #define DEBSUB "DbgStopService:"
  958. BOOL Status;
  959. SC_HANDLE ServiceHandle;
  960. SERVICE_STATUS ServiceStatus;
  961. //
  962. // Open the service.
  963. //
  964. ServiceHandle = FrsOpenServiceHandle(NULL, ServiceName);
  965. if (!HANDLE_IS_VALID(ServiceHandle)) {
  966. DPRINT1(0, ":S: Couldn't stop service %ws\n", ServiceName);
  967. return;
  968. }
  969. //
  970. // Stop the service
  971. //
  972. Status = ControlService(ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus);
  973. if (!WIN_SUCCESS(Status)) {
  974. DPRINT1_WS(0, ":S: Couldn't stop %ws;", ServiceName, GetLastError());
  975. CloseServiceHandle(ServiceHandle);
  976. return;
  977. }
  978. CloseServiceHandle(ServiceHandle);
  979. DPRINT1(4, ":S: Stopped %ws\n", ServiceName);
  980. }
  981. ULONG
  982. DbgForceAssert(
  983. IN PVOID Ignored
  984. )
  985. /*++
  986. Routine Description:
  987. Force an assert after some seconds
  988. Arguments:
  989. Ignored
  990. Return Value:
  991. ERROR_SUCCESS
  992. --*/
  993. {
  994. #undef DEBSUB
  995. #define DEBSUB "DbgForceAssert:"
  996. BOOL ForcingAssert = TRUE;
  997. //
  998. // Wait for a shutdown event
  999. //
  1000. WaitForSingleObject(ShutDownEvent, DebugInfo.AssertSeconds * 1000);
  1001. if (!FrsIsShuttingDown) {
  1002. DPRINT(0, ":S: FORCING ASSERT\n");
  1003. FRS_ASSERT(!ForcingAssert);
  1004. }
  1005. return STATUS_SUCCESS;
  1006. }
  1007. VOID
  1008. DbgQueryLogParams(
  1009. )
  1010. /*++
  1011. Routine Description:
  1012. Read the registry for new values for the logging params.
  1013. Arguments:
  1014. Return Value:
  1015. None.
  1016. --*/
  1017. {
  1018. #undef DEBSUB
  1019. #define DEBSUB "DbgQueryLogParams:"
  1020. PWCHAR WStr, WStr1;
  1021. PCHAR AStr;
  1022. PWCHAR NewLogDirStr = NULL;
  1023. PWCHAR File;
  1024. DWORD WStatus;
  1025. DWORD NewDisabled;
  1026. BOOL OpenNewLog = FALSE;
  1027. ULARGE_INTEGER FreeBytes;
  1028. ULARGE_INTEGER TotalBytes;
  1029. //
  1030. // Get new state before taking debug lock since function does DPRINTs.
  1031. //
  1032. CfgRegReadDWord(FKC_DEBUG_DISABLE, NULL, 0, &NewDisabled);
  1033. //
  1034. // Check for a change in Disable Debug
  1035. //
  1036. DebLock();
  1037. if ((BOOL)NewDisabled != DebugInfo.Disabled) {
  1038. DebugInfo.Disabled = NewDisabled;
  1039. if (DebugInfo.Disabled) {
  1040. //
  1041. // Stop logging.
  1042. //
  1043. if (HANDLE_IS_VALID(DebugInfo.LogFILE)) {
  1044. FrsFlushFile(L"LogFILE", DebugInfo.LogFILE);
  1045. DbgFlushInterval = DebugInfo.LogFlushInterval;
  1046. FRS_CLOSE(DebugInfo.LogFILE);
  1047. }
  1048. DebugInfo.LogFILE = INVALID_HANDLE_VALUE;
  1049. } else {
  1050. //
  1051. // Start logging.
  1052. //
  1053. OpenNewLog = TRUE;
  1054. }
  1055. }
  1056. DebUnLock();
  1057. //
  1058. // Quit now if logging is disabled.
  1059. //
  1060. if (DebugInfo.Disabled) {
  1061. return;
  1062. }
  1063. //
  1064. // Log File Directory (only if not running multiple servers on one machine)
  1065. //
  1066. if (ServerName == NULL) {
  1067. CfgRegReadString(FKC_DEBUG_LOG_FILE, NULL, 0, &NewLogDirStr);
  1068. if (NewLogDirStr != NULL) {
  1069. if ((DebugInfo.LogDir == NULL) ||
  1070. WSTR_NE(NewLogDirStr, DebugInfo.LogDir)) {
  1071. OpenNewLog = TRUE;
  1072. } else {
  1073. NewLogDirStr = FrsFree(NewLogDirStr);
  1074. }
  1075. }
  1076. }
  1077. //
  1078. // Number of log files
  1079. //
  1080. CfgRegReadDWord(FKC_DEBUG_LOG_FILES, NULL, 0, &DebugInfo.LogFiles);
  1081. //
  1082. // Flush the trace log after every n lines.
  1083. //
  1084. CfgRegReadDWord(FKC_DEBUG_LOG_FLUSH_INTERVAL, NULL, 0, &DebugInfo.LogFlushInterval);
  1085. //
  1086. // Severity for console print.
  1087. //
  1088. CfgRegReadDWord(FKC_DEBUG_SEVERITY, NULL, 0, &DebugInfo.Severity);
  1089. //
  1090. // Log Severity
  1091. //
  1092. CfgRegReadDWord(FKC_DEBUG_LOG_SEVERITY, NULL, 0, &DebugInfo.LogSeverity);
  1093. //
  1094. // Systems - selected list of functions to trace. trace all if NULL.
  1095. //
  1096. CfgRegReadString(FKC_DEBUG_SYSTEMS, NULL, 0, &WStr);
  1097. if (WStr != NULL) {
  1098. AStr = DebugInfo.Systems;
  1099. DebLock();
  1100. DebugInfo.Systems = (wcslen(WStr)) ? FrsWtoA(WStr) : NULL;
  1101. DebUnLock();
  1102. WStr = FrsFree(WStr);
  1103. AStr = FrsFree(AStr);
  1104. }
  1105. //
  1106. // Maximum Log Messages
  1107. //
  1108. CfgRegReadDWord(FKC_DEBUG_MAX_LOG, NULL, 0, &DebugInfo.MaxLogLines);
  1109. //
  1110. // Debugger serial line Print (assume suppress so no dprints leak out)
  1111. //
  1112. DebugInfo.Suppress = TRUE;
  1113. CfgRegReadDWord(FKC_DEBUG_SUPPRESS, NULL, 0, &DebugInfo.Suppress);
  1114. //
  1115. // Enable break into debugger if present.
  1116. //
  1117. CfgRegReadDWord(FKC_DEBUG_BREAK, NULL, 0, &DebugInfo.Break);
  1118. //
  1119. // Open a new log if logging was just turned on or if we were.
  1120. // having trouble logging due to errors like out of disk space.
  1121. // Save old log files and open a new log file.
  1122. //
  1123. if ((OpenNewLog || !HANDLE_IS_VALID(DebugInfo.LogFILE)) &&
  1124. (HANDLE_IS_VALID(DebugInfo.LogFile) || (NewLogDirStr != NULL))) {
  1125. WStr = DebugInfo.LogFile;
  1126. WStr1 = DebugInfo.LogDir;
  1127. DebLock();
  1128. if (NewLogDirStr != NULL) {
  1129. //
  1130. // Add the filename prefix to the end of the dir path.
  1131. //
  1132. DebugInfo.LogDir = NewLogDirStr;
  1133. DebugInfo.LogFile = FrsWcsCat(NewLogDirStr, NTFRS_DBG_LOG_FILE);
  1134. }
  1135. //
  1136. // Create new debug directory
  1137. //
  1138. if (!CreateDirectory(DebugInfo.LogDir, NULL)) {
  1139. WStatus = GetLastError();
  1140. if (!WIN_ALREADY_EXISTS(WStatus)) {
  1141. DebugInfo.LogFile = FrsFree(DebugInfo.LogFile);
  1142. DebugInfo.LogDir = FrsFree(DebugInfo.LogDir);
  1143. }
  1144. }
  1145. if (DebugInfo.LogFile != NULL) {
  1146. if (HANDLE_IS_VALID(DebugInfo.LogFILE)) {
  1147. FRS_CLOSE(DebugInfo.LogFILE);
  1148. }
  1149. DbgShiftLogFiles(DebugInfo.LogFile,
  1150. LOG_FILE_SUFFIX,
  1151. (DebugInfo.CopyLogs) ? DebugInfo.AssertShare : NULL,
  1152. DebugInfo.LogFiles);
  1153. DbgOpenLogFile();
  1154. }
  1155. DebUnLock();
  1156. if (NewLogDirStr != NULL) {
  1157. WStr = FrsFree(WStr);
  1158. WStr1 = FrsFree(WStr1);
  1159. }
  1160. }
  1161. //
  1162. // Raise a eventlog message if there isn't enough disk space on the logging volume
  1163. // to accomodate all the log files.
  1164. //
  1165. if (DebugInfo.LogDir != NULL) {
  1166. FreeBytes.QuadPart = QUADZERO;
  1167. TotalBytes.QuadPart = QUADZERO;
  1168. if (GetDiskFreeSpaceEx(DebugInfo.LogDir,
  1169. &FreeBytes,
  1170. &TotalBytes,
  1171. NULL)) {
  1172. //
  1173. // Complain if we have less than 10 MB free.
  1174. //
  1175. if (FreeBytes.QuadPart < (10 * 1000 * 1000)) {
  1176. EPRINT1(EVENT_FRS_LOG_SPACE, DebugInfo.LogDir);
  1177. }
  1178. }
  1179. }
  1180. }
  1181. VOID
  1182. DbgQueryDynamicConfigParams(
  1183. )
  1184. /*++
  1185. Routine Description:
  1186. Read the registry for new values for config params that can change
  1187. while service is running.
  1188. Arguments:
  1189. Return Value:
  1190. None.
  1191. --*/
  1192. {
  1193. #undef DEBSUB
  1194. #define DEBSUB "DbgQueryDynamicConfigParams:"
  1195. DWORD CompressStagingFiles = 1;
  1196. PWCHAR WStr = NULL;
  1197. //
  1198. // Pick up new debug logging related parameters.
  1199. //
  1200. DbgQueryLogParams();
  1201. //
  1202. // Get boolean to tell us if we should do automatic restore when
  1203. // we hit journal wrap
  1204. //
  1205. CfgRegReadDWord(FKC_ENABLE_JOURNAL_WRAP_AUTOMATIC_RESTORE, NULL, 0, &DebugInfo.EnableJrnlWrapAutoRestore);
  1206. //
  1207. // Check if automatic cleanup of staging files is enabled or disabled.
  1208. //
  1209. CfgRegReadDWord(FKC_RECLAIM_STAGING_SPACE, NULL, 0, &DebugInfo.ReclaimStagingSpace);
  1210. //
  1211. // Check if a new value for outlog history time is set.
  1212. //
  1213. CfgRegReadDWord(FKC_OUTLOG_CHANGE_HISTORY, NULL, 0, &DebugInfo.OutlogChangeHistory);
  1214. //
  1215. // Check if saving outlog history is disabled.
  1216. //
  1217. CfgRegReadDWord(FKC_SAVE_OUTLOG_CHANGE_HISTORY, NULL, 0, &DebugInfo.SaveOutlogChangeHistory);
  1218. //
  1219. // Check if a new value for install override is set.
  1220. //
  1221. CfgRegReadDWord(FKC_ENABLE_INSTALL_OVERRIDE, NULL, 0, &DebugInfo.EnableInstallOverride);
  1222. //
  1223. // Check if a new value for forced rename on file updates is set.
  1224. //
  1225. CfgRegReadDWord(FKC_ENABLE_RENAME_BASED_UPDATES, NULL, 0, &DebugInfo.EnableRenameUpdates);
  1226. //
  1227. // Check if suppress identical updates is disabled.
  1228. //
  1229. CfgRegReadDWord(FKC_SUPPRESS_IDENTICAL_UPDATES, NULL, 0, &DebugInfo.SuppressIdenticalUpdt);
  1230. //
  1231. // Read the new value for the compression parameter.
  1232. //
  1233. CfgRegReadDWord(FKC_COMPRESS_STAGING_FILES, NULL, 0, &CompressStagingFiles);
  1234. DisableCompressionStageFiles = (CompressStagingFiles == 0);
  1235. //
  1236. // Pick up the Outlog file repeat interval.
  1237. //
  1238. CfgRegReadDWord(FKC_OUTLOG_REPEAT_INTERVAL, NULL, 0, &GOutLogRepeatInterval);
  1239. //
  1240. // Find out which reparse points to replicate.
  1241. //
  1242. CfgRegReadReparseTagInfo();
  1243. //
  1244. // Get the Test code params. They consist of a code name, a sub-code
  1245. // number, a trigger count and a trigger count refresh value.
  1246. //
  1247. CfgRegReadString(FKC_DEBUG_TEST_CODE_NAME, NULL, 0, &WStr);
  1248. if (WStr != NULL) {
  1249. DebugInfo.TestCodeName = (wcslen(WStr)) ? FrsWtoA(WStr) : NULL;
  1250. WStr = FrsFree(WStr);
  1251. }
  1252. CfgRegReadDWord(FKC_DEBUG_TEST_CODE_NUMBER, NULL, 0, &DebugInfo.TestSubCodeNumber);
  1253. CfgRegReadDWord(FKC_DEBUG_TEST_TRIGGER_COUNT, NULL, 0, &DebugInfo.TestTriggerCount);
  1254. CfgRegReadDWord(FKC_DEBUG_TEST_TRIGGER_REFRESH, NULL, 0, &DebugInfo.TestTriggerRefresh);
  1255. }
  1256. VOID
  1257. DbgInitLogTraceFile(
  1258. IN LONG argc,
  1259. IN PWCHAR *argv
  1260. )
  1261. /*++
  1262. Routine Description:
  1263. Initialize enough of the debug subsystem to start the log file.
  1264. The rest can wait until we have synced up with the service controller.
  1265. Arguments:
  1266. argc - from main
  1267. argv - from main; in wide char format
  1268. Return Value:
  1269. None.
  1270. --*/
  1271. {
  1272. #undef DEBSUB
  1273. #define DEBSUB "DbgInitLogTraceFile:"
  1274. PWCHAR WStr;
  1275. PWCHAR File;
  1276. DWORD WStatus;
  1277. //
  1278. // Configure initial debug params until we read registry.
  1279. //
  1280. DebugInfo.AssertSeconds = 0;
  1281. DebugInfo.RestartSeconds = 0;
  1282. DebugInfo.Queues = 0;
  1283. DebugInfo.DbsOutOfSpace = DBG_DBS_OUT_OF_SPACE_OP_NONE;
  1284. DebugInfo.DbsOutOfSpaceTrigger = 0;
  1285. //
  1286. // Get the logging config params.
  1287. // Registry overrides defaults and CLI overrides registry.
  1288. //
  1289. //
  1290. // Disable Debug
  1291. //
  1292. CfgRegReadDWord(FKC_DEBUG_DISABLE, NULL, 0, &DebugInfo.Disabled);
  1293. if (FrsSearchArgv(argc, argv, L"disabledebug", NULL)) {
  1294. DebugInfo.Disabled = TRUE;
  1295. }
  1296. //
  1297. // Log File (really the dir containing the log files)
  1298. //
  1299. FrsSearchArgv(argc, argv, L"logfile", &DebugInfo.LogDir);
  1300. if (DebugInfo.LogDir == NULL) {
  1301. CfgRegReadString(FKC_DEBUG_LOG_FILE, NULL, 0, &DebugInfo.LogDir);
  1302. }
  1303. if (DebugInfo.LogDir != NULL) {
  1304. //
  1305. // Add the filename prefix to the end of the dir path.
  1306. //
  1307. DebugInfo.LogFile = FrsWcsCat(DebugInfo.LogDir, NTFRS_DBG_LOG_FILE);
  1308. } else {
  1309. DebugInfo.LogFile = NULL;
  1310. }
  1311. //
  1312. // Share for copying log/assert files
  1313. //
  1314. FrsSearchArgv(argc, argv, L"assertshare", &DebugInfo.AssertShare);
  1315. if (DebugInfo.AssertShare == NULL) {
  1316. CfgRegReadString(FKC_DEBUG_ASSERT_SHARE, NULL, 0, &DebugInfo.AssertShare);
  1317. }
  1318. //
  1319. // Copy log files into assert share
  1320. //
  1321. CfgRegReadDWord(FKC_DEBUG_COPY_LOG_FILES, NULL, 0, &DebugInfo.CopyLogs);
  1322. //
  1323. // Number of assert files
  1324. //
  1325. if (!FrsSearchArgvDWord(argc, argv, L"assertfiles", &DebugInfo.AssertFiles)) {
  1326. CfgRegReadDWord(FKC_DEBUG_ASSERT_FILES, NULL, 0, &DebugInfo.AssertFiles);
  1327. }
  1328. //
  1329. // Number of log files
  1330. //
  1331. if (!FrsSearchArgvDWord(argc, argv, L"logfiles", &DebugInfo.LogFiles)) {
  1332. CfgRegReadDWord(FKC_DEBUG_LOG_FILES, NULL, 0, &DebugInfo.LogFiles);
  1333. }
  1334. //
  1335. // Flush the trace log after every n lines.
  1336. //
  1337. if (!FrsSearchArgvDWord(argc, argv, L"logflushinterval", &DebugInfo.LogFlushInterval)) {
  1338. CfgRegReadDWord(FKC_DEBUG_LOG_FLUSH_INTERVAL, NULL, 0, &DebugInfo.LogFlushInterval);
  1339. }
  1340. //
  1341. // Create the dir path to the share where Assert Logs are copied.
  1342. //
  1343. if ((DebugInfo.AssertShare != NULL) &&
  1344. wcslen(DebugInfo.AssertShare) && wcslen(ComputerName)) {
  1345. WStr = FrsWcsCat3(DebugInfo.AssertShare, L"\\", ComputerName);
  1346. FrsFree(DebugInfo.AssertShare);
  1347. DebugInfo.AssertShare = WStr;
  1348. WStr = NULL;
  1349. }
  1350. //
  1351. // Severity for console print.
  1352. //
  1353. if (!FrsSearchArgvDWord(argc, argv, L"severity", &DebugInfo.Severity)) {
  1354. CfgRegReadDWord(FKC_DEBUG_SEVERITY, NULL, 0, &DebugInfo.Severity);
  1355. }
  1356. //
  1357. // Log Severity
  1358. //
  1359. if (!FrsSearchArgvDWord(argc, argv, L"logseverity", &DebugInfo.LogSeverity)) {
  1360. CfgRegReadDWord(FKC_DEBUG_LOG_SEVERITY, NULL, 0, &DebugInfo.LogSeverity);
  1361. }
  1362. //
  1363. // Systems - selected list of functions to trace. trace all if NULL.
  1364. //
  1365. DebugInfo.Systems = NULL;
  1366. if (!FrsSearchArgv(argc, argv, L"systems", &WStr)) {
  1367. CfgRegReadString(FKC_DEBUG_SYSTEMS, NULL, 0, &WStr);
  1368. }
  1369. if (WStr != NULL) {
  1370. DebugInfo.Systems = (wcslen(WStr)) ? FrsWtoA(WStr) : NULL;
  1371. WStr = FrsFree(WStr);
  1372. }
  1373. //
  1374. // Maximum Log Messages
  1375. //
  1376. DebugInfo.MaxLogLines = DEFAULT_DEBUG_MAX_LOG;
  1377. if (!FrsSearchArgvDWord(argc, argv, L"maxloglines", &DebugInfo.MaxLogLines)) {
  1378. CfgRegReadDWord(FKC_DEBUG_MAX_LOG, NULL, 0, &DebugInfo.MaxLogLines);
  1379. }
  1380. //
  1381. // Debugger serial line Print (assume suppress so no dprints leak out)
  1382. //
  1383. DebugInfo.Suppress = TRUE;
  1384. if (!FrsSearchArgv(argc, argv, L"debuggerprint", NULL)) {
  1385. CfgRegReadDWord(FKC_DEBUG_SUPPRESS, NULL, 0, &DebugInfo.Suppress);
  1386. } else {
  1387. DebugInfo.Suppress = FALSE;
  1388. }
  1389. //
  1390. // Enable break into debugger if present.
  1391. //
  1392. DebugInfo.Break = TRUE;
  1393. if (!FrsSearchArgv(argc, argv, L"break", NULL)) {
  1394. CfgRegReadDWord(FKC_DEBUG_BREAK, NULL, 0, &DebugInfo.Break);
  1395. }
  1396. //
  1397. // Turn on debug log if desired.
  1398. // Save old log files and open a new log file.
  1399. //
  1400. if (DebugInfo.LogFile != NULL) {
  1401. //
  1402. // Create the debug directory
  1403. //
  1404. if (!CreateDirectory(DebugInfo.LogDir, NULL)) {
  1405. WStatus = GetLastError();
  1406. if (!WIN_ALREADY_EXISTS(WStatus)) {
  1407. //
  1408. // Need some way to report the following.
  1409. //
  1410. //DPRINT1_WS(0, ":S: CreateDirectory(Logfile) %ws -- failed;",
  1411. // DebugInfo.LogFile, WStatus);
  1412. EPRINT1(EVENT_FRS_BAD_DEBUG_DIR, DebugInfo.LogDir);
  1413. DebugInfo.LogFile = FrsFree(DebugInfo.LogFile);
  1414. DebugInfo.LogDir = FrsFree(DebugInfo.LogDir);
  1415. }
  1416. }
  1417. if (DebugInfo.LogFile != NULL) {
  1418. DbgShiftLogFiles(DebugInfo.LogFile,
  1419. LOG_FILE_SUFFIX,
  1420. (DebugInfo.CopyLogs) ? DebugInfo.AssertShare : NULL,
  1421. DebugInfo.LogFiles);
  1422. DbgOpenLogFile();
  1423. }
  1424. }
  1425. //
  1426. // Executable's full path for symbols.
  1427. //
  1428. DbgExePathW[0] = L'\0';
  1429. if (GetFullPathNameW(argv[0], MAX_PATH-4, DbgExePathW, &File) == 0) {
  1430. DPRINT1(0, ":S: Could not get the full pathname for %ws\n", argv[0]);
  1431. }
  1432. if (!wcsstr(DbgExePathW, L".exe")) {
  1433. wcscat(DbgExePathW, L".exe");
  1434. }
  1435. DPRINT1(0, ":S: Full pathname for %ws\n", DbgExePathW);
  1436. if (_snprintf(DbgExePathA, sizeof(DbgExePathA), "%ws", DbgExePathW) < 0) {
  1437. DbgExePathA[sizeof(DbgExePathA) - 1] = '\0';
  1438. DPRINT1(0, ":S: Image path too long to get symbols for traceback: %ws\n", DbgExePathW);
  1439. return;
  1440. }
  1441. //
  1442. // Init the symbol support for stack traceback if we are tracking mem allocs.
  1443. // Don't use the memory subsystem until symbols are enabled
  1444. //
  1445. if (DebugInfo.Mem) {
  1446. DbgStackInit();
  1447. }
  1448. }
  1449. VOID
  1450. DbgMustInit(
  1451. IN LONG argc,
  1452. IN PWCHAR *argv
  1453. )
  1454. /*++
  1455. Routine Description:
  1456. Initialize the debug subsystem
  1457. Arguments:
  1458. argc - from main
  1459. argv - from main; in wide char format
  1460. Return Value:
  1461. None.
  1462. --*/
  1463. {
  1464. #undef DEBSUB
  1465. #define DEBSUB "DbgMustInit:"
  1466. ULONG Len;
  1467. LONG i;
  1468. PWCHAR Wcs;
  1469. PWCHAR WStr;
  1470. DWORD WStatus;
  1471. //
  1472. // Init the known thread array.
  1473. //
  1474. for (i = 0; i < ARRAY_SZ(KnownThreadArray); i++) {
  1475. KnownThreadArray[i].Name = NULL;
  1476. }
  1477. DbgCaptureThreadInfo2(L"First", NULL, GetCurrentThreadId());
  1478. //
  1479. // Get some config info for the debug log header.
  1480. //
  1481. OsInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
  1482. GetVersionExW((POSVERSIONINFOW) &OsInfo);
  1483. GetSystemInfo(&SystemInfo);
  1484. //
  1485. // When not running as a service, the exe will restart itself
  1486. // after an assertion failure. When running as a service, the
  1487. // service controller will restart the service.
  1488. //
  1489. // Rebuild the command line for restart.
  1490. //
  1491. if (!RunningAsAService) {
  1492. #define RESTART_PARAM L" /restart"
  1493. Len = wcslen(RESTART_PARAM) + 2;
  1494. for (i = 0; i < argc; ++i) {
  1495. Len += wcslen(argv[i]) + 1;
  1496. }
  1497. DebugInfo.CommandLine = FrsAlloc(Len * sizeof(WCHAR));
  1498. for (i = 0; i < argc; ++i) {
  1499. //
  1500. // Give our parent process time to die so that it will
  1501. // release its handles on the journal, database, ...
  1502. //
  1503. if (wcsstr(argv[i], L"restart")) {
  1504. Sleep(5 * 1000);
  1505. continue;
  1506. }
  1507. wcscat(DebugInfo.CommandLine, argv[i]);
  1508. wcscat(DebugInfo.CommandLine, L" ");
  1509. }
  1510. wcscat(DebugInfo.CommandLine, RESTART_PARAM);
  1511. }
  1512. //
  1513. // Get rest of config params. Command line takes precedence over registrr.
  1514. //
  1515. //
  1516. // Restart the service iff it has asserted and has run at least this long
  1517. // to avoid assert loops.
  1518. //
  1519. if (!FrsSearchArgvDWord(argc, argv, L"restartseconds", &DebugInfo.RestartSeconds)) {
  1520. CfgRegReadDWord(FKC_DEBUG_RESTART_SECONDS, NULL, 0, &DebugInfo.RestartSeconds);
  1521. }
  1522. //
  1523. // Sendmail recipient (future)
  1524. //
  1525. DebugInfo.Recipients = NULL;
  1526. CfgRegReadString(FKC_DEBUG_RECIPIENTS, NULL, 0, &WStr);
  1527. if (WStr != NULL) {
  1528. DebugInfo.Recipients = (wcslen(WStr)) ? FrsWtoA(WStr) : NULL;
  1529. WStr = FrsFree(WStr);
  1530. }
  1531. //
  1532. // Sendmail Profile (future)
  1533. //
  1534. DebugInfo.Profile = NULL;
  1535. CfgRegReadString(FKC_DEBUG_PROFILE, NULL, 0, &WStr);
  1536. if (WStr != NULL) {
  1537. DebugInfo.Profile = (wcslen(WStr)) ? FrsWtoA(WStr) : NULL;
  1538. WStr = FrsFree(WStr);
  1539. }
  1540. //
  1541. // Buildlab info
  1542. //
  1543. DebugInfo.BuildLab = NULL;
  1544. CfgRegReadString(FKC_DEBUG_BUILDLAB, NULL, 0, &WStr);
  1545. if (WStr != NULL) {
  1546. DebugInfo.BuildLab = (wcslen(WStr)) ? FrsWtoA(WStr) : NULL;
  1547. WStr = FrsFree(WStr);
  1548. }
  1549. //
  1550. // Use the hardwired config file if there is no Directory Service.
  1551. //
  1552. if (FrsSearchArgv(argc, argv, L"nods", &WStr)) {
  1553. NoDs = TRUE;
  1554. if (WStr != NULL) {
  1555. IniFileName = wcslen(WStr) ? WStr : NULL;
  1556. }
  1557. }
  1558. //
  1559. // Single machine is pretending to be several machines
  1560. //
  1561. if (FrsSearchArgv(argc, argv, L"server", &WStr)) {
  1562. if ((WStr != NULL) && (wcslen(WStr) > 0)) {
  1563. NoDs = TRUE;
  1564. ServerName = WStr;
  1565. }
  1566. }
  1567. #ifdef DS_FREE
  1568. NoDs = TRUE;
  1569. #endif DS_FREE
  1570. //
  1571. // The following parameters are testing / debugging.
  1572. //
  1573. //
  1574. // Check queues
  1575. //
  1576. DebugInfo.Queues = TRUE;
  1577. if (!FrsSearchArgv(argc, argv, L"queues", NULL)) {
  1578. CfgRegReadDWord(FKC_DEBUG_QUEUES, NULL, 0, &DebugInfo.Queues);
  1579. }
  1580. //
  1581. // Enable VvJoin Tests
  1582. //
  1583. DebugInfo.VvJoinTests = FrsSearchArgv(argc, argv, L"vvjointests", NULL);
  1584. //
  1585. // forcevvjoin on every join
  1586. //
  1587. DebugInfo.ForceVvJoin = FrsSearchArgv(argc, argv, L"vvjoin", NULL);
  1588. //
  1589. // Enable rename fid test
  1590. //
  1591. DebugInfo.TestFid = FrsSearchArgv(argc, argv, L"testfid", NULL);
  1592. //
  1593. // forceunjoin on one cxtion after N remote co's
  1594. //
  1595. DebugInfo.UnjoinTrigger = 0;
  1596. FrsSearchArgvDWord(argc, argv, L"unjoin", &DebugInfo.UnjoinTrigger);
  1597. //
  1598. // forceunjoin on one cxtion after N remote co's
  1599. //
  1600. DebugInfo.FetchRetryReset = 0;
  1601. if (!FrsSearchArgvDWord(argc, argv, L"fetchretry", &DebugInfo.FetchRetryReset)) {
  1602. }
  1603. DebugInfo.FetchRetryTrigger = DebugInfo.FetchRetryReset;
  1604. DebugInfo.FetchRetryInc = DebugInfo.FetchRetryReset;
  1605. //
  1606. // Set interval for toggling the schedule
  1607. //
  1608. FrsSearchArgvDWord(argc, argv, L"interval", &DebugInfo.Interval);
  1609. //
  1610. // Force an assert after N seconds (0 == don't assert)
  1611. //
  1612. DebugInfo.AssertSeconds = 0;
  1613. if (!FrsSearchArgvDWord(argc, argv, L"assertseconds", &DebugInfo.AssertSeconds)) {
  1614. CfgRegReadDWord(FKC_DEBUG_ASSERT_SECONDS, NULL, 0, &DebugInfo.AssertSeconds);
  1615. }
  1616. //
  1617. // Force REAL out of space errors on database operations
  1618. //
  1619. DebugInfo.DbsOutOfSpace = 0;
  1620. if (!FrsSearchArgvDWord(argc, argv, L"dbsoutOfSpace", &DebugInfo.DbsOutOfSpace)) {
  1621. CfgRegReadDWord(FKC_DEBUG_DBS_OUT_OF_SPACE, NULL, 0, &DebugInfo.DbsOutOfSpace);
  1622. }
  1623. //
  1624. // Trigger phoney out of space errors on database operations
  1625. //
  1626. DebugInfo.DbsOutOfSpaceTrigger = 0;
  1627. if (!FrsSearchArgvDWord(argc, argv, L"outofspacetrigger", &DebugInfo.DbsOutOfSpaceTrigger)) {
  1628. CfgRegReadDWord(FKC_DEBUG_DBS_OUT_OF_SPACE_TRIGGER, NULL, 0, &DebugInfo.DbsOutOfSpaceTrigger);
  1629. }
  1630. //
  1631. // Enable compression. Default will be on.
  1632. //
  1633. CfgRegReadDWord(FKC_DEBUG_DISABLE_COMPRESSION, NULL, 0, &DebugInfo.DisableCompression);
  1634. //
  1635. // Check if automatic cleanup of staging files is enabled or disabled.
  1636. //
  1637. CfgRegReadDWord(FKC_RECLAIM_STAGING_SPACE, NULL, 0, &DebugInfo.ReclaimStagingSpace);
  1638. //
  1639. // Check if a new value for outlog history time is set.
  1640. //
  1641. CfgRegReadDWord(FKC_OUTLOG_CHANGE_HISTORY, NULL, 0, &DebugInfo.OutlogChangeHistory);
  1642. //
  1643. // Check if saving outlog history is disabled.
  1644. //
  1645. CfgRegReadDWord(FKC_SAVE_OUTLOG_CHANGE_HISTORY, NULL, 0, &DebugInfo.SaveOutlogChangeHistory);
  1646. //
  1647. // Check if a new value for install override is set.
  1648. //
  1649. CfgRegReadDWord(FKC_ENABLE_INSTALL_OVERRIDE, NULL, 0, &DebugInfo.EnableInstallOverride);
  1650. //
  1651. // Check if a new value for forced rename on file updates is set.
  1652. //
  1653. CfgRegReadDWord(FKC_ENABLE_RENAME_BASED_UPDATES, NULL, 0, &DebugInfo.EnableRenameUpdates);
  1654. //
  1655. // Check if suppress identical updates is disabled.
  1656. //
  1657. CfgRegReadDWord(FKC_SUPPRESS_IDENTICAL_UPDATES, NULL, 0, &DebugInfo.SuppressIdenticalUpdt);
  1658. //
  1659. // Ldap Search timeout. Default is 10 minutes.
  1660. //
  1661. CfgRegReadDWord(FKC_LDAP_SEARCH_TIMEOUT_IN_MINUTES, NULL, 0, &LdapSearchTimeoutInMinutes);
  1662. //
  1663. // Ldap Bind timeout. Default is 30 seconds.
  1664. //
  1665. CfgRegReadDWord(FKC_LDAP_BIND_TIMEOUT_IN_SECONDS, NULL, 0, &LdapBindTimeoutInSeconds);
  1666. //
  1667. // Get boolean to tell us if we should do automatic restore when
  1668. // we hit journal wrap
  1669. //
  1670. CfgRegReadDWord(FKC_ENABLE_JOURNAL_WRAP_AUTOMATIC_RESTORE, NULL, 0, &DebugInfo.EnableJrnlWrapAutoRestore);
  1671. //
  1672. // Display the debug parameters.
  1673. //
  1674. DbgPrintInfo(0);
  1675. //
  1676. // Remember our start time (in minutes)
  1677. //
  1678. // 100-nsecs / (10 (microsecs) * 1000 (msecs) * 1000 (secs) * 60 (min)
  1679. //
  1680. GetSystemTimeAsFileTime((FILETIME *)&DebugInfo.StartSeconds);
  1681. DebugInfo.StartSeconds /= (10 * 1000 * 1000);
  1682. }
  1683. VOID
  1684. DbgMinimumInit(
  1685. VOID
  1686. )
  1687. /*++
  1688. Routine Description:
  1689. Called at the beginning of MainMinimumInit()
  1690. Arguments:
  1691. None.
  1692. Return Value:
  1693. None.
  1694. --*/
  1695. {
  1696. #undef DEBSUB
  1697. #define DEBSUB "DbgMinimumInit:"
  1698. HANDLE ThreadHandle;
  1699. DWORD ThreadId;
  1700. //
  1701. // This thread forces an assert after DebugInfo.AssertSeconds
  1702. //
  1703. if (DebugInfo.AssertSeconds) {
  1704. ThreadHandle = (HANDLE)CreateThread(NULL,
  1705. 0,
  1706. DbgForceAssert,
  1707. NULL,
  1708. 0,
  1709. &ThreadId);
  1710. FRS_ASSERT(HANDLE_IS_VALID(ThreadHandle));
  1711. DbgCaptureThreadInfo2(L"ForceAssert", DbgForceAssert, ThreadId);
  1712. FRS_CLOSE(ThreadHandle);
  1713. }
  1714. }
  1715. BOOL
  1716. DoDebug(
  1717. IN ULONG Sev,
  1718. IN UCHAR *DebSub
  1719. )
  1720. /*++
  1721. Routine Description:
  1722. Should we print this line
  1723. Arguments:
  1724. sev
  1725. debsub
  1726. Return Value:
  1727. None.
  1728. --*/
  1729. {
  1730. #undef DEBSUB
  1731. #define DEBSUB "DoDebug:"
  1732. //
  1733. // Debugging has been disabled
  1734. //
  1735. if (DebugInfo.Disabled) {
  1736. return FALSE;
  1737. }
  1738. //
  1739. // Not important enough
  1740. //
  1741. if (Sev > DebugInfo.Severity && Sev > DebugInfo.LogSeverity) {
  1742. return FALSE;
  1743. }
  1744. //
  1745. // Not tracing this subsystem
  1746. //
  1747. if (DebSub &&
  1748. DebugInfo.Systems &&
  1749. (strstr(DebugInfo.Systems, DebSub) == NULL)) {
  1750. return FALSE;
  1751. }
  1752. //
  1753. // Not tracing this thread
  1754. //
  1755. if (DebugInfo.ThreadId &&
  1756. GetCurrentThreadId() != DebugInfo.ThreadId) {
  1757. return FALSE;
  1758. }
  1759. return TRUE;
  1760. }
  1761. VOID
  1762. DebPrintLine(
  1763. IN ULONG Sev,
  1764. IN PCHAR Line
  1765. )
  1766. /*++
  1767. Routine Description:
  1768. Print a line of debug output to various combinations
  1769. of standard out, debugger, kernel debugger, and a log file.
  1770. Arguments:
  1771. Sev
  1772. Line
  1773. Return Value:
  1774. None.
  1775. --*/
  1776. {
  1777. #undef DEBSUB
  1778. #define DEBSUB "DebPrintLine:"
  1779. DWORD BytesWritten = 0;
  1780. //
  1781. // stdout
  1782. //
  1783. if ((Sev <= DebugInfo.Severity) && !RunningAsAService) {
  1784. printf("%s", Line);
  1785. }
  1786. //
  1787. // log file
  1788. //
  1789. if (HANDLE_IS_VALID(DebugInfo.LogFILE) && Sev <= DebugInfo.LogSeverity) {
  1790. //
  1791. // Number of messages exceeded; save the old file and
  1792. // start afresh. The existing old file is deleted.
  1793. //
  1794. if (DebugInfo.LogLines > DebugInfo.MaxLogLines) {
  1795. FrsFlushFile(L"LogFILE", DebugInfo.LogFILE);
  1796. DbgFlushInterval = DebugInfo.LogFlushInterval;
  1797. FRS_CLOSE(DebugInfo.LogFILE);
  1798. DbgShiftLogFiles(DebugInfo.LogFile,
  1799. LOG_FILE_SUFFIX,
  1800. (DebugInfo.CopyLogs) ? DebugInfo.AssertShare : NULL,
  1801. DebugInfo.LogFiles);
  1802. DbgOpenLogFile();
  1803. DebugInfo.LogLines = 0;
  1804. DebugInfo.PrintStats = TRUE;
  1805. }
  1806. if (HANDLE_IS_VALID(DebugInfo.LogFILE)) {
  1807. WriteFile(DebugInfo.LogFILE,
  1808. Line,
  1809. strlen(Line),
  1810. &BytesWritten,
  1811. NULL);
  1812. //
  1813. // Flush the log file every DebugInfo.LogFlushInterval lines and on
  1814. // every severity 0 message.
  1815. //
  1816. if ((--DbgFlushInterval < 0) || (Sev ==0)) {
  1817. if (!WIN_SUCCESS(FrsFlushFile(L"LogFILE", DebugInfo.LogFILE))) {
  1818. FRS_CLOSE(DebugInfo.LogFILE);
  1819. }
  1820. DbgFlushInterval = DebugInfo.LogFlushInterval;
  1821. }
  1822. }
  1823. }
  1824. //
  1825. // debugger
  1826. //
  1827. if ((Sev <= DebugInfo.Severity) && !DebugInfo.Suppress) {
  1828. OutputDebugStringA(Line);
  1829. }
  1830. }
  1831. BOOL
  1832. DebFormatLine(
  1833. IN ULONG Sev,
  1834. IN BOOL Format,
  1835. IN PCHAR DebSub,
  1836. IN UINT LineNo,
  1837. IN PCHAR Line,
  1838. IN ULONG LineSize,
  1839. IN PUCHAR Str,
  1840. IN va_list argptr
  1841. )
  1842. /*++
  1843. Routine Description:
  1844. Format the line of output
  1845. Arguments:
  1846. DebSub
  1847. LineNo
  1848. Line
  1849. LineSize
  1850. Str
  1851. Return Value:
  1852. None.
  1853. --*/
  1854. {
  1855. #undef DEBSUB
  1856. #define DEBSUB "DebFormatLine:"
  1857. ULONG LineUsed;
  1858. SYSTEMTIME SystemTime;
  1859. BOOL Ret = TRUE;
  1860. try {
  1861. if (Format) {
  1862. //
  1863. // Increment the line count here to prevent counting
  1864. // the several DPRINTs that don't have a newline.
  1865. //
  1866. ++DebugInfo.LogLines;
  1867. ++DebugInfo.TotalLogLines;
  1868. GetLocalTime(&SystemTime);
  1869. if (_snprintf(Line,
  1870. LineSize,
  1871. "<%-31s%4u: %5u: S%1u: %02d:%02d:%02d> ",
  1872. (DebSub) ? DebSub : "NoName",
  1873. GetCurrentThreadId(),
  1874. LineNo,
  1875. Sev,
  1876. SystemTime.wHour,
  1877. SystemTime.wMinute,
  1878. SystemTime.wSecond) < 0) {
  1879. Line[LineSize - 1] = '\0';
  1880. Ret = FALSE;
  1881. } else {
  1882. LineUsed = strlen(Line);
  1883. }
  1884. } else {
  1885. LineUsed = 0;
  1886. }
  1887. if (Ret) {
  1888. if (((LineUsed + 1) >= LineSize) ||
  1889. (_vsnprintf(Line + LineUsed, LineSize - LineUsed, Str, argptr) < 0)) {
  1890. Ret = FALSE;
  1891. }
  1892. }
  1893. } except(EXCEPTION_EXECUTE_HANDLER) {
  1894. Ret = FALSE;
  1895. }
  1896. return Ret;
  1897. }
  1898. BOOL
  1899. DebFormatTrackingLine(
  1900. IN PCHAR Line,
  1901. IN ULONG LineSize,
  1902. IN PUCHAR Str,
  1903. IN va_list argptr
  1904. )
  1905. /*++
  1906. Routine Description:
  1907. Format the line of output
  1908. Arguments:
  1909. Line
  1910. LineSize
  1911. Str
  1912. Return Value:
  1913. None.
  1914. --*/
  1915. {
  1916. #undef DEBSUB
  1917. #define DEBSUB "DebFormatTrackingLine:"
  1918. ULONG LineUsed = 0;
  1919. SYSTEMTIME SystemTime;
  1920. BOOL Ret = TRUE;
  1921. try {
  1922. //
  1923. // Increment the line count here to prevent counting
  1924. // the several DPRINTs that don't have a newline.
  1925. //
  1926. ++DebugInfo.LogLines;
  1927. ++DebugInfo.TotalLogLines;
  1928. GetLocalTime(&SystemTime);
  1929. if (_snprintf(Line,
  1930. LineSize,
  1931. "%2d/%2d-%02d:%02d:%02d ",
  1932. SystemTime.wMonth,
  1933. SystemTime.wDay,
  1934. SystemTime.wHour,
  1935. SystemTime.wMinute,
  1936. SystemTime.wSecond) < 0) {
  1937. Line[LineSize - 1] = '\0';
  1938. Ret = FALSE;
  1939. } else {
  1940. LineUsed = strlen(Line);
  1941. }
  1942. if (Ret) {
  1943. if (((LineUsed + 1) >= LineSize) ||
  1944. (_vsnprintf(Line + LineUsed, LineSize - LineUsed, Str, argptr) < 0)) {
  1945. Ret = FALSE;
  1946. }
  1947. }
  1948. } except(EXCEPTION_EXECUTE_HANDLER) {
  1949. Ret = FALSE;
  1950. }
  1951. return Ret;
  1952. }
  1953. VOID
  1954. DebPrintTrackingNoLock(
  1955. IN ULONG Sev,
  1956. IN PUCHAR Str,
  1957. IN ... )
  1958. /*++
  1959. Routine Description:
  1960. Format and print a line of tracking output to various combinations
  1961. of standard out, debugger, kernel debugger, and a log file. The
  1962. debug print lock is held and the caller filtered lines that
  1963. shouldn't be printed.
  1964. Arguments:
  1965. Sev - severity level
  1966. Str - printf format
  1967. Return Value:
  1968. None.
  1969. --*/
  1970. {
  1971. #undef DEBSUB
  1972. #define DEBSUB "DebPrintTrackingNoLock:"
  1973. CHAR Buf[512];
  1974. DWORD BufUsed = 0;
  1975. //
  1976. // varargs stuff
  1977. //
  1978. va_list argptr;
  1979. va_start(argptr, Str);
  1980. //
  1981. // Print the line to some combination of stdout, file, and debugger
  1982. //
  1983. if (DebFormatTrackingLine(Buf, sizeof(Buf), Str, argptr)) {
  1984. DebPrintLine(Sev, Buf);
  1985. }
  1986. va_end(argptr);
  1987. }
  1988. VOID
  1989. DebLock(
  1990. VOID
  1991. )
  1992. /*++
  1993. Routine Description:
  1994. Acquire the print lock
  1995. Arguments:
  1996. None.
  1997. Return Value:
  1998. None.
  1999. --*/
  2000. {
  2001. #undef DEBSUB
  2002. #define DEBSUB "DebLock:"
  2003. EnterCriticalSection(&DebugInfo.Lock);
  2004. }
  2005. BOOL
  2006. DebTryLock(
  2007. VOID
  2008. )
  2009. /*++
  2010. Routine Description:
  2011. Try to acquire the print lock
  2012. Arguments:
  2013. None.
  2014. Return Value:
  2015. None.
  2016. --*/
  2017. {
  2018. #undef DEBSUB
  2019. #define DEBSUB "DebTryLock:"
  2020. return TryEnterCriticalSection(&DebugInfo.Lock);
  2021. }
  2022. VOID
  2023. DebUnLock(
  2024. VOID
  2025. )
  2026. /*++
  2027. Routine Description:
  2028. Release the print lock
  2029. Arguments:
  2030. None.
  2031. Return Value:
  2032. None.
  2033. --*/
  2034. {
  2035. #undef DEBSUB
  2036. #define DEBSUB "DebUnLock:"
  2037. BOOL PrintStats;
  2038. //
  2039. // Print summary stats close to the beginning of each
  2040. // log file. The stats may show up a few lines into
  2041. // the new log file when callers hold the DebLock() across
  2042. // several lines.
  2043. //
  2044. // Be careful not to recurse if MaxLogLines is smaller
  2045. // than the number of lines in the stats.
  2046. //
  2047. if (DebugInfo.PrintStats) {
  2048. if (DebugInfo.PrintingStats) {
  2049. DebugInfo.PrintStats = FALSE;
  2050. } else {
  2051. DebugInfo.PrintingStats = TRUE;
  2052. }
  2053. }
  2054. PrintStats = DebugInfo.PrintStats;
  2055. LeaveCriticalSection(&DebugInfo.Lock);
  2056. if (PrintStats) {
  2057. DbgPrintAllStats();
  2058. EnterCriticalSection(&DebugInfo.Lock);
  2059. DebugInfo.PrintingStats = FALSE;
  2060. LeaveCriticalSection(&DebugInfo.Lock);
  2061. }
  2062. }
  2063. VOID
  2064. DebPrintNoLock(
  2065. IN ULONG Sev,
  2066. IN BOOL Format,
  2067. IN PUCHAR Str,
  2068. IN PCHAR DebSub,
  2069. IN UINT LineNo,
  2070. IN ... )
  2071. /*++
  2072. Routine Description:
  2073. Format and print a line of debug output to various combinations
  2074. of standard out, debugger, kernel debugger, and a log file. The
  2075. debug print lock is held and the caller filtered lines that
  2076. shouldn't be printed.
  2077. Arguments:
  2078. Sev - severity filter
  2079. Format - Add format info?
  2080. Str - printf format
  2081. DebSub - module name
  2082. LineNo
  2083. Return Value:
  2084. None.
  2085. --*/
  2086. {
  2087. #undef DEBSUB
  2088. #define DEBSUB "DebPrintNoLock:"
  2089. CHAR Buf[512];
  2090. DWORD BufUsed = 0;
  2091. //
  2092. // varargs stuff
  2093. //
  2094. va_list argptr;
  2095. va_start(argptr, LineNo);
  2096. //
  2097. // Print the line to some combination of stdout, file, and debugger
  2098. //
  2099. if (DebFormatLine(Sev, Format, DebSub, LineNo, Buf, sizeof(Buf), Str, argptr)) {
  2100. DebPrintLine(Sev, Buf);
  2101. }
  2102. va_end(argptr);
  2103. }
  2104. VOID
  2105. DebPrint(
  2106. IN ULONG Sev,
  2107. IN PUCHAR Str,
  2108. IN PCHAR DebSub,
  2109. IN UINT LineNo,
  2110. IN ... )
  2111. /*++
  2112. Routine Description:
  2113. Format and print a line of debug output to various combinations
  2114. of standard out, debugger, kernel debugger, and a log file.
  2115. Arguments:
  2116. sev - severity filter
  2117. str - printf format
  2118. debsub - module name
  2119. LineNo
  2120. Return Value:
  2121. None.
  2122. --*/
  2123. {
  2124. #undef DEBSUB
  2125. #define DEBSUB "DebPrint:"
  2126. CHAR Buf[512];
  2127. DWORD BufUsed = 0;
  2128. //
  2129. // varargs stuff
  2130. //
  2131. va_list argptr;
  2132. va_start(argptr, LineNo);
  2133. //
  2134. // Don't print this
  2135. //
  2136. if (!DoDebug(Sev, DebSub)) {
  2137. return;
  2138. }
  2139. //
  2140. // Print the line to some combination of stdout, file, and debugger
  2141. //
  2142. DebLock();
  2143. if (DebFormatLine(Sev, TRUE, DebSub, LineNo, Buf, sizeof(Buf), Str, argptr)) {
  2144. DebPrintLine(Sev, Buf);
  2145. }
  2146. DebUnLock();
  2147. va_end(argptr);
  2148. #if 0
  2149. static int failedload = FALSE;
  2150. static TRANSMITSPECIALFRAME_FN lpfnTransmitSpecialFrame = NULL;
  2151. //
  2152. // Calling nal.dll from inside lsa causes a deadlock during startup
  2153. //
  2154. if ( /* (!RunningAsAService) &&*/ // davidor - lets try it.
  2155. (NmDebugTest(sev, DebSub)))
  2156. {
  2157. if (failedload == FALSE) {
  2158. //
  2159. // Only try to load the NetMon trace routine once.
  2160. //
  2161. if (!lpfnTransmitSpecialFrame) {
  2162. HINSTANCE hInst;
  2163. hInst = LoadLibrary (L"NAL.DLL" );
  2164. if (hInst) {
  2165. lpfnTransmitSpecialFrame =
  2166. (TRANSMITSPECIALFRAME_FN)GetProcAddress ( hInst, "TransmitSpecialFrame" );
  2167. }
  2168. }
  2169. if (lpfnTransmitSpecialFrame) {
  2170. int length;
  2171. int length2;
  2172. unsigned char buff[256];
  2173. if (DebSub) {
  2174. length = _snprintf(buff, sizeof(buff), "<%s%u:%u> ", DebSub, tid, uLineNo);
  2175. buff[sizeof(buff) - 1] = '\0';
  2176. } else {
  2177. length = 0;
  2178. }
  2179. length2 = _vsnprintf(buff + length, sizeof(buff) - length, str, argptr );
  2180. lpfnTransmitSpecialFrame(FRAME_TYPE_COMMENT,
  2181. 0,
  2182. buff,
  2183. length + length2 + 1 );
  2184. } else {
  2185. failedload = TRUE; // that was our one and only try to load the routine.
  2186. }
  2187. }
  2188. }
  2189. #endif 0
  2190. }
  2191. VOID
  2192. DbgDoAssert(
  2193. IN PCHAR Exp,
  2194. IN UINT Line,
  2195. IN PCHAR Debsub
  2196. )
  2197. /*++
  2198. Routine Description:
  2199. Assertion failure; print a message and exit after allowing some
  2200. time for shutdown.
  2201. Arguments:
  2202. Exp - failing assertion expression
  2203. Line - line number of failing expression
  2204. Debsub - module name of failing expression
  2205. Return Value:
  2206. Doesn't return
  2207. --*/
  2208. {
  2209. #undef DEBSUB
  2210. #define DEBSUB "DbgDoAssert:"
  2211. PWCHAR ExpW;
  2212. PWCHAR DebsubW;
  2213. WCHAR LineW[32];
  2214. //
  2215. // Inform the world
  2216. //
  2217. FrsIsAsserting = TRUE;
  2218. ExpW = FrsAtoW(Exp);
  2219. DebsubW = FrsAtoW(Debsub);
  2220. _snwprintf(LineW, 32, L"%d", Line);
  2221. LineW[ARRAY_SZ(LineW)-1] = L'\0';
  2222. //
  2223. // Post an error log entry followed by recovery steps.
  2224. //
  2225. EPRINT3(EVENT_FRS_ASSERT, DebsubW, LineW, ExpW);
  2226. EPRINT1(EVENT_FRS_IN_ERROR_STATE, JetPath);
  2227. FrsFree(ExpW);
  2228. FrsFree(DebsubW);
  2229. //
  2230. // Stack trace
  2231. //
  2232. if (!DebugInfo.Mem) {
  2233. //
  2234. // Init the symbols here since mem alloc tracing is off.
  2235. //
  2236. DbgStackInit();
  2237. }
  2238. DbgPrintStackTrace(0, Debsub, Line);
  2239. //
  2240. // Failing expression
  2241. //
  2242. DebPrint(0, ":S: ASSERTION FAILURE: %s\n", Debsub, Line, Exp);
  2243. //
  2244. // Save the log file as an assert file
  2245. //
  2246. #if 0
  2247. // disable saving assert logs under separate name; too confusing
  2248. //
  2249. if (HANDLE_IS_VALID(DebugInfo.LogFILE)) {
  2250. DebLock();
  2251. FrsFlushFile(L"LogFILE", DebugInfo.LogFILE);
  2252. DbgFlushInterval = DebugInfo.LogFlushInterval;
  2253. FRS_CLOSE(DebugInfo.LogFILE);
  2254. DbgShiftLogFiles(DebugInfo.LogFile,
  2255. ASSERT_FILE_SUFFIX,
  2256. DebugInfo.AssertShare,
  2257. DebugInfo.AssertFiles);
  2258. DebugInfo.LogFILE = CreateFile(LogPath,
  2259. GENERIC_READ | GENERIC_WRITE,
  2260. FILE_SHARE_READ,
  2261. NULL,
  2262. CREATE_ALWAYS,
  2263. FILE_FLAG_BACKUP_SEMANTICS,
  2264. NULL);
  2265. DebugInfo.LogLines = 0;
  2266. DebugInfo.PrintStats = TRUE;
  2267. DebUnLock();
  2268. }
  2269. #endif 0
  2270. DEBUG_FLUSH();
  2271. //
  2272. // Break into the debugger, if any
  2273. //
  2274. if (DebugInfo.Break && IsDebuggerPresent()) {
  2275. DebugBreak();
  2276. }
  2277. //
  2278. // Shutting down during an assert seldom completes; a critical thread
  2279. // is usually the thread that has asserted. One can't simply return
  2280. // from an assert. So exit the process and trust jet and ntfrs to
  2281. // recover at start up.
  2282. //
  2283. // FrsIsShuttingDown = TRUE;
  2284. // SetEvent(ShutDownEvent);
  2285. // ExitThread(1);
  2286. //
  2287. // Raise an exception.
  2288. //
  2289. if (--DbgRaiseCount <= 0) {
  2290. exit(1);
  2291. }
  2292. XRAISEGENEXCEPTION( ERROR_OPERATION_ABORTED );
  2293. }
  2294. #endif