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.

4810 lines
121 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. frsalloc.c
  5. Abstract:
  6. Routines for allocating and freeing memory structures in the
  7. NT File Replication Service.
  8. Author:
  9. David Orbits (davidor) - 3-Mar-1997
  10. Revision History:
  11. --*/
  12. #include <ntreppch.h>
  13. #pragma hdrstop
  14. #undef DEBSUB
  15. #define DEBSUB "FRSALLOC:"
  16. #include <frs.h>
  17. #include <ntfrsapi.h>
  18. #include <info.h>
  19. #include <perrepsr.h>
  20. #pragma warning( disable:4102) // unreferenced label
  21. //
  22. // Check for allocation problems
  23. //
  24. #define DBG_NUM_MEM_STACK (8)
  25. #define MAX_MEM_ON_FREE_LIST (1024)
  26. #define MAX_MEM_INDEX (1024)
  27. #define FRS_DEB_PRINT(_f, _d) \
  28. DebPrintNoLock(Severity, TRUE, _f, Debsub, uLineNo, _d)
  29. #define FRS_DEB_PRINT2(_f, _d1, _d2) \
  30. DebPrintNoLock(Severity, TRUE, _f, Debsub, uLineNo, _d1, _d2)
  31. #define FRS_DEB_PRINT3(_f, _d1, _d2, _d3) \
  32. DebPrintNoLock(Severity, TRUE, _f, Debsub, uLineNo, _d1, _d2, _d3)
  33. CRITICAL_SECTION MemLock;
  34. typedef struct _MEM MEM, *PMEM;
  35. struct _MEM {
  36. PMEM Next;
  37. ULONG_PTR *Begin;
  38. ULONG_PTR *End;
  39. DWORD OrigSize;
  40. ULONG_PTR Stack[DBG_NUM_MEM_STACK];
  41. };
  42. PMEM MemList;
  43. PMEM FreeMemList;
  44. DWORD MemOnFreeList;
  45. DWORD TotalAlloced;
  46. DWORD TotalAllocCalls;
  47. DWORD TotalFreed;
  48. DWORD TotalFreeCalls;
  49. DWORD TotalDelta;
  50. DWORD TotalDeltaMax;
  51. DWORD TotalTrigger = 10000;
  52. ULONG TypesAllocatedCount[NODE_TYPE_MAX];
  53. ULONG TypesAllocatedMax[NODE_TYPE_MAX];
  54. ULONG TypesAllocated[NODE_TYPE_MAX];
  55. ULONG SizesAllocatedCount[MAX_MEM_INDEX];
  56. ULONG SizesAllocatedMax[MAX_MEM_INDEX];
  57. ULONG SizesAllocated[MAX_MEM_INDEX];
  58. ULONG DbgBreakSize = 2;
  59. LONG DbgBreakTrigger = 1;
  60. LONG DbgBreakReset = 1;
  61. LONG DbgBreakResetInc = 0;
  62. PULONG_PTR MaxAllocAddr;
  63. PULONG_PTR MinAllocAddr;
  64. DWORD ReAllocs;
  65. DWORD NewAllocs;
  66. //
  67. // Keep these in the same order as the Node Type ENUM.
  68. //
  69. PCHAR NodeTypeNames[]= {
  70. "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
  71. "THREAD_CONTEXT_TYPE",
  72. "REPLICA_TYPE",
  73. "REPLICA_THREAD_TYPE",
  74. "CONFIG_NODE_TYPE",
  75. "CXTION_TYPE",
  76. "GUID/RPC HANDLE",
  77. "THREAD_TYPE",
  78. "GEN_TABLE_TYPE",
  79. "JBUFFER_TYPE",
  80. "VOLUME_MONITOR_ENTRY_TYPE",
  81. "COMMAND_PACKET_TYPE",
  82. "GENERIC_HASH_TABLE_TYPE",
  83. "CHANGE_ORDER_ENTRY_TYPE",
  84. "FILTER_TABLE_ENTRY_TYPE",
  85. "QHASH_TABLE_TYPE",
  86. "OUT_LOG_PARTNER_TYPE",
  87. "WILDCARD_FILTER_ENTRY_TYPE",
  88. "NODE_TYPE_MAX"
  89. };
  90. extern PCHAR CoLocationNames[];
  91. extern FLAG_NAME_TABLE StageFlagNameTable[];
  92. extern FLAG_NAME_TABLE OlpFlagNameTable[];
  93. extern PCHAR OLPartnerStateNames[];
  94. extern PWCHAR DsConfigTypeName[];
  95. extern PGEN_TABLE VolSerialNumberToDriveTable;
  96. VOID
  97. FrsDisplayUsnReason(
  98. ULONG ReasonMask,
  99. PCHAR Buffer,
  100. LONG MaxLength
  101. );
  102. PFRS_THREAD
  103. ThSupEnumThreads(
  104. PFRS_THREAD FrsThread
  105. );
  106. VOID
  107. DbgPrintThreadIds(
  108. IN ULONG Severity
  109. );
  110. VOID
  111. DbsDataInitCocExtension(
  112. IN PCHANGE_ORDER_RECORD_EXTENSION CocExt
  113. );
  114. VOID
  115. SndCsDestroyCxtion(
  116. IN PCXTION Cxtion,
  117. IN DWORD CxtionFlags
  118. );
  119. VOID
  120. FrsInitializeMemAlloc(
  121. VOID
  122. )
  123. /*++
  124. Routine Description:
  125. Initialize the memory allocation subsystem
  126. Arguments:
  127. None.
  128. Return Value:
  129. None.
  130. --*/
  131. {
  132. #undef DEBSUB
  133. #define DEBSUB "FrsInitializeMemAlloc:"
  134. InitializeCriticalSection(&MemLock);
  135. //
  136. // Get Debugmem and DebugMemCompact from ntfrs config section in the registry
  137. //
  138. CfgRegReadDWord(FKC_DEBUG_MEM, NULL, 0, &DebugInfo.Mem);
  139. CfgRegReadDWord(FKC_DEBUG_MEM_COMPACT, NULL, 0, &DebugInfo.MemCompact);
  140. }
  141. VOID
  142. FrsPrintAllocStats(
  143. IN ULONG Severity,
  144. IN PNTFRSAPI_INFO Info, OPTIONAL
  145. IN DWORD Tabs
  146. )
  147. /*++
  148. Routine Description:
  149. Print the memory stats into the info buffer or using DPRINT (Info == NULL).
  150. Arguments:
  151. Severity - for DPRINT
  152. Info - for IPRINT (use DPRINT if NULL)
  153. Tabs - indentation for prettyprint
  154. Return Value:
  155. None.
  156. --*/
  157. {
  158. #undef DEBSUB
  159. #define DEBSUB "FrsPrintAllocStats:"
  160. ULONG i;
  161. WCHAR TabW[MAX_TAB_WCHARS + 1];
  162. InfoTabs(Tabs, TabW);
  163. IDPRINT0(Severity, Info, "\n");
  164. IDPRINT1(Severity, Info, "%wsNTFRS MEMORY USAGE:\n", TabW);
  165. IDPRINT2(Severity, Info, "%ws ENABLE STATS : %s\n",
  166. TabW,
  167. (DebugInfo.Mem) ? "TRUE" : "FALSE");
  168. IDPRINT3(Severity, Info, "%ws Alloced : %6d KB (%d calls)\n",
  169. TabW,
  170. TotalAlloced / 1024,
  171. TotalAllocCalls);
  172. IDPRINT3(Severity, Info, "%ws Freed : %6d KB (%d calls)\n",
  173. TabW,
  174. TotalFreed / 1024,
  175. TotalFreeCalls);
  176. IDPRINT2(Severity, Info, "%ws Delta : %6d KB\n",
  177. TabW,
  178. TotalDelta / 1024);
  179. IDPRINT2(Severity, Info, "%ws Max delta : %6d KB\n",
  180. TabW,
  181. TotalDeltaMax / 1024);
  182. IDPRINT2(Severity, Info, "%ws Addr Range : %6d KB\n",
  183. TabW,
  184. (((PCHAR)MaxAllocAddr) - ((PCHAR)MinAllocAddr)) / 1024);
  185. IDPRINT2(Severity, Info, "%ws OnFreeList : %d\n", TabW, MemOnFreeList);
  186. IDPRINT2(Severity, Info, "%ws ReAllocs : %d\n", TabW, ReAllocs);
  187. IDPRINT2(Severity, Info, "%ws NewAllocs : %d\n", TabW, NewAllocs);
  188. IDPRINT2(Severity, Info, "%ws MinAddr : 0x%08x\n", TabW, MinAllocAddr);
  189. IDPRINT2(Severity, Info, "%ws MaxAddr : 0x%08x\n", TabW, MaxAllocAddr);
  190. for (i = 0; i < NODE_TYPE_MAX; ++i) {
  191. if (!TypesAllocatedCount[i]) {
  192. continue;
  193. }
  194. IDPRINT5(Severity, Info, "%ws %-26s: %6d Calls, %6d Max, %6d busy\n",
  195. TabW, NodeTypeNames[i], TypesAllocatedCount[i],
  196. TypesAllocatedMax[i], TypesAllocated[i]);
  197. }
  198. IDPRINT0(Severity, Info, "\n");
  199. for (i = 0; i < MAX_MEM_INDEX; ++i) {
  200. if (!SizesAllocatedCount[i]) {
  201. continue;
  202. }
  203. IDPRINT6(Severity, Info, "%ws %6d to %6d : %6d Calls, %6d Max, %6d busy\n",
  204. TabW, i << 4, ((i + 1) << 4) - 1,
  205. SizesAllocatedCount[i], SizesAllocatedMax[i], SizesAllocated[i]);
  206. }
  207. IDPRINT0(Severity, Info, "\n");
  208. }
  209. VOID
  210. FrsPrintThreadStats(
  211. IN ULONG Severity,
  212. IN PNTFRSAPI_INFO Info, OPTIONAL
  213. IN DWORD Tabs
  214. )
  215. /*++
  216. Routine Description:
  217. Print the thread stats into the info buffer or using DPRINT (Info == NULL).
  218. Arguments:
  219. Severity - for DPRINT
  220. Info - for IPRINT (use DPRINT if NULL)
  221. Tabs - indentation for prettyprint
  222. Return Value:
  223. None.
  224. --*/
  225. {
  226. #undef DEBSUB
  227. #define DEBSUB "FrsPrintThreadStats:"
  228. ULONGLONG CreateTime;
  229. ULONGLONG ExitTime;
  230. ULONGLONG KernelTime;
  231. ULONGLONG UserTime;
  232. PFRS_THREAD FrsThread;
  233. WCHAR TabW[MAX_TAB_WCHARS + 1];
  234. InfoTabs(Tabs, TabW);
  235. IDPRINT0(Severity, Info, "\n");
  236. IDPRINT1(Severity, Info, "%wsNTFRS THREAD USAGE:\n", TabW);
  237. //
  238. // Thread CPU Times
  239. //
  240. FrsThread = NULL;
  241. while (FrsThread = ThSupEnumThreads(FrsThread)) {
  242. if (HANDLE_IS_VALID(FrsThread->Handle)) {
  243. if (GetThreadTimes(FrsThread->Handle,
  244. (PFILETIME)&CreateTime,
  245. (PFILETIME)&ExitTime,
  246. (PFILETIME)&KernelTime,
  247. (PFILETIME)&UserTime)) {
  248. //
  249. // Hasn't exited, yet
  250. //
  251. if (ExitTime < CreateTime) {
  252. ExitTime = CreateTime;
  253. }
  254. IDPRINT5(Severity, Info, "%ws %-15ws: %8d CPU Seconds (%d kernel, %d elapsed)\n",
  255. TabW,
  256. FrsThread->Name,
  257. (DWORD)((KernelTime + UserTime) / (10 * 1000 * 1000)),
  258. (DWORD)((KernelTime) / (10 * 1000 * 1000)),
  259. (DWORD)((ExitTime - CreateTime) / (10 * 1000 * 1000)));
  260. }
  261. }
  262. }
  263. //
  264. // Process CPU Times
  265. //
  266. if (GetProcessTimes(ProcessHandle,
  267. (PFILETIME)&CreateTime,
  268. (PFILETIME)&ExitTime,
  269. (PFILETIME)&KernelTime,
  270. (PFILETIME)&UserTime)) {
  271. //
  272. // Hasn't exited, yet
  273. //
  274. if (ExitTime < CreateTime) {
  275. ExitTime = CreateTime;
  276. }
  277. IDPRINT5(Severity, Info, "%ws %-15ws: %8d CPU Seconds (%d kernel, %d elapsed)\n",
  278. TabW,
  279. L"PROCESS",
  280. (DWORD)((KernelTime + UserTime) / (10 * 1000 * 1000)),
  281. (DWORD)((KernelTime) / (10 * 1000 * 1000)),
  282. (DWORD)((ExitTime - CreateTime) / (10 * 1000 * 1000)));
  283. }
  284. IDPRINT0(Severity, Info, "\n");
  285. }
  286. VOID
  287. FrsPrintStageStats(
  288. IN ULONG Severity,
  289. IN PNTFRSAPI_INFO Info, OPTIONAL
  290. IN DWORD Tabs
  291. )
  292. /*++
  293. Routine Description:
  294. Print the staging area stats into the info buffer or
  295. using DPRINT (Info == NULL).
  296. Arguments:
  297. Severity - for DPRINT
  298. Info - for IPRINT (use DPRINT if NULL)
  299. Tabs - indentation for prettyprint
  300. Return Value:
  301. None.
  302. --*/
  303. {
  304. #undef DEBSUB
  305. #define DEBSUB "FrsPrintStageStats:"
  306. PVOID Key;
  307. PSTAGE_ENTRY SEntry;
  308. DWORD SizeInKb;
  309. WCHAR TabW[MAX_TAB_WCHARS + 1];
  310. CHAR Guid[GUID_CHAR_LEN + 1];
  311. extern DWORD StagingAreaAllocated;
  312. extern PGEN_TABLE StagingAreaTable;
  313. InfoTabs(Tabs, TabW);
  314. try {
  315. GTabLockTable(StagingAreaTable);
  316. IDPRINT0(Severity, Info, "\n");
  317. IDPRINT3(Severity, Info, "%wsNTFRS STAGE USAGE: %d KB of %d KB allocated\n",
  318. TabW, StagingAreaAllocated, StagingLimitInKb);
  319. SizeInKb = 0;
  320. Key = NULL;
  321. while (SEntry = GTabNextDatumNoLock(StagingAreaTable, &Key)) {
  322. GuidToStr(&SEntry->FileOrCoGuid, Guid);
  323. IDPRINT2(Severity, Info, "%ws %s\n", TabW, Guid);
  324. IDPRINT2(Severity, Info, "%ws Flags: %08x\n", TabW, SEntry->Flags);
  325. IDPRINT2(Severity, Info, "%ws Size : %d\n", TabW, SEntry->FileSizeInKb);
  326. SizeInKb += SEntry->FileSizeInKb;
  327. }
  328. IDPRINT2(Severity, Info, "%ws Calculated Usage is %d KB\n", TabW, SizeInKb);
  329. IDPRINT0(Severity, Info, "\n");
  330. } finally {
  331. GTabUnLockTable(StagingAreaTable);
  332. }
  333. }
  334. VOID
  335. MyDbgBreak(
  336. VOID
  337. )
  338. {
  339. }
  340. VOID
  341. DbgCheck(
  342. IN PMEM Mem
  343. )
  344. /*++
  345. Routine Description:
  346. Check a memory block. Memory lock must be held.
  347. Arguments:
  348. Mem - memory block
  349. Return Value:
  350. None.
  351. --*/
  352. {
  353. #undef DEBSUB
  354. #define DEBSUB "DbgCheck:"
  355. PULONG_PTR pDWord;
  356. ULONG_PTR Pattern;
  357. //
  358. // Begins at first byte at the end of the user's allocation
  359. //
  360. Pattern = (ULONG_PTR)(Mem->End) | (Mem->OrigSize << 24);
  361. //
  362. // Check for overwritten memory
  363. //
  364. if ( (ULONG_PTR)*Mem->Begin != (ULONG_PTR)Mem->Begin ) {
  365. DPRINT2(0, "Begin Memory @ 0x%08x has been overwritten with 0x%08x\n",
  366. Mem->Begin, *Mem->Begin);
  367. } else if (memcmp(((PCHAR)Mem->Begin) + Mem->OrigSize + 8,
  368. (PCHAR)&Pattern, sizeof(Pattern))) {
  369. DPRINT1(0, "End Memory @ 0x%08x has been overwritten\n",
  370. ((PCHAR)Mem->Begin) + Mem->OrigSize + 8);
  371. } else {
  372. return;
  373. }
  374. DPRINT(0, "Memory's stack trace\n");
  375. STACK_PRINT(0, Mem->Stack, DBG_NUM_MEM_STACK);
  376. DPRINT(0, "Caller's stack trace\n");
  377. STACK_TRACE_AND_PRINT(0);
  378. DPRINT(0, "Corrupted block of memory\n");
  379. for (pDWord = Mem->Begin; pDWord != Mem->End; ++pDWord) {
  380. DPRINT2(0, "0x%08x: 0x%08x\n", pDWord, *pDWord);
  381. }
  382. exit(1);
  383. }
  384. VOID
  385. DbgCheckAll(
  386. VOID
  387. )
  388. /*++
  389. Routine Description:
  390. Check all memory blocks.
  391. Arguments:
  392. Mem - memory block
  393. Return Value:
  394. None.
  395. --*/
  396. {
  397. #undef DEBSUB
  398. #define DEBSUB "DbgCheckAll:"
  399. PMEM Mem;
  400. //
  401. // Don't check the entire list of allocated memory blocks
  402. //
  403. if (DebugInfo.Mem < 2) {
  404. return;
  405. }
  406. EnterCriticalSection(&MemLock);
  407. for (Mem = MemList; Mem; Mem = Mem->Next) {
  408. //
  409. // Check for overwritten memory
  410. //
  411. DbgCheck(Mem);
  412. }
  413. LeaveCriticalSection(&MemLock);
  414. }
  415. VOID
  416. FrsUnInitializeMemAlloc(
  417. VOID
  418. )
  419. /*++
  420. Routine Description:
  421. Initialize the memory allocation subsystem
  422. Arguments:
  423. None.
  424. Return Value:
  425. None.
  426. --*/
  427. {
  428. #undef DEBSUB
  429. #define DEBSUB "FrsUnInitializeMemAlloc:"
  430. PMEM Mem;
  431. EnterCriticalSection(&MemLock);
  432. for (Mem = MemList; Mem; Mem = Mem->Next) {
  433. //
  434. // Check for overwritten memory
  435. //
  436. DbgCheck(Mem);
  437. DPRINT2(1, "\t%d bytes @ 0x%08x\n",
  438. ((PCHAR)Mem->End) - ((PCHAR)Mem->Begin), Mem->Begin);
  439. STACK_PRINT(1, Mem->Stack, DBG_NUM_MEM_STACK);
  440. }
  441. LeaveCriticalSection(&MemLock);
  442. }
  443. PMEM
  444. DbgAlloc(
  445. IN ULONG_PTR *Begin,
  446. IN ULONG_PTR *End,
  447. IN DWORD OrigSize
  448. )
  449. /*++
  450. Routine Description:
  451. Add a new allocation to our list of allocated memory after
  452. checking for overlaps.
  453. Arguments:
  454. Begin - beginning of newly allocated memory
  455. End - end of same
  456. OrigSize - Size requested by caller
  457. Return Value:
  458. None.
  459. --*/
  460. {
  461. #undef DEBSUB
  462. #define DEBSUB "DbgAlloc:"
  463. PMEM *PMem;
  464. PMEM Mem;
  465. ULONG Calls;
  466. ULONG_PTR Pattern;
  467. DWORD MemIndex;
  468. //
  469. // Approximate stats
  470. //
  471. if (!DebugInfo.Mem) {
  472. //
  473. // Memory stats
  474. //
  475. Calls = ++TotalAllocCalls;
  476. TotalAlloced += (DWORD)((PUCHAR)End - (PUCHAR)Begin);
  477. if (Begin > MaxAllocAddr) {
  478. ++NewAllocs;
  479. MaxAllocAddr = Begin;
  480. } else {
  481. if (!MinAllocAddr) {
  482. MinAllocAddr = Begin;
  483. }
  484. ++ReAllocs;
  485. }
  486. //
  487. // Tracking memory sizes
  488. //
  489. MemIndex = OrigSize >> 4;
  490. if (MemIndex >= MAX_MEM_INDEX) {
  491. MemIndex = (MAX_MEM_INDEX - 1);
  492. }
  493. SizesAllocatedCount[MemIndex]++;
  494. //
  495. // Print memory stats every so often
  496. //
  497. if (!(Calls % TotalTrigger)) {
  498. DbgPrintThreadIds(DebugInfo.LogSeverity);
  499. FrsPrintAllocStats(DebugInfo.LogSeverity, NULL, 0);
  500. }
  501. return NULL;
  502. }
  503. //
  504. // Verify heap consistency
  505. //
  506. DbgCheckAll();
  507. EnterCriticalSection(&MemLock);
  508. PMem = &MemList;
  509. for (Mem = *PMem; Mem; Mem = *PMem) {
  510. //
  511. // Check for overwritten memory
  512. //
  513. DbgCheck(Mem);
  514. //
  515. // Check for overlap
  516. //
  517. if ((Begin >= Mem->Begin && Begin < Mem->End) ||
  518. (Mem->Begin >= Begin && Mem->Begin < End) ||
  519. (Mem->End > Begin && Mem->End < End) ||
  520. (End > Mem->Begin && End < Mem->End)) {
  521. //
  522. // DUP ALLOCATION (OVERLAP DETECTED)
  523. // Release lock in case DPRINT calls allocation routines
  524. //
  525. LeaveCriticalSection(&MemLock);
  526. DPRINT4(0, "ERROR -- DUP ALLOC: 0x%x to 0x%x is already allocated to 0x%x to 0x%x; EXITING\n",
  527. Begin, End, Mem->Begin, Mem->End);
  528. FRS_ASSERT(!"Duplicate memory allocation");
  529. }
  530. //
  531. // This memory should be linked later in the sorted memory list
  532. //
  533. if (Begin > Mem->Begin) {
  534. PMem = &Mem->Next;
  535. continue;
  536. }
  537. //
  538. // This memory should be linked here in the sorted memory list
  539. //
  540. break;
  541. }
  542. //
  543. // Allocate a memory block header
  544. //
  545. Mem = FreeMemList;
  546. if (Mem) {
  547. --MemOnFreeList;
  548. FreeMemList = Mem->Next;
  549. } else {
  550. Mem = (PVOID)malloc(sizeof(MEM));
  551. if (Mem == NULL) {
  552. RaiseException(ERROR_OUTOFMEMORY, 0, 0, NULL);
  553. }
  554. ZeroMemory(Mem, sizeof(MEM));
  555. }
  556. //
  557. // Initialize the header and the header/trailer for memory overrun detection.
  558. //
  559. Mem->OrigSize = OrigSize;
  560. Mem->End = End;
  561. Mem->Begin = Begin;
  562. //
  563. // Initialize the header/trailer for memory overrun detection.
  564. //
  565. *Mem->Begin = (ULONG_PTR)Begin;
  566. *(Mem->Begin + 1) = OrigSize;
  567. Pattern = (ULONG_PTR)(Mem->End) | (Mem->OrigSize << 24);
  568. CopyMemory(((PCHAR)Begin) + Mem->OrigSize + 8, (PCHAR)&Pattern, sizeof(Pattern));
  569. //
  570. // Add to sorted list
  571. //
  572. Mem->Next = *PMem;
  573. *PMem = Mem;
  574. //
  575. // Note: stackwalk won't work from here; see frsalloctype()
  576. //
  577. // DbgStackTrace(Mem->Stack, DBG_NUM_MEM_STACK)
  578. //
  579. // Memory stats
  580. //
  581. Calls = ++TotalAllocCalls;
  582. TotalAlloced += (DWORD)((PUCHAR)End - (PUCHAR)Begin);
  583. TotalDelta = TotalAlloced - TotalFreed;
  584. if (TotalDelta > TotalDeltaMax) {
  585. TotalDeltaMax = TotalDelta;
  586. }
  587. if (Begin > MaxAllocAddr) {
  588. ++NewAllocs;
  589. MaxAllocAddr = Begin;
  590. } else {
  591. if (!MinAllocAddr) {
  592. MinAllocAddr = Begin;
  593. }
  594. ++ReAllocs;
  595. }
  596. //
  597. // Tracking memory sizes
  598. //
  599. MemIndex = OrigSize >> 4;
  600. if (MemIndex >= MAX_MEM_INDEX) {
  601. MemIndex = (MAX_MEM_INDEX - 1);
  602. }
  603. SizesAllocated[MemIndex]++;
  604. SizesAllocatedCount[MemIndex]++;
  605. if (SizesAllocated[MemIndex] > SizesAllocatedMax[MemIndex]) {
  606. SizesAllocatedMax[MemIndex] = SizesAllocated[MemIndex];
  607. }
  608. //
  609. // Done
  610. //
  611. LeaveCriticalSection(&MemLock);
  612. //
  613. // Print memory stats every so often
  614. //
  615. if (!(Calls % TotalTrigger)) {
  616. DbgPrintThreadIds(DebugInfo.LogSeverity);
  617. FrsPrintAllocStats(DebugInfo.LogSeverity, NULL, 0);
  618. }
  619. DbgCheckAll();
  620. return Mem;
  621. }
  622. VOID
  623. DbgFree(
  624. IN PULONG_PTR Begin
  625. )
  626. /*++
  627. Routine Description:
  628. Remove allocated memory from list
  629. Arguments:
  630. Begin - allocated (maybe) memory
  631. Return Value:
  632. TRUE - found it
  633. FALSE - didn't find it
  634. --*/
  635. {
  636. #undef DEBSUB
  637. #define DEBSUB "DbgFree:"
  638. PMEM *PMem;
  639. PMEM Mem;
  640. DWORD MemIndex;
  641. //
  642. // Freeing NULL pointer is allowed
  643. //
  644. if (Begin == NULL || !DebugInfo.Mem) {
  645. return;
  646. }
  647. DbgCheckAll();
  648. EnterCriticalSection(&MemLock);
  649. PMem = &MemList;
  650. for (Mem = *PMem; Mem; Mem = *PMem) {
  651. //
  652. // Check for overwritten memory
  653. //
  654. DbgCheck(Mem);
  655. //
  656. // Not the right one
  657. //
  658. if (Begin > Mem->Begin) {
  659. PMem = &Mem->Next;
  660. continue;
  661. }
  662. if (Begin != Mem->Begin) {
  663. break;
  664. }
  665. //
  666. // Found it; remove from list and free it
  667. //
  668. ++TotalFreeCalls;
  669. TotalFreed += (DWORD)((PUCHAR)Mem->End - (PUCHAR)Mem->Begin);
  670. TotalDelta = TotalAlloced - TotalFreed;
  671. MemIndex = Mem->OrigSize >> 4;
  672. if (MemIndex >= MAX_MEM_INDEX) {
  673. MemIndex = (MAX_MEM_INDEX - 1);
  674. }
  675. SizesAllocated[MemIndex]--;
  676. *PMem = Mem->Next;
  677. if (MemOnFreeList > MAX_MEM_ON_FREE_LIST) {
  678. free(Mem);
  679. } else {
  680. ++MemOnFreeList;
  681. Mem->Next = FreeMemList;
  682. FreeMemList = Mem;
  683. }
  684. LeaveCriticalSection(&MemLock);
  685. DbgCheckAll();
  686. return;
  687. }
  688. LeaveCriticalSection(&MemLock);
  689. DPRINT1(0, "ERROR -- Memory @ 0x%x is not allocated\n", Begin);
  690. FRS_ASSERT(!"Memory free error, not allocated");
  691. }
  692. BOOL
  693. DbgIsAlloc(
  694. IN PULONG_PTR Begin
  695. )
  696. /*++
  697. Routine Description:
  698. Is Begin alloced?
  699. Arguments:
  700. Begin - allocated (maybe) memory
  701. Return Value:
  702. TRUE - found it
  703. FALSE - didn't find it
  704. --*/
  705. {
  706. #undef DEBSUB
  707. #define DEBSUB "DbgIsAlloc:"
  708. PMEM *PMem;
  709. PMEM Mem;
  710. if (!DebugInfo.Mem) {
  711. return TRUE;
  712. }
  713. //
  714. // NULL pointer is always alloced
  715. //
  716. if (Begin == NULL) {
  717. return TRUE;
  718. }
  719. DbgCheckAll();
  720. EnterCriticalSection(&MemLock);
  721. PMem = &MemList;
  722. for (Mem = *PMem; Mem; Mem = *PMem) {
  723. //
  724. // Check for overwritten memory
  725. //
  726. DbgCheck(Mem);
  727. //
  728. // Not the right one
  729. //
  730. if (Begin > Mem->Begin) {
  731. PMem = &Mem->Next;
  732. continue;
  733. }
  734. if (Begin != Mem->Begin) {
  735. break;
  736. }
  737. LeaveCriticalSection(&MemLock);
  738. DbgCheckAll();
  739. return TRUE;
  740. }
  741. LeaveCriticalSection(&MemLock);
  742. DbgCheckAll();
  743. return FALSE;
  744. }
  745. PVOID
  746. FrsAlloc(
  747. IN DWORD OrigSize
  748. )
  749. /*++
  750. Routine Description:
  751. Allocate memory. Raise an exception if there is no memory.
  752. Arguments:
  753. Size - size of the memory request
  754. Return Value:
  755. Allocated memory.
  756. --*/
  757. {
  758. #undef DEBSUB
  759. #define DEBSUB "FrsAlloc:"
  760. PVOID Node;
  761. DWORD Size;
  762. PMEM Mem;
  763. //
  764. // FRS_ASSERT is added here to satisfy prefix. The return value from FrsAlloc is not checked anywhere
  765. // in the code.
  766. //
  767. FRS_ASSERT(OrigSize != 0);
  768. Size = OrigSize;
  769. if (DebugInfo.Mem) {
  770. //
  771. // Check for debug break
  772. //
  773. if (OrigSize == DbgBreakSize) {
  774. if (DbgBreakTrigger) {
  775. if (--DbgBreakTrigger <= 0) {
  776. DbgBreakTrigger = DbgBreakReset;
  777. DbgBreakReset += DbgBreakResetInc;
  778. MyDbgBreak();
  779. }
  780. }
  781. }
  782. //
  783. // Adjust size for header/trailer
  784. //
  785. Size = (((OrigSize + 7) >> 3) << 3) + 16;
  786. }
  787. //
  788. // Raise an exception if there is no memory
  789. //
  790. Node = (PVOID)malloc(Size);
  791. if (Node == NULL) {
  792. RaiseException(ERROR_OUTOFMEMORY, 0, 0, NULL);
  793. }
  794. ZeroMemory(Node, Size);
  795. //
  796. // Even with mem alloc tracing off call DbgAlloc to capture mem alloc stats.
  797. //
  798. Mem = DbgAlloc(Node, (PULONG_PTR)(((PCHAR)Node) + Size), OrigSize);
  799. //
  800. // Note: should be in dbgalloc(); but stackwalk won't work
  801. //
  802. if (DebugInfo.Mem) {
  803. DbgStackTrace(Mem->Stack, DBG_NUM_MEM_STACK);
  804. ((PCHAR)Node) += 8;
  805. }
  806. return Node;
  807. }
  808. PVOID
  809. FrsRealloc(
  810. PVOID OldNode,
  811. DWORD OrigSize
  812. )
  813. /*++
  814. Routine Description:
  815. Reallocate memory. Raise an exception if there is no memory.
  816. Arguments:
  817. Size - size of the memory request
  818. Return Value:
  819. Reallocated memory.
  820. --*/
  821. {
  822. #undef DEBSUB
  823. #define DEBSUB "FrsRealloc:"
  824. PVOID Node;
  825. DWORD Size;
  826. PMEM Mem;
  827. if (!OldNode) {
  828. //
  829. // Need to check if OrigSize == 0 as FrsAlloc asserts if called with 0 as the first parameter (prefix fix).
  830. //
  831. if (OrigSize == 0) {
  832. return NULL;
  833. }
  834. return FrsAlloc(OrigSize);
  835. }
  836. Size = OrigSize;
  837. if (DebugInfo.Mem) {
  838. ((PCHAR)OldNode) -= 8;
  839. DbgFree(OldNode);
  840. //
  841. // Adjust size for header/trailer
  842. //
  843. Size = (((OrigSize + 7) >> 3) << 3) + 16;
  844. }
  845. //
  846. // Raise an exception if there is no memory
  847. //
  848. Node = (PVOID)realloc(OldNode, Size);
  849. if (Node == NULL) {
  850. RaiseException(ERROR_OUTOFMEMORY, 0, 0, NULL);
  851. }
  852. //
  853. // Even with mem alloc tracing off call DbgAlloc to capture mem alloc stats.
  854. //
  855. Mem = DbgAlloc(Node, (PULONG_PTR)(((PCHAR)Node) + Size), OrigSize);
  856. //
  857. // Note: should be in dbgalloc(); but stackwalk won't work
  858. //
  859. if (DebugInfo.Mem) {
  860. DbgStackTrace(Mem->Stack, DBG_NUM_MEM_STACK);
  861. ((PCHAR)Node) += 8;
  862. }
  863. return Node;
  864. }
  865. PVOID
  866. FrsFree(
  867. PVOID Node
  868. )
  869. /*++
  870. Routine Description:
  871. Free memory allocated with FrsAlloc
  872. Arguments:
  873. Node - memory allocated with FrsAlloc
  874. Return Value:
  875. None.
  876. --*/
  877. {
  878. #undef DEBSUB
  879. #define DEBSUB "FrsFree:"
  880. if (!Node) {
  881. return NULL;
  882. }
  883. if (DebugInfo.Mem) {
  884. ((PCHAR)Node) -= 8;
  885. DbgFree(Node);
  886. }
  887. free(Node);
  888. if (DebugInfo.MemCompact) {
  889. HeapCompact(GetProcessHeap(), 0);
  890. }
  891. return NULL;
  892. }
  893. PCHAR
  894. FrsWtoA(
  895. PWCHAR Wstr
  896. )
  897. /*++
  898. Routine Description:
  899. Translate a wide char string into a newly allocated char string.
  900. Arguments:
  901. Wstr - wide char string
  902. Return Value:
  903. Duplicated string. Free with FrsFree().
  904. --*/
  905. {
  906. #undef DEBSUB
  907. #define DEBSUB "FrsWtoA:"
  908. PCHAR Astr;
  909. //
  910. // E.g., when duplicating NodePartner when none exists
  911. //
  912. if (Wstr == NULL)
  913. return NULL;
  914. Astr = FrsAlloc(wcslen(Wstr) + 1);
  915. sprintf(Astr, "%ws", Wstr);
  916. return Astr;
  917. }
  918. PWCHAR
  919. FrsWcsTrim(
  920. PWCHAR Wstr,
  921. WCHAR Trim
  922. )
  923. /*++
  924. Routine Description:
  925. Remove the Trim char from the trailing end of the string by replacing
  926. any occurance with a L'\0'.
  927. Skip over any leading Trim chars and return a ptr to the first non-TRIM
  928. char found. If we hit the end of the string return the pointer to
  929. the terminating null.
  930. Arguments:
  931. Wstr - wide char string
  932. Trim - Char to trim.
  933. Return Value:
  934. ptr to first non Trim char.
  935. --*/
  936. {
  937. #undef DEBSUB
  938. #define DEBSUB "FrsWcsTrim:"
  939. LONG Len, Index;
  940. if (Wstr == NULL)
  941. return NULL;
  942. //
  943. //
  944. Len = wcslen(Wstr);
  945. Index = Len - 1;
  946. while (Index >= 0) {
  947. if (Wstr[Index] != Trim) {
  948. break;
  949. }
  950. Index--;
  951. }
  952. Wstr[++Index] = UNICODE_NULL;
  953. Len = Index;
  954. Index = 0;
  955. while (Index < Len) {
  956. if (Wstr[Index] != Trim) {
  957. break;
  958. }
  959. Index++;
  960. }
  961. return Wstr + Index;
  962. }
  963. PWCHAR
  964. FrsAtoW(
  965. PCHAR Astr
  966. )
  967. /*++
  968. Routine Description:
  969. Translate a wide char string into a newly allocated char string.
  970. Arguments:
  971. Wstr - wide char string
  972. Return Value:
  973. Duplicated string. Free with FrsFree().
  974. --*/
  975. {
  976. PWCHAR Wstr;
  977. //
  978. // E.g., when duplicating NodePartner when none exists
  979. //
  980. if (Astr == NULL) {
  981. return NULL;
  982. }
  983. Wstr = FrsAlloc((strlen(Astr) + 1) * sizeof(WCHAR));
  984. swprintf(Wstr, L"%hs", Astr);
  985. return Wstr;
  986. }
  987. PWCHAR
  988. FrsWcsDup(
  989. PWCHAR OldStr
  990. )
  991. /*++
  992. Routine Description:
  993. Duplicate a string using our memory allocater
  994. Arguments:
  995. OldArg - string to duplicate
  996. Return Value:
  997. Duplicated string. Free with FrsFree().
  998. --*/
  999. {
  1000. #undef DEBSUB
  1001. #define DEBSUB "FrsWcsDup:"
  1002. PWCHAR NewStr;
  1003. //
  1004. // E.g., when duplicating NodePartner when none exists
  1005. //
  1006. if (OldStr == NULL) {
  1007. return NULL;
  1008. }
  1009. NewStr = FrsAlloc((wcslen(OldStr) + 1) * sizeof(WCHAR));
  1010. wcscpy(NewStr, OldStr);
  1011. return NewStr;
  1012. }
  1013. VOID
  1014. FrsBuildVolSerialNumberToDriveTable(
  1015. VOID
  1016. )
  1017. /*++
  1018. Routine Description:
  1019. New way to get the current configuration from the DS and merge it with
  1020. the active replicas.
  1021. Arguments:
  1022. None.
  1023. Return Value:
  1024. None.
  1025. --*/
  1026. {
  1027. #undef DEBSUB
  1028. #define DEBSUB "FrsBuildVolSerialNumberToDriveTable:"
  1029. ULONG MaxFileNameLen;
  1030. DWORD FileSystemFlags;
  1031. PWCHAR DrivePtr = NULL;
  1032. DWORD WStatus;
  1033. PVOLUME_INFO_NODE VolumeInfoNode;
  1034. UINT DriveType;
  1035. ULONG VolumeSerialNumber = 0;
  1036. WCHAR LogicalDrives[MAX_PATH];
  1037. WCHAR VolumeGuidName[MAX_PATH];
  1038. //
  1039. // Initialize the VolSerialNumberToDriveTable.
  1040. //
  1041. if (VolSerialNumberToDriveTable == NULL) {
  1042. VolSerialNumberToDriveTable = GTabAllocNumberTable();
  1043. }
  1044. //
  1045. // Get the logical drive strings.
  1046. //
  1047. if (!GetLogicalDriveStrings(MAX_PATH, LogicalDrives) || (VolSerialNumberToDriveTable == NULL)) {
  1048. DPRINT_WS(1, "WARN - Getting logical drives. It may not be possible to start on this server.", GetLastError());
  1049. return;
  1050. }
  1051. //
  1052. // Lock the table during rebuild to synchronize with the many callers of
  1053. // FrsWcsVolume() in other threads.
  1054. //
  1055. GTabLockTable(VolSerialNumberToDriveTable);
  1056. GTabEmptyTableNoLock(VolSerialNumberToDriveTable, FrsFree);
  1057. DrivePtr = LogicalDrives;
  1058. while (wcscmp(DrivePtr,L"")) {
  1059. DriveType = GetDriveType(DrivePtr);
  1060. //
  1061. // Skip remote drives and CDROM drives.
  1062. //
  1063. if ((DriveType == DRIVE_REMOTE) || (DriveType == DRIVE_CDROM)) {
  1064. DPRINT1(4, "Skipping Drive %ws. Invalid drive type.\n", DrivePtr);
  1065. DrivePtr = DrivePtr + wcslen(DrivePtr) + 1;
  1066. continue;
  1067. }
  1068. if (!GetVolumeInformation(DrivePtr,
  1069. VolumeGuidName,
  1070. MAX_PATH,
  1071. &VolumeSerialNumber,
  1072. &MaxFileNameLen,
  1073. &FileSystemFlags,
  1074. NULL,
  1075. 0)){
  1076. DPRINT1_WS(1,"WARN - GetvolumeInformation for %ws;", DrivePtr, GetLastError());
  1077. DrivePtr = DrivePtr + wcslen(DrivePtr) + 1;
  1078. continue;
  1079. }
  1080. VolumeInfoNode = FrsAlloc(sizeof(VOLUME_INFO_NODE));
  1081. wcscpy(VolumeInfoNode->DriveName, L"\\\\.\\");
  1082. wcscat(VolumeInfoNode->DriveName, DrivePtr);
  1083. //
  1084. // Remove the trailing back slash.
  1085. //
  1086. VolumeInfoNode->DriveName[wcslen(VolumeInfoNode->DriveName) - 1] = L'\0';
  1087. VolumeInfoNode->VolumeSerialNumber = VolumeSerialNumber;
  1088. GTabInsertEntryNoLock(VolSerialNumberToDriveTable, VolumeInfoNode, &(VolumeInfoNode->VolumeSerialNumber), NULL);
  1089. DrivePtr = DrivePtr + wcslen(DrivePtr) + 1;
  1090. }
  1091. GTabUnLockTable(VolSerialNumberToDriveTable);
  1092. return;
  1093. }
  1094. PWCHAR
  1095. FrsWcsVolume(
  1096. PWCHAR Path
  1097. )
  1098. /*++
  1099. Routine Description:
  1100. Get the drive from the VolSerialNumberToDriveTable. The volume serial
  1101. number is used to locate the drive since a mount point can take us to
  1102. another drive.
  1103. Arguments:
  1104. Path
  1105. Return Value:
  1106. Duplicated string containing drive:\ from Path or NULL.
  1107. --*/
  1108. {
  1109. #undef DEBSUB
  1110. #define DEBSUB "FrsWcsVolume:"
  1111. PWCHAR Volume = NULL;
  1112. HANDLE DirHandle;
  1113. DWORD WStatus;
  1114. NTSTATUS Status;
  1115. IO_STATUS_BLOCK IoStatusBlock;
  1116. DWORD VolumeInfoLength;
  1117. PFILE_FS_VOLUME_INFORMATION VolumeInfo;
  1118. PVOLUME_INFO_NODE VolumeInfoNode;
  1119. //
  1120. // Get the volume Guid for the path.
  1121. //
  1122. // Always open the path by masking off the FILE_OPEN_REPARSE_POINT flag
  1123. // because we want to open the destination dir not the junction if the root
  1124. // happens to be a mount point.
  1125. //
  1126. WStatus = FrsOpenSourceFileW(&DirHandle,
  1127. Path,
  1128. GENERIC_READ,
  1129. FILE_OPEN_FOR_BACKUP_INTENT);
  1130. CLEANUP1_WS(4,"ERROR - Could not open %ws;", Path, WStatus, RETURN);
  1131. VolumeInfoLength = sizeof(FILE_FS_VOLUME_INFORMATION) +
  1132. MAXIMUM_VOLUME_LABEL_LENGTH;
  1133. VolumeInfo = FrsAlloc(VolumeInfoLength);
  1134. Status = NtQueryVolumeInformationFile(DirHandle,
  1135. &IoStatusBlock,
  1136. VolumeInfo,
  1137. VolumeInfoLength,
  1138. FileFsVolumeInformation);
  1139. NtClose(DirHandle);
  1140. if (NT_SUCCESS(Status)) {
  1141. //
  1142. // Build the table if it does not yet exist. This table is rebuilt at the
  1143. // start of each DS poll cycle so we have updated information about
  1144. // the volumes on the machine.
  1145. //
  1146. if (VolSerialNumberToDriveTable == NULL) {
  1147. FrsBuildVolSerialNumberToDriveTable();
  1148. }
  1149. VolumeInfoNode = GTabLookup(VolSerialNumberToDriveTable, &(VolumeInfo->VolumeSerialNumber), NULL);
  1150. if (VolumeInfoNode) {
  1151. Volume = FrsWcsDup(VolumeInfoNode->DriveName);
  1152. }
  1153. } else {
  1154. DPRINT1_NT(1,"WARN - NtQueryVolumeInformationFile failed for %ws;", Path, Status);
  1155. }
  1156. VolumeInfo = FrsFree(VolumeInfo);
  1157. RETURN:
  1158. return Volume;
  1159. }
  1160. PWCHAR
  1161. FrsWcsCat3(
  1162. PWCHAR First,
  1163. PWCHAR Second,
  1164. PWCHAR Third
  1165. )
  1166. /*++
  1167. Routine Description:
  1168. Concatenate three strings into a new string using our memory allocater
  1169. Arguments:
  1170. First - First string in the concat
  1171. Second - Second string in the concat
  1172. Third - Third string in the concat
  1173. Return Value:
  1174. Return concatenated string. Free with FrsFree().
  1175. --*/
  1176. {
  1177. #undef DEBSUB
  1178. #define DEBSUB "FrsWcscat3:"
  1179. PCHAR New;
  1180. DWORD BytesFirst;
  1181. DWORD BytesSecond;
  1182. DWORD BytesThird;
  1183. if (!First || !Second || !Third) {
  1184. return NULL;
  1185. }
  1186. //
  1187. // Allocate a buffer for the concatentated string
  1188. //
  1189. BytesFirst = wcslen(First) * sizeof(WCHAR);
  1190. BytesSecond = wcslen(Second) * sizeof(WCHAR);
  1191. BytesThird = (wcslen(Third) + 1) * sizeof(WCHAR);
  1192. New = (PCHAR)FrsAlloc(BytesFirst + BytesSecond + BytesThird);
  1193. CopyMemory(&New[0], First, BytesFirst);
  1194. CopyMemory(&New[BytesFirst], Second, BytesSecond);
  1195. CopyMemory(&New[BytesFirst + BytesSecond], Third, BytesThird);
  1196. return (PWCHAR)New;
  1197. }
  1198. PWCHAR
  1199. FrsWcsCat(
  1200. PWCHAR First,
  1201. PWCHAR Second
  1202. )
  1203. /*++
  1204. Routine Description:
  1205. Concatenate two strings into a new string using our memory allocater
  1206. Arguments:
  1207. First - First string in the concat
  1208. Second - Second string in the concat
  1209. Return Value:
  1210. Duplicated and concatentated string. Free with FrsFree().
  1211. --*/
  1212. {
  1213. #undef DEBSUB
  1214. #define DEBSUB "FrsWcscat:"
  1215. DWORD Bytes;
  1216. PWCHAR New;
  1217. FRS_ASSERT(First != NULL && Second != NULL);
  1218. // size of new string
  1219. Bytes = (wcslen(First) + wcslen(Second) + 1) * sizeof(WCHAR);
  1220. New = (PWCHAR)FrsAlloc(Bytes);
  1221. // Not as efficient as I would like but this routine is seldom used
  1222. wcscpy(New, First);
  1223. wcscat(New, Second);
  1224. return New;
  1225. }
  1226. PCHAR
  1227. FrsCsCat(
  1228. PCHAR First,
  1229. PCHAR Second
  1230. )
  1231. /*++
  1232. Routine Description:
  1233. Concatenate two strings into a new string using our memory allocater
  1234. Arguments:
  1235. First - First string in the concat
  1236. Second - Second string in the concat
  1237. Return Value:
  1238. Duplicated and concatentated string. Free with FrsFree().
  1239. --*/
  1240. {
  1241. #undef DEBSUB
  1242. #define DEBSUB "FrsCscat:"
  1243. DWORD Bytes;
  1244. PCHAR New;
  1245. FRS_ASSERT(First != NULL && Second != NULL);
  1246. // size of new string
  1247. Bytes = strlen(First) + strlen(Second) + 1;
  1248. New = (PCHAR)FrsAlloc(Bytes);
  1249. // Not as efficient as I would like but this routine is seldom used
  1250. strcpy(New, First);
  1251. strcat(New, Second);
  1252. return New;
  1253. }
  1254. PWCHAR
  1255. FrsWcsPath(
  1256. PWCHAR First,
  1257. PWCHAR Second
  1258. )
  1259. /*++
  1260. Routine Description:
  1261. Concatenate two strings into a pathname
  1262. Arguments:
  1263. First - First string in the concat
  1264. Second - Second string in the concat
  1265. Return Value:
  1266. Dup of First\Second. Free with FrsFree();
  1267. --*/
  1268. {
  1269. #undef DEBSUB
  1270. #define DEBSUB "FrsWcsPath:"
  1271. return FrsWcsCat3(First, L"\\", Second);
  1272. }
  1273. PCHAR
  1274. FrsCsPath(
  1275. PCHAR First,
  1276. PCHAR Second
  1277. )
  1278. /*++
  1279. Routine Description:
  1280. Concatenate two strings into a pathname
  1281. Arguments:
  1282. First - First string in the concat
  1283. Second - Second string in the concat
  1284. Return Value:
  1285. Duplicated and concatentated string. Free with FrsFree().
  1286. --*/
  1287. {
  1288. #undef DEBSUB
  1289. #define DEBSUB "FrsCsPath:"
  1290. PCHAR TmpPath;
  1291. PCHAR FinalPath;
  1292. //
  1293. // Very inefficient but seldom called
  1294. //
  1295. TmpPath = FrsCsCat(First, "\\");
  1296. FinalPath = FrsCsCat(TmpPath, Second);
  1297. FrsFree(TmpPath);
  1298. return FinalPath;
  1299. }
  1300. PVOID
  1301. FrsAllocTypeSize(
  1302. IN NODE_TYPE NodeType,
  1303. IN ULONG SizeDelta
  1304. )
  1305. /*++
  1306. Routine Description:
  1307. This routine allocates memory for the given node type and performs any
  1308. node specific initialization/allocation. The node is zeroed and the
  1309. size/type fields are filled in.
  1310. Arguments:
  1311. NodeType - The type of node to allocate.
  1312. SizeDelta - The amount of storage to allocate in ADDITION to the base type.
  1313. Return Value:
  1314. The node address is returned here. An exception is raised if
  1315. memory could not be allocated.
  1316. --*/
  1317. {
  1318. #undef DEBSUB
  1319. #define DEBSUB "FrsAllocTypeSize:"
  1320. PVOID Node;
  1321. ULONG NodeSize;
  1322. PREPLICA Replica;
  1323. PREPLICA_THREAD_CTX RtCtx;
  1324. PTHREAD_CTX ThreadCtx;
  1325. PTABLE_CTX TableCtx;
  1326. ULONG i;
  1327. PJBUFFER Jbuffer;
  1328. PVOLUME_MONITOR_ENTRY pVme;
  1329. PFILTER_TABLE_ENTRY FilterEntry;
  1330. PQHASH_TABLE QhashTable;
  1331. PCXTION Cxtion;
  1332. PCONFIG_NODE ConfigNode;
  1333. PCHANGE_ORDER_ENTRY ChangeOrder;
  1334. PGHANDLE GHandle;
  1335. PWILDCARD_FILTER_ENTRY WildcardEntry;
  1336. switch (NodeType) {
  1337. //
  1338. // Allocate a Thread Context struct
  1339. //
  1340. case THREAD_CONTEXT_TYPE:
  1341. NodeSize = sizeof(THREAD_CTX);
  1342. Node = FrsAlloc(NodeSize);
  1343. //
  1344. // No session or DB open yet.
  1345. //
  1346. ThreadCtx = (PTHREAD_CTX) Node;
  1347. ThreadCtx->JSesid = JET_sesidNil;
  1348. ThreadCtx->JDbid = JET_dbidNil;
  1349. ThreadCtx->JInstance = GJetInstance;
  1350. FrsRtlInitializeList(&ThreadCtx->ThreadCtxListHead);
  1351. break;
  1352. //
  1353. // Allocate a Replica struct and the config table ctx struct.
  1354. //
  1355. case REPLICA_TYPE:
  1356. NodeSize = sizeof(REPLICA);
  1357. Node = FrsAlloc(NodeSize);
  1358. Replica = (PREPLICA) Node;
  1359. //
  1360. // Config record flags (CONFIG_FLAG_... in schema.h)
  1361. //
  1362. SetFlag(Replica->CnfFlags, CONFIG_FLAG_MULTIMASTER);
  1363. InitializeCriticalSection(&Replica->ReplicaLock);
  1364. FrsRtlInitializeList(&Replica->ReplicaCtxListHead);
  1365. InitializeListHead(&Replica->FileNameFilterHead);
  1366. InitializeListHead(&Replica->FileNameInclFilterHead);
  1367. InitializeListHead(&Replica->DirNameFilterHead);
  1368. InitializeListHead(&Replica->DirNameInclFilterHead);
  1369. Replica->ConfigTable.TableType = TABLE_TYPE_INVALID;
  1370. DbsAllocTableCtx(ConfigTablex, &Replica->ConfigTable);
  1371. Replica->VVector = GTabAllocTable();
  1372. Replica->Cxtions = GTabAllocTable();
  1373. Replica->FStatus = FrsErrorSuccess;
  1374. Replica->Consistent = TRUE;
  1375. InitializeCriticalSection(&Replica->OutLogLock);
  1376. InitializeListHead(&Replica->OutLogEligible);
  1377. InitializeListHead(&Replica->OutLogStandBy);
  1378. InitializeListHead(&Replica->OutLogActive);
  1379. InitializeListHead(&Replica->OutLogInActive);
  1380. Replica->OutLogWorkState = OL_REPLICA_INITIALIZING;
  1381. Replica->ServiceState = REPLICA_STATE_ALLOCATED;
  1382. Replica->OutLogJLx = 1;
  1383. //
  1384. // No preinstall directory, yet
  1385. //
  1386. Replica->PreInstallHandle = INVALID_HANDLE_VALUE;
  1387. //
  1388. // Initialize the NewStage fiend.
  1389. //
  1390. Replica->NewStage = NULL;
  1391. //
  1392. // Initialize InitSyncCxtionsMasterList and InitSyncCxtionsWorkingList.
  1393. //
  1394. Replica->InitSyncCxtionsMasterList = NULL;
  1395. Replica->InitSyncCxtionsWorkingList = NULL;
  1396. Replica->InitSyncQueue = NULL;
  1397. //
  1398. // Add memory for the counter data structure, set the back pointer
  1399. // and bump ref count.
  1400. //
  1401. Replica->PerfRepSetData =
  1402. (PHT_REPLICA_SET_DATA) FrsAlloc (sizeof(HT_REPLICA_SET_DATA));
  1403. Replica->PerfRepSetData->RepBackPtr = Replica;
  1404. InterlockedIncrement(&Replica->ReferenceCount);
  1405. break;
  1406. //
  1407. // Allocate a Replica Thread Context struct and the table context structs.
  1408. //
  1409. case REPLICA_THREAD_TYPE:
  1410. NodeSize = sizeof(REPLICA_THREAD_CTX);
  1411. Node = FrsAlloc(NodeSize);
  1412. //
  1413. // Get the base of the array of TableCtx structs from the replica thread
  1414. // context struct and the base of the table create structs.
  1415. //
  1416. RtCtx = (PREPLICA_THREAD_CTX) Node;
  1417. TableCtx = RtCtx->RtCtxTables;
  1418. //
  1419. // Open the initial set of tables for the replica set.
  1420. //
  1421. for (i=0; i<TABLE_TYPE_MAX; ++i, ++TableCtx) {
  1422. //
  1423. // Marking the TableType as INVALID causes DbsAllocTableCtx()
  1424. // to allocate the DB support structs on the first call.
  1425. //
  1426. TableCtx->TableType = TABLE_TYPE_INVALID;
  1427. //
  1428. // If the SizeDelta parameter is non-zero then do not allocate
  1429. // the TableCtx internal structs. The caller will do it.
  1430. //
  1431. if (SizeDelta == 0) {
  1432. DbsAllocTableCtx(i, TableCtx);
  1433. } else {
  1434. //
  1435. // Mark table as not open by a session yet.
  1436. //
  1437. TableCtx->Tid = JET_tableidNil;
  1438. TableCtx->Sesid = JET_sesidNil;
  1439. TableCtx->ReplicaNumber = FRS_UNDEFINED_REPLICA_NUMBER;
  1440. }
  1441. }
  1442. break;
  1443. //
  1444. // Allocate a topology node
  1445. //
  1446. case CONFIG_NODE_TYPE:
  1447. NodeSize = sizeof(CONFIG_NODE);
  1448. Node = FrsAlloc(NodeSize);
  1449. ConfigNode = (PCONFIG_NODE) Node;
  1450. ConfigNode->Consistent = TRUE;
  1451. break;
  1452. //
  1453. // Allocate a connection
  1454. //
  1455. case CXTION_TYPE:
  1456. NodeSize = sizeof(CXTION);
  1457. Node = FrsAlloc(NodeSize);
  1458. Cxtion = Node;
  1459. Cxtion->CoeTable = GTabAllocTable();
  1460. //
  1461. // Allocate memory for the counter data structure
  1462. //
  1463. Cxtion->PerfRepConnData =
  1464. (PHT_REPLICA_CONN_DATA) FrsAlloc (sizeof(HT_REPLICA_CONN_DATA));
  1465. break;
  1466. //
  1467. // Allocate a list of bound rpc handles indexed by server guid
  1468. //
  1469. case GHANDLE_TYPE:
  1470. NodeSize = sizeof(GHANDLE);
  1471. Node = FrsAlloc(NodeSize);
  1472. GHandle = Node;
  1473. InitializeCriticalSection(&GHandle->Lock);
  1474. break;
  1475. //
  1476. // Allocate a generic table
  1477. //
  1478. case GEN_TABLE_TYPE:
  1479. NodeSize = sizeof(GEN_TABLE);
  1480. Node = FrsAlloc(NodeSize);
  1481. break;
  1482. //
  1483. // Allocate a generic thread context
  1484. //
  1485. case THREAD_TYPE:
  1486. NodeSize = sizeof(FRS_THREAD);
  1487. Node = FrsAlloc(NodeSize);
  1488. break;
  1489. //
  1490. // Allocate a journal read buffer.
  1491. //
  1492. case JBUFFER_TYPE:
  1493. NodeSize = SizeOfJournalBuffer;
  1494. Node = FrsAlloc(NodeSize);
  1495. //
  1496. // Init the data buffer size and start address.
  1497. //
  1498. Jbuffer = (PJBUFFER) Node;
  1499. Jbuffer->BufferSize = NodeSize - SizeOfJournalBufferDesc;
  1500. Jbuffer->DataBuffer = &Jbuffer->Buffer[0];
  1501. break;
  1502. //
  1503. // Allocate a journal volume monitor entry.
  1504. //
  1505. case VOLUME_MONITOR_ENTRY_TYPE:
  1506. NodeSize = sizeof(VOLUME_MONITOR_ENTRY);
  1507. Node = FrsAlloc(NodeSize);
  1508. pVme = (PVOLUME_MONITOR_ENTRY) Node;
  1509. FrsRtlInitializeList(&pVme->ReplicaListHead);
  1510. InitializeCriticalSection(&pVme->Lock);
  1511. InitializeCriticalSection(&pVme->QuadWriteLock);
  1512. pVme->Event = CreateEvent(NULL, TRUE, FALSE, NULL);
  1513. pVme->JournalState = JRNL_STATE_ALLOCATED;
  1514. break;
  1515. //
  1516. // Allocate a command packet.
  1517. //
  1518. case COMMAND_PACKET_TYPE:
  1519. NodeSize = sizeof(COMMAND_PACKET);
  1520. Node = FrsAlloc(NodeSize + SizeDelta);
  1521. break;
  1522. //
  1523. // Allocate a generic hash table struct.
  1524. //
  1525. case GENERIC_HASH_TABLE_TYPE:
  1526. NodeSize = sizeof(GENERIC_HASH_TABLE);
  1527. Node = FrsAlloc(NodeSize);
  1528. break;
  1529. //
  1530. // Allocate a Change Order Entry struct. Caller allocates Extension as necc.
  1531. //
  1532. case CHANGE_ORDER_ENTRY_TYPE:
  1533. NodeSize = sizeof(CHANGE_ORDER_ENTRY);
  1534. Node = FrsAlloc(NodeSize + SizeDelta);
  1535. ChangeOrder = (PCHANGE_ORDER_ENTRY)Node;
  1536. //
  1537. // Init the unicode filename string to point to internal alloc.
  1538. //
  1539. ChangeOrder->UFileName.Buffer = ChangeOrder->Cmd.FileName;
  1540. ChangeOrder->UFileName.MaximumLength = (USHORT)
  1541. (SIZEOF(CHANGE_ORDER_ENTRY, Cmd.FileName) + SizeDelta);
  1542. ChangeOrder->UFileName.Length = 0;
  1543. break;
  1544. //
  1545. // Allocate a Filter Table Entry struct.
  1546. //
  1547. case FILTER_TABLE_ENTRY_TYPE:
  1548. NodeSize = sizeof(FILTER_TABLE_ENTRY);
  1549. Node = FrsAlloc(NodeSize + SizeDelta);
  1550. FilterEntry = (PFILTER_TABLE_ENTRY)Node;
  1551. //
  1552. // Init the unicode filename string to point to internal alloc.
  1553. //
  1554. FilterEntry->UFileName.Buffer = FilterEntry->DFileName;
  1555. FilterEntry->UFileName.MaximumLength = (USHORT)SizeDelta + sizeof(WCHAR);
  1556. FilterEntry->UFileName.Length = 0;
  1557. InitializeListHead(&FilterEntry->ChildHead);
  1558. break;
  1559. //
  1560. // Allocate a QHASH table struct. Just alloc the
  1561. // base table. An extension is allocated on the first collision.
  1562. // *NOTE* caller specifies the size of the actual hash table and
  1563. // the extension. Caller also must store an address to a hash calc
  1564. // function.
  1565. //
  1566. case QHASH_TABLE_TYPE:
  1567. NodeSize = sizeof(QHASH_TABLE);
  1568. Node = FrsAlloc(NodeSize + SizeDelta);
  1569. QhashTable = (PQHASH_TABLE)Node;
  1570. InitializeCriticalSection(&QhashTable->Lock);
  1571. InitializeListHead(&QhashTable->ExtensionListHead);
  1572. QhashTable->BaseAllocSize = NodeSize + SizeDelta;
  1573. QhashTable->NumberEntries = SizeDelta / sizeof(QHASH_ENTRY);
  1574. if (SizeDelta <= QHASH_EXTENSION_MAX) {
  1575. QhashTable->ExtensionAllocSize = sizeof(LIST_ENTRY) + SizeDelta;
  1576. } else {
  1577. QhashTable->ExtensionAllocSize = sizeof(LIST_ENTRY) + QHASH_EXTENSION_MAX;
  1578. }
  1579. QhashTable->HashRowBase = (PQHASH_ENTRY) (QhashTable + 1);
  1580. SET_QHASH_TABLE_HASH_CALC(QhashTable, NULL);
  1581. QhashTable->FreeList.Next = NULL;
  1582. break;
  1583. //
  1584. // Allocate an Output Log Partner struct.
  1585. // This is ultimately hooked to a Connection struct which provides the
  1586. // Guid and version vector.
  1587. //
  1588. case OUT_LOG_PARTNER_TYPE:
  1589. NodeSize = sizeof(OUT_LOG_PARTNER);
  1590. Node = FrsAlloc(NodeSize);
  1591. break;
  1592. //
  1593. // Allocate a WildcardEntry filter Entry struct.
  1594. //
  1595. case WILDCARD_FILTER_ENTRY_TYPE:
  1596. NodeSize = sizeof(WILDCARD_FILTER_ENTRY);
  1597. Node = FrsAlloc(NodeSize + SizeDelta);
  1598. WildcardEntry = (PWILDCARD_FILTER_ENTRY)Node;
  1599. //
  1600. // Init the unicode filename string to point to internal alloc.
  1601. //
  1602. WildcardEntry->UFileName.Buffer = WildcardEntry->FileName;
  1603. WildcardEntry->UFileName.MaximumLength = (USHORT)SizeDelta;
  1604. WildcardEntry->UFileName.Length = 0;
  1605. break;
  1606. //
  1607. // Invalid Node Type
  1608. //
  1609. default:
  1610. Node = NULL;
  1611. DPRINT1(0, "Internal error - invalid node type - %d\n", NodeType);
  1612. XRAISEGENEXCEPTION(FrsErrorInternalError);
  1613. }
  1614. //
  1615. // Set up the header for later checking in FrsFreeType
  1616. //
  1617. ((PFRS_NODE_HEADER) Node)->Type = (USHORT) NodeType;
  1618. ((PFRS_NODE_HEADER) Node)->Size = (USHORT) NodeSize;
  1619. //
  1620. // Tracking memory expansion
  1621. //
  1622. EnterCriticalSection(&MemLock);
  1623. TypesAllocated[NodeType]++;
  1624. TypesAllocatedCount[NodeType]++;
  1625. if (TypesAllocated[NodeType] > TypesAllocatedMax[NodeType]) {
  1626. TypesAllocatedMax[NodeType] = TypesAllocated[NodeType];
  1627. }
  1628. LeaveCriticalSection(&MemLock);
  1629. //
  1630. // Return node address to caller.
  1631. //
  1632. return Node;
  1633. }
  1634. PVOID
  1635. FrsFreeType(
  1636. IN PVOID Node
  1637. )
  1638. /*++
  1639. Routine Description:
  1640. This routine frees memory for the given node, performing any node specific
  1641. cleanup. It marks the freed memory with the hex string 0xDEADBEnn where
  1642. the low byte (nn) is set to the node type being freed to catch users of
  1643. stale pointers.
  1644. Arguments:
  1645. Node - The address of the node to free.
  1646. Return Value:
  1647. NULL. Typical call is: ptr = FrsFreeType(ptr) to catch errors.
  1648. --*/
  1649. {
  1650. #undef DEBSUB
  1651. #define DEBSUB "FrsFreeType:"
  1652. ULONG NodeSize;
  1653. ULONG NodeType;
  1654. ULONG Marker;
  1655. PREPLICA Replica;
  1656. PREPLICA_THREAD_CTX RtCtx;
  1657. PTABLE_CTX TableCtx;
  1658. PTHREAD_CTX ThreadCtx;
  1659. ULONG i;
  1660. PVOLUME_MONITOR_ENTRY pVme;
  1661. PFILTER_TABLE_ENTRY FilterEntry;
  1662. PQHASH_TABLE QhashTable;
  1663. PLIST_ENTRY Entry;
  1664. PCXTION Cxtion;
  1665. PCONFIG_NODE ConfigNode;
  1666. PCHANGE_ORDER_ENTRY ChangeOrder;
  1667. PGHANDLE GHandle;
  1668. PHANDLE_LIST HandleList;
  1669. PWILDCARD_FILTER_ENTRY WildcardEntry;
  1670. POUT_LOG_PARTNER OutLogPartner;
  1671. if (Node == NULL) {
  1672. return NULL;
  1673. }
  1674. NodeType = (ULONG) (((PFRS_NODE_HEADER) Node)->Type);
  1675. NodeSize = (ULONG) (((PFRS_NODE_HEADER) Node)->Size);
  1676. switch (NodeType) {
  1677. //
  1678. // Free a Thread Context struct
  1679. //
  1680. case THREAD_CONTEXT_TYPE:
  1681. if (NodeSize != sizeof(THREAD_CTX)) {
  1682. DPRINT1(0, "FrsFree - Bad node size %d for THREAD_CONTEXT\n", NodeSize);
  1683. XRAISEGENEXCEPTION(FrsErrorInternalError);
  1684. }
  1685. ThreadCtx = (PTHREAD_CTX) Node;
  1686. FrsRtlDeleteList(&ThreadCtx->ThreadCtxListHead);
  1687. break;
  1688. //
  1689. // Free a Replica struct
  1690. //
  1691. case REPLICA_TYPE:
  1692. if (NodeSize != sizeof(REPLICA)) {
  1693. DPRINT1(0, "FrsFree - Bad node size %d for REPLICA\n", NodeSize);
  1694. XRAISEGENEXCEPTION(FrsErrorInternalError);
  1695. }
  1696. Replica = (PREPLICA) Node;
  1697. //
  1698. // Free the config table context.
  1699. //
  1700. DbsFreeTableCtx(&Replica->ConfigTable, NodeType);
  1701. FrsRtlDeleteList(&Replica->ReplicaCtxListHead);
  1702. //
  1703. // Empty the file and directory filter lists
  1704. //
  1705. FrsEmptyNameFilter(&Replica->FileNameFilterHead);
  1706. FrsEmptyNameFilter(&Replica->FileNameInclFilterHead);
  1707. FrsEmptyNameFilter(&Replica->DirNameFilterHead);
  1708. FrsEmptyNameFilter(&Replica->DirNameInclFilterHead);
  1709. FrsFree(Replica->FileFilterList);
  1710. FrsFree(Replica->FileInclFilterList);
  1711. FrsFree(Replica->DirFilterList);
  1712. FrsFree(Replica->DirInclFilterList);
  1713. DeleteCriticalSection(&Replica->ReplicaLock);
  1714. DeleteCriticalSection(&Replica->OutLogLock);
  1715. if (Replica->OutLogRecordLock != NULL) {
  1716. //
  1717. // Free the record lock table.
  1718. //
  1719. Replica->OutLogRecordLock = FrsFreeType(Replica->OutLogRecordLock);
  1720. }
  1721. //
  1722. // queue
  1723. //
  1724. if (Replica->Queue) {
  1725. FrsRtlDeleteQueue(Replica->Queue);
  1726. FrsFree(Replica->Queue);
  1727. }
  1728. //
  1729. // free the initsync queue.
  1730. //
  1731. if (Replica->InitSyncQueue) {
  1732. FrsRtlDeleteQueue(Replica->InitSyncQueue);
  1733. Replica->InitSyncQueue = FrsFree(Replica->InitSyncQueue);
  1734. }
  1735. //
  1736. // Names
  1737. //
  1738. FrsFree(Replica->Root);
  1739. FrsFree(Replica->Stage);
  1740. FrsFree(Replica->NewStage);
  1741. FrsFree(Replica->Volume);
  1742. FrsFreeGName(Replica->ReplicaName);
  1743. FrsFreeGName(Replica->SetName);
  1744. FrsFreeGName(Replica->MemberName);
  1745. //
  1746. // Root Guid
  1747. //
  1748. FrsFree(Replica->ReplicaRootGuid);
  1749. //
  1750. // Status of sysvol seeding
  1751. //
  1752. FrsFree(Replica->NtFrsApi_ServiceDisplay);
  1753. //
  1754. // Schedule
  1755. //
  1756. FrsFree(Replica->Schedule);
  1757. //
  1758. // VVector
  1759. //
  1760. VVFree(Replica->VVector);
  1761. //
  1762. // Cxtions
  1763. //
  1764. GTabFreeTable(Replica->Cxtions, FrsFreeType);
  1765. //
  1766. // Preinstall directory
  1767. //
  1768. FRS_CLOSE(Replica->PreInstallHandle);
  1769. //
  1770. // Free the counter data structure memory
  1771. //
  1772. if (Replica->PerfRepSetData != NULL) {
  1773. if (Replica->PerfRepSetData->oid != NULL) {
  1774. if (Replica->PerfRepSetData->oid->name != NULL) {
  1775. Replica->PerfRepSetData->oid->name =
  1776. FrsFree(Replica->PerfRepSetData->oid->name);
  1777. }
  1778. Replica->PerfRepSetData->oid =
  1779. FrsFree(Replica->PerfRepSetData->oid);
  1780. }
  1781. Replica->PerfRepSetData = FrsFree(Replica->PerfRepSetData);
  1782. }
  1783. break;
  1784. //
  1785. // Free a Replica Thread Context struct
  1786. //
  1787. case REPLICA_THREAD_TYPE:
  1788. if (NodeSize != sizeof(REPLICA_THREAD_CTX)) {
  1789. DPRINT1(0, "FrsFree - Bad node size %d for REPLICA_THREAD_CTX\n", NodeSize);
  1790. XRAISEGENEXCEPTION(FrsErrorInternalError);
  1791. }
  1792. RtCtx = (PREPLICA_THREAD_CTX) Node;
  1793. //
  1794. // Get the base of the array of TableCtx structs from the replica thread
  1795. // context struct.
  1796. //
  1797. TableCtx = RtCtx->RtCtxTables;
  1798. //
  1799. // Release the memory for each table context struct.
  1800. //
  1801. for (i=0; i<TABLE_TYPE_MAX; ++i, ++TableCtx)
  1802. DbsFreeTableCtx(TableCtx, NodeType);
  1803. break;
  1804. //
  1805. // Free a topology node
  1806. //
  1807. case CONFIG_NODE_TYPE:
  1808. if (NodeSize != sizeof(CONFIG_NODE)) {
  1809. DPRINT1(0, "FrsFree - Bad node size %d for CONFIG_NODE\n", NodeSize);
  1810. XRAISEGENEXCEPTION(FrsErrorInternalError);
  1811. }
  1812. ConfigNode = (PCONFIG_NODE) Node;
  1813. FrsFreeGName(ConfigNode->Name);
  1814. FrsFreeGName(ConfigNode->PartnerName);
  1815. FrsFree(ConfigNode->Root);
  1816. FrsFree(ConfigNode->Stage);
  1817. FrsFree(ConfigNode->Schedule);
  1818. FrsFree(ConfigNode->Dn);
  1819. FrsFree(ConfigNode->PrincName);
  1820. FrsFree(ConfigNode->PartnerDn);
  1821. FrsFree(ConfigNode->PartnerCoDn);
  1822. FrsFree(ConfigNode->SettingsDn);
  1823. FrsFree(ConfigNode->ComputerDn);
  1824. FrsFree(ConfigNode->MemberDn);
  1825. FrsFree(ConfigNode->Working);
  1826. FrsFree(ConfigNode->SetType);
  1827. FrsFree(ConfigNode->FileFilterList);
  1828. FrsFree(ConfigNode->DirFilterList);
  1829. FrsFree(ConfigNode->UsnChanged);
  1830. FrsFree(ConfigNode->DnsName);
  1831. FrsFree(ConfigNode->PartnerDnsName);
  1832. FrsFree(ConfigNode->Sid);
  1833. FrsFree(ConfigNode->PartnerSid);
  1834. FrsFree(ConfigNode->EnabledCxtion);
  1835. break;
  1836. //
  1837. // Free a connection
  1838. //
  1839. case CXTION_TYPE:
  1840. if (NodeSize != sizeof(CXTION)) {
  1841. DPRINT1(0, "FrsFree - Bad node size %d for CXTION\n", NodeSize);
  1842. XRAISEGENEXCEPTION(FrsErrorInternalError);
  1843. }
  1844. Cxtion = (PCXTION) Node;
  1845. VVFreeOutbound(Cxtion->VVector);
  1846. //
  1847. // Free the CompressionTable that was build for the outbound partner.
  1848. //
  1849. GTabFreeTable(Cxtion->CompressionTable, FrsFree);
  1850. //
  1851. // Free the OutLogPartner context.
  1852. //
  1853. FrsFreeType(Cxtion->OLCtx);
  1854. SndCsDestroyCxtion(Cxtion, CXTION_FLAGS_UNJOIN_GUID_VALID);
  1855. if (Cxtion->CommTimeoutCmd) {
  1856. //
  1857. // Try to catch the case where a Comm Time Out wait command is
  1858. // getting freed while it is still on the timeout queue. This is
  1859. // related to a bug where we get into a comm timeout loop with an
  1860. // invalid command code.
  1861. //
  1862. FRS_ASSERT(!CxtionFlagIs(Cxtion, CXTION_FLAGS_TIMEOUT_SET));
  1863. FRS_ASSERT(!CmdWaitFlagIs(Cxtion->CommTimeoutCmd, CMD_PKT_WAIT_FLAGS_ONLIST));
  1864. FrsFreeType(Cxtion->CommTimeoutCmd);
  1865. }
  1866. //
  1867. // A cxtion doesn't actually "own" the join command packet; it
  1868. // only maintains a reference to prevent extraneous join commands
  1869. // from flooding the replica's queue.
  1870. //
  1871. Cxtion->JoinCmd = NULL;
  1872. //
  1873. // VvJoin Command Server (1 per cxtion)
  1874. //
  1875. if (Cxtion->VvJoinCs) {
  1876. FrsRunDownCommandServer(Cxtion->VvJoinCs,
  1877. &Cxtion->VvJoinCs->Queue);
  1878. FrsDeleteCommandServer(Cxtion->VvJoinCs);
  1879. FrsFree(Cxtion->VvJoinCs);
  1880. }
  1881. if (!Cxtion->ChangeOrderCount) {
  1882. GTabFreeTable(Cxtion->CoeTable, NULL);
  1883. }
  1884. FrsFreeGName(Cxtion->Name);
  1885. FrsFreeGName(Cxtion->Partner);
  1886. FrsFree(Cxtion->PartnerPrincName);
  1887. FrsFree(Cxtion->Schedule);
  1888. FrsFree(Cxtion->PartSrvName);
  1889. FrsFree(Cxtion->PartnerDnsName);
  1890. FrsFree(Cxtion->PartnerSid);
  1891. //
  1892. // Delete the connection from the perfmon tables.
  1893. // Free the counter data structure memory
  1894. //
  1895. if (Cxtion->PerfRepConnData != NULL) {
  1896. if (Cxtion->PerfRepConnData->oid != NULL) {
  1897. DeletePerfmonInstance(REPLICACONN, Cxtion->PerfRepConnData);
  1898. }
  1899. Cxtion->PerfRepConnData = FrsFree(Cxtion->PerfRepConnData);
  1900. }
  1901. break;
  1902. //
  1903. // Free a guid/rpc handle
  1904. //
  1905. case GHANDLE_TYPE:
  1906. if (NodeSize != sizeof(GHANDLE)) {
  1907. DPRINT2(0, "FrsFree - Bad node size %d (%d) for GHANDLE\n",
  1908. NodeSize, sizeof(GHANDLE));
  1909. XRAISEGENEXCEPTION(FrsErrorInternalError);
  1910. }
  1911. GHandle = (PGHANDLE)Node;
  1912. while (HandleList = GHandle->HandleList) {
  1913. GHandle->HandleList = HandleList->Next;
  1914. FrsRpcUnBindFromServer(&HandleList->RpcHandle);
  1915. FrsFree(HandleList);
  1916. }
  1917. DeleteCriticalSection(&GHandle->Lock);
  1918. break;
  1919. //
  1920. // Free a generic table
  1921. //
  1922. case GEN_TABLE_TYPE:
  1923. if (NodeSize != sizeof(GEN_TABLE)) {
  1924. DPRINT1(0, "FrsFree - Bad node size %d for GEN_TABLE\n", NodeSize);
  1925. XRAISEGENEXCEPTION(FrsErrorInternalError);
  1926. }
  1927. break;
  1928. //
  1929. // Free a generic thread context
  1930. //
  1931. case THREAD_TYPE:
  1932. if (NodeSize != sizeof(FRS_THREAD)) {
  1933. DPRINT1(0, "FrsFree - Bad node size %d for FRS_THREAD\n", NodeSize);
  1934. XRAISEGENEXCEPTION(FrsErrorInternalError);
  1935. }
  1936. break;
  1937. //
  1938. // Free a journal read buffer.
  1939. //
  1940. case JBUFFER_TYPE:
  1941. if (NodeSize != SizeOfJournalBuffer) {
  1942. DPRINT1(0, "FrsFree - Bad node size %d for JBUFFER\n", NodeSize);
  1943. XRAISEGENEXCEPTION(FrsErrorInternalError);
  1944. }
  1945. break;
  1946. //
  1947. // Free a journal volume monitor entry.
  1948. //
  1949. case VOLUME_MONITOR_ENTRY_TYPE:
  1950. if (NodeSize != sizeof(VOLUME_MONITOR_ENTRY)) {
  1951. DPRINT1(0, "FrsFree - Bad node size %d for VOLUME_MONITOR_ENTRY\n", NodeSize);
  1952. XRAISEGENEXCEPTION(FrsErrorInternalError);
  1953. }
  1954. pVme = (PVOLUME_MONITOR_ENTRY) Node;
  1955. FrsRtlDeleteList(&pVme->ReplicaListHead);
  1956. DeleteCriticalSection(&pVme->Lock);
  1957. DeleteCriticalSection(&pVme->QuadWriteLock);
  1958. FRS_CLOSE(pVme->Event);
  1959. //
  1960. // Release the change order hash table.
  1961. //
  1962. GhtDestroyTable(pVme->ChangeOrderTable);
  1963. //
  1964. // Release the Filter Hash Table.
  1965. //
  1966. GhtDestroyTable(pVme->FilterTable);
  1967. break;
  1968. //
  1969. // Free a command packet.
  1970. //
  1971. case COMMAND_PACKET_TYPE:
  1972. if (NodeSize != sizeof(COMMAND_PACKET)) {
  1973. DPRINT1(0, "FrsFree - Bad node size %d for COMMAND_PACKET\n", NodeSize);
  1974. XRAISEGENEXCEPTION(FrsErrorInternalError);
  1975. }
  1976. break;
  1977. //
  1978. // Free a generic hash table struct.
  1979. //
  1980. case GENERIC_HASH_TABLE_TYPE:
  1981. if (NodeSize != sizeof(GENERIC_HASH_TABLE)) {
  1982. DPRINT1(0, "FrsFree - Bad node size %d for GENERIC_HASH_TABLE\n", NodeSize);
  1983. XRAISEGENEXCEPTION(FrsErrorInternalError);
  1984. }
  1985. break;
  1986. //
  1987. // Free a Change Order Entry struct.
  1988. //
  1989. case CHANGE_ORDER_ENTRY_TYPE:
  1990. if (NodeSize != sizeof(CHANGE_ORDER_ENTRY)) {
  1991. DPRINT1(0, "FrsFree - Bad node size %d for CHANGE_ORDER_ENTRY\n", NodeSize);
  1992. XRAISEGENEXCEPTION(FrsErrorInternalError);
  1993. }
  1994. ChangeOrder = (PCHANGE_ORDER_ENTRY)Node;
  1995. //
  1996. // If we allocated a new name string then free it.
  1997. //
  1998. if (ChangeOrder->UFileName.Buffer != ChangeOrder->Cmd.FileName) {
  1999. FrsFree(ChangeOrder->UFileName.Buffer);
  2000. }
  2001. //
  2002. // Free the change order extenstion.
  2003. //
  2004. if (ChangeOrder->Cmd.Extension != NULL) {
  2005. FrsFree(ChangeOrder->Cmd.Extension);
  2006. }
  2007. break;
  2008. //
  2009. // Free a Filter Table Entry struct.
  2010. //
  2011. case FILTER_TABLE_ENTRY_TYPE:
  2012. if (NodeSize != sizeof(FILTER_TABLE_ENTRY)) {
  2013. DPRINT1(0, "FrsFree - Bad node size %d for FILTER_TABLE_ENTRY\n", NodeSize);
  2014. XRAISEGENEXCEPTION(FrsErrorInternalError);
  2015. }
  2016. FilterEntry = (PFILTER_TABLE_ENTRY)Node;
  2017. //
  2018. // If we allocated a new name string then free it.
  2019. //
  2020. if (FilterEntry->UFileName.Buffer != FilterEntry->DFileName) {
  2021. FrsFree(FilterEntry->UFileName.Buffer);
  2022. }
  2023. break;
  2024. //
  2025. // Free a QHASH table struct.
  2026. //
  2027. case QHASH_TABLE_TYPE:
  2028. if (NodeSize != sizeof(QHASH_TABLE)) {
  2029. DPRINT1(0, "FrsFree - Bad node size %d for QHASH_TABLE\n", NodeSize);
  2030. XRAISEGENEXCEPTION(FrsErrorInternalError);
  2031. }
  2032. QhashTable = (PQHASH_TABLE)Node;
  2033. QHashEmptyLargeKeyTable(QhashTable);
  2034. //
  2035. // Free up all the extensions we allocated.
  2036. //
  2037. while (!IsListEmpty(&QhashTable->ExtensionListHead)) {
  2038. Entry = GetListHead(&QhashTable->ExtensionListHead);
  2039. FrsRemoveEntryList(Entry);
  2040. FrsFree(Entry);
  2041. }
  2042. DeleteCriticalSection(&QhashTable->Lock);
  2043. break;
  2044. //
  2045. // Free an Output Log Partner struct.
  2046. //
  2047. case OUT_LOG_PARTNER_TYPE:
  2048. if (NodeSize != sizeof(OUT_LOG_PARTNER)) {
  2049. DPRINT1(0, "FrsFree - Bad node size %d for OUT_LOG_PARTNER\n", NodeSize);
  2050. XRAISEGENEXCEPTION(FrsErrorInternalError);
  2051. }
  2052. OutLogPartner = (POUT_LOG_PARTNER)Node;
  2053. //
  2054. // Free the Must send QHash Table.
  2055. //
  2056. OutLogPartner->MustSendTable = FrsFreeType(OutLogPartner->MustSendTable);
  2057. break;
  2058. //
  2059. // Free a Wildcard file filter Entry struct.
  2060. //
  2061. case WILDCARD_FILTER_ENTRY_TYPE:
  2062. if (NodeSize != sizeof(WILDCARD_FILTER_ENTRY)) {
  2063. DPRINT1(0, "FrsFree - Bad node size %d for WILDCARD_FILTER_ENTRY\n", NodeSize);
  2064. XRAISEGENEXCEPTION(FrsErrorInternalError);
  2065. }
  2066. WildcardEntry = (PWILDCARD_FILTER_ENTRY)Node;
  2067. //
  2068. // Free the name buffer if it no longer points at the initial alloc.
  2069. //
  2070. if (WildcardEntry->UFileName.Buffer != WildcardEntry->FileName) {
  2071. FrsFree(WildcardEntry->UFileName.Buffer);
  2072. }
  2073. break;
  2074. //
  2075. // Invalid Node Type
  2076. //
  2077. default:
  2078. Node = NULL;
  2079. DPRINT1(0, "Internal error - invalid node type - %d\n", NodeType);
  2080. XRAISEGENEXCEPTION(FrsErrorInternalError);
  2081. }
  2082. EnterCriticalSection(&MemLock);
  2083. TypesAllocated[NodeType]--;
  2084. LeaveCriticalSection(&MemLock);
  2085. //
  2086. // Fill the node with a marker then free it.
  2087. //
  2088. Marker = (ULONG) 0xDEADBE00 + NodeType;
  2089. FillMemory(Node, NodeSize, (BYTE)Marker);
  2090. return FrsFree(Node);
  2091. }
  2092. VOID
  2093. FrsFreeTypeList(
  2094. PLIST_ENTRY Head
  2095. )
  2096. /*++
  2097. Routine Description:
  2098. Free all the "typed" entries on the specified list.
  2099. Note: This routine requires that the LIST_ENTRY struct in each
  2100. list entry immediately follow the FRS_NODE_HEADER and of course that
  2101. the list entry is actually linked through that LIST_ENTRY struct.
  2102. Arguments:
  2103. Head -- ptr to the list head.
  2104. Thread Return Value:
  2105. None.
  2106. --*/
  2107. {
  2108. #undef DEBSUB
  2109. #define DEBSUB "FrsFreeTypeList:"
  2110. PLIST_ENTRY Entry;
  2111. PFRS_NODE_HEADER Header;
  2112. Entry = RemoveHeadList(Head);
  2113. while (Entry != Head) {
  2114. Header = (PFRS_NODE_HEADER) CONTAINING_RECORD(Entry, COMMAND_PACKET, ListEntry);
  2115. if ((Header->Type >= NODE_TYPE_MIN) &&
  2116. (Header->Type < NODE_TYPE_MAX)) {
  2117. FrsFreeType(Header);
  2118. } else {
  2119. DPRINT(0, "Node type out of range. Not freed.\n");
  2120. }
  2121. Entry = RemoveHeadList(Head);
  2122. }
  2123. }
  2124. VOID
  2125. FrsPrintGNameForNode(
  2126. IN ULONG Severity,
  2127. IN PGNAME GName,
  2128. IN PWCHAR Indent,
  2129. IN PWCHAR Id,
  2130. IN PCHAR Debsub,
  2131. IN ULONG uLineNo
  2132. )
  2133. /*++
  2134. Routine Description:
  2135. Pretty print a gname for FrsPrintNode()
  2136. Arguments:
  2137. Severity -- Severity level for print. (See debug.c, debug.h)
  2138. GName - The address of the GName to print.
  2139. Indent - line indentation
  2140. Id - identifies the gname
  2141. Debsub -- Name of calling subroutine.
  2142. uLineno -- Line number of caller
  2143. Return Value:
  2144. none.
  2145. --*/
  2146. {
  2147. CHAR GuidStr[GUID_CHAR_LEN];
  2148. if (GName) {
  2149. if (GName->Name) {
  2150. FRS_DEB_PRINT3("%ws%ws: %ws\n", Indent, Id, GName->Name);
  2151. } else {
  2152. FRS_DEB_PRINT3("%wsNO %ws->NAME for %08x\n", Indent, Id, GName);
  2153. }
  2154. if (GName->Guid) {
  2155. GuidToStr(GName->Guid, GuidStr);
  2156. FRS_DEB_PRINT3("%ws%wsGuid: %s\n", Indent, Id, GuidStr);
  2157. } else {
  2158. FRS_DEB_PRINT3("%wsNO %ws->GUID for %08x\n", Indent, Id, GName);
  2159. }
  2160. } else {
  2161. FRS_DEB_PRINT3("%wsNO %ws for %08x\n", Indent, Id, GName);
  2162. }
  2163. }
  2164. VOID
  2165. FrsPrintTypeSchedule(
  2166. IN ULONG Severity, OPTIONAL
  2167. IN PNTFRSAPI_INFO Info, OPTIONAL
  2168. IN DWORD Tabs, OPTIONAL
  2169. IN PSCHEDULE Schedule,
  2170. IN PCHAR Debsub, OPTIONAL
  2171. IN ULONG uLineNo OPTIONAL
  2172. )
  2173. /*++
  2174. Routine Description:
  2175. Print a schedule.
  2176. Arguments:
  2177. Severity - for DPRINTs
  2178. Info - RPC output buffer
  2179. Tabs - prettyprint
  2180. Schedule - schedule blob
  2181. Debsub - for DPRINTs
  2182. uLineNo - for DPRINTs
  2183. Return Value:
  2184. None.
  2185. --*/
  2186. {
  2187. ULONG i;
  2188. ULONG Day;
  2189. ULONG Hour;
  2190. ULONG LineLen;
  2191. PUCHAR ScheduleData;
  2192. CHAR Line[256];
  2193. WCHAR TabW[MAX_TAB_WCHARS + 1];
  2194. if (!Schedule) {
  2195. return;
  2196. }
  2197. InfoTabs(Tabs, TabW);
  2198. for (i = 0; i < Schedule->NumberOfSchedules; ++i) {
  2199. ScheduleData = ((PUCHAR)Schedule) + Schedule->Schedules[i].Offset;
  2200. if (Schedule->Schedules[i].Type != SCHEDULE_INTERVAL) {
  2201. continue;
  2202. }
  2203. for (Day = 0; Day < 7; ++Day) {
  2204. _snprintf(Line, sizeof(Line), "%wsDay %1d: ", TabW, Day + 1);
  2205. for (Hour = 0; Hour < 24; ++Hour) {
  2206. LineLen = strlen(Line);
  2207. _snprintf(&Line[LineLen],
  2208. sizeof(Line) - LineLen,
  2209. "%1x",
  2210. *(ScheduleData + (Day * 24) + Hour) & 0x0F);
  2211. }
  2212. ITPRINT1("%s\n", Line);
  2213. }
  2214. }
  2215. }
  2216. VOID
  2217. FrsPrintTypeVv(
  2218. IN ULONG Severity, OPTIONAL
  2219. IN PNTFRSAPI_INFO Info, OPTIONAL
  2220. IN DWORD Tabs, OPTIONAL
  2221. IN PGEN_TABLE Vv,
  2222. IN PCHAR Debsub, OPTIONAL
  2223. IN ULONG uLineNo OPTIONAL
  2224. )
  2225. /*++
  2226. Routine Description:
  2227. Print a version vector
  2228. Arguments:
  2229. Severity - for DPRINTs
  2230. Info - RPC output buffer
  2231. Tabs - prettyprint
  2232. Vv - Version vector table
  2233. Debsub - for DPRINTs
  2234. uLineNo - for DPRINTs
  2235. Return Value:
  2236. None.
  2237. --*/
  2238. {
  2239. #undef DEBSUB
  2240. #define DEBSUB "FrsPrintTypeVv:"
  2241. PVOID Key;
  2242. PVV_ENTRY MasterVVEntry;
  2243. WCHAR TabW[MAX_TAB_WCHARS + 1];
  2244. CHAR Guid[GUID_CHAR_LEN + 1];
  2245. if (!Vv) {
  2246. return;
  2247. }
  2248. InfoTabs(Tabs, TabW);
  2249. Key = NULL;
  2250. while (MasterVVEntry = GTabNextDatum(Vv, &Key)) {
  2251. if (!Info) {
  2252. DebLock();
  2253. }
  2254. GuidToStr(&MasterVVEntry->GVsn.Guid, Guid);
  2255. ITPRINT3("%wsVvEntry: %s = %08x %08x\n",
  2256. TabW, Guid, PRINTQUAD(MasterVVEntry->GVsn.Vsn));
  2257. if (!Info) {
  2258. DebUnLock();
  2259. }
  2260. }
  2261. }
  2262. VOID
  2263. FrsPrintTypeOutLogAVToStr(
  2264. POUT_LOG_PARTNER OutLogPartner,
  2265. ULONG RetireCOx,
  2266. PCHAR *OutStr1,
  2267. PCHAR *OutStr2,
  2268. PCHAR *OutStr3
  2269. )
  2270. {
  2271. #undef DEBSUB
  2272. #define DEBSUB "FrsPrintTypeOutLogAVToStr:"
  2273. PCHAR Str, Str2, Str3;
  2274. ULONG j, Slotx, MaxSlotx, COx, Fill, Scan;
  2275. //
  2276. // Caller frees strings with FrsFree(Str).
  2277. //
  2278. Str = FrsAlloc(3*(ACK_VECTOR_SIZE+4));
  2279. Str2 = Str + (ACK_VECTOR_SIZE+4);
  2280. Str3 = Str2 + (ACK_VECTOR_SIZE+4);
  2281. COx = OutLogPartner->COTx;
  2282. Slotx = AVSlot(OutLogPartner->COTx, OutLogPartner);
  2283. MaxSlotx = Slotx + ACK_VECTOR_SIZE;
  2284. while (Slotx < MaxSlotx) {
  2285. j = Slotx & (ACK_VECTOR_SIZE-1);
  2286. if (ReadAVBitBySlot(Slotx, OutLogPartner) == 0) {
  2287. Str[j] = '.';
  2288. } else {
  2289. Str[j] = '1';
  2290. }
  2291. if (COx == OutLogPartner->COTx) {
  2292. Str2[j] = 'T';
  2293. } else
  2294. if (COx == OutLogPartner->COLx) {
  2295. Str2[j] = 'L';
  2296. } else {
  2297. Str2[j] = '_';
  2298. }
  2299. if (COx == RetireCOx) {
  2300. Str3[j] = '^';
  2301. } else {
  2302. Str3[j] = ' ';
  2303. }
  2304. COx += 1;
  2305. Slotx += 1;
  2306. }
  2307. Str[ACK_VECTOR_SIZE] = '\0';
  2308. Str2[ACK_VECTOR_SIZE] = '\0';
  2309. Str3[ACK_VECTOR_SIZE] = '\0';
  2310. //
  2311. // Compress out blocks of 8
  2312. //
  2313. Fill = 0;
  2314. Scan = 0;
  2315. while (Scan < ACK_VECTOR_SIZE) {
  2316. for (j=Scan; j < Scan+8; j++) {
  2317. if ((Str[j] != '.') || (Str2[j] != '_') || (Str3[j] != ' ')) {
  2318. break;
  2319. }
  2320. }
  2321. if (j == Scan+8) {
  2322. // Compress out this block
  2323. Str[Fill] = Str2[Fill] = Str3[Fill] = '-';
  2324. Fill += 1;
  2325. } else {
  2326. // Copy this block to fill point of strings.
  2327. for (j=Scan; j < Scan+8; j++) {
  2328. Str[Fill] = Str[j];
  2329. Str2[Fill] = Str2[j];
  2330. Str3[Fill] = Str3[j];
  2331. Fill += 1;
  2332. }
  2333. }
  2334. Scan += 8;
  2335. }
  2336. Str[Fill] = Str2[Fill] = Str3[Fill] = '\0';
  2337. *OutStr1 = Str;
  2338. *OutStr2 = Str2;
  2339. *OutStr3 = Str3;
  2340. return;
  2341. }
  2342. VOID
  2343. FrsPrintTypeOutLogPartner(
  2344. IN ULONG Severity, OPTIONAL
  2345. IN PNTFRSAPI_INFO Info, OPTIONAL
  2346. IN DWORD Tabs, OPTIONAL
  2347. IN POUT_LOG_PARTNER Olp,
  2348. IN ULONG RetireCox,
  2349. IN PCHAR Description,
  2350. IN PCHAR Debsub, OPTIONAL
  2351. IN ULONG uLineNo OPTIONAL
  2352. )
  2353. /*++
  2354. Routine Description:
  2355. Print an outlog partner
  2356. Arguments:
  2357. Severity - for DPRINTs
  2358. Info - RPC output buffer
  2359. Tabs - prettyprint
  2360. Olp - Out log partner struct
  2361. RetireCox - change order index for ack vector
  2362. Description - description of caller
  2363. Debsub - for DPRINTs
  2364. uLineNo - for DPRINTs
  2365. Return Value:
  2366. None.
  2367. --*/
  2368. {
  2369. #undef DEBSUB
  2370. #define DEBSUB "FrsPrintTypeOutLogPartner:"
  2371. PCHAR OutStr1, OutStr2, OutStr3;
  2372. CHAR FBuf[120];
  2373. CHAR TimeStr[TIME_STRING_LENGTH];
  2374. WCHAR TabW[MAX_TAB_WCHARS + 1];
  2375. InfoTabs(Tabs, TabW);
  2376. if (!Info) {
  2377. DebLock();
  2378. }
  2379. ITPRINT2("%wsOutLogPartner : %s\n", TabW, Description);
  2380. if (Olp->Cxtion && Olp->Cxtion->Name) {
  2381. ITPRINT2( "%wsCxtion : %ws\n",
  2382. TabW,
  2383. Olp->Cxtion->Name->Name);
  2384. if (Olp->Cxtion->Partner && Olp->Cxtion->Partner->Name) {
  2385. ITPRINT2( "%wsPartner : %ws\n",
  2386. TabW,
  2387. Olp->Cxtion->Partner->Name);
  2388. }
  2389. }
  2390. FrsFlagsToStr(Olp->Flags, OlpFlagNameTable, sizeof(FBuf), FBuf);
  2391. ITPRINT3("%wsFlags : %08x Flags [%s]\n", TabW, Olp->Flags, FBuf);
  2392. ITPRINT2("%wsState : %s\n", TabW, OLPartnerStateNames[Olp->State]);
  2393. ITPRINT2("%wsCoTx : %8d\n", TabW, Olp->COTx);
  2394. ITPRINT2("%wsCoLx : %8d\n", TabW, Olp->COLx);
  2395. ITPRINT2("%wsCOLxRestart : %8d\n", TabW, Olp->COLxRestart);
  2396. ITPRINT2("%wsCOLxVVJoinDone : %8d\n", TabW, Olp->COLxVVJoinDone);
  2397. ITPRINT2("%wsCoTxSave : %8d\n", TabW, Olp->COTxNormalModeSave);
  2398. ITPRINT2("%wsCoTslot : %8d\n", TabW, Olp->COTslot);
  2399. ITPRINT2("%wsOutstandingCos : %8d\n", TabW, Olp->OutstandingCos);
  2400. ITPRINT2("%wsOutstandingQuota: %8d\n", TabW, Olp->OutstandingQuota);
  2401. FileTimeToString((PFILETIME) &Olp->AckVersion, TimeStr);
  2402. ITPRINT2("%wsAckVersion : %s\n" , TabW, TimeStr);
  2403. if (RetireCox != -1) {
  2404. ITPRINT2("%wsRetireCox : %8d\n", TabW, RetireCox);
  2405. }
  2406. FrsPrintTypeOutLogAVToStr(Olp, RetireCox, &OutStr1, &OutStr2, &OutStr3);
  2407. //
  2408. // keep output together.
  2409. //
  2410. ITPRINT2("%wsAck: |%s|\n", TabW, OutStr1);
  2411. ITPRINT2("%wsAck: |%s|\n", TabW, OutStr2);
  2412. ITPRINT2("%wsAck: |%s|\n", TabW, OutStr3);
  2413. FrsFree(OutStr1);
  2414. if (!Info) {
  2415. DebUnLock();
  2416. }
  2417. }
  2418. VOID
  2419. FrsPrintTypeCxtion(
  2420. IN ULONG Severity, OPTIONAL
  2421. IN PNTFRSAPI_INFO Info, OPTIONAL
  2422. IN DWORD Tabs, OPTIONAL
  2423. IN PCXTION Cxtion,
  2424. IN PCHAR Debsub, OPTIONAL
  2425. IN ULONG uLineNo OPTIONAL
  2426. )
  2427. /*++
  2428. Routine Description:
  2429. Print a cxtion
  2430. Arguments:
  2431. Severity - for DPRINTs
  2432. Info - RPC output buffer
  2433. Tabs - prettyprint
  2434. Cxtion
  2435. Debsub - for DPRINTs
  2436. uLineNo - for DPRINTs
  2437. Return Value:
  2438. None.
  2439. --*/
  2440. {
  2441. #undef DEBSUB
  2442. #define DEBSUB "FrsPrintTypeCxtion:"
  2443. WCHAR TabW[MAX_TAB_WCHARS + 1];
  2444. CHAR Guid[GUID_CHAR_LEN + 1];
  2445. CHAR TimeStr[TIME_STRING_LENGTH];
  2446. CHAR FlagBuffer[120];
  2447. if (!Cxtion) {
  2448. return;
  2449. }
  2450. //
  2451. // Prettyprint indentation
  2452. //
  2453. InfoTabs(Tabs, TabW);
  2454. if (!Info) {
  2455. DebLock();
  2456. }
  2457. ITPRINT0("\n");
  2458. ITPRINTGNAME(Cxtion->Name,
  2459. "%ws Cxtion: %ws (%s)\n");
  2460. ITPRINTGNAME(Cxtion->Partner,
  2461. "%ws Partner : %ws (%s)\n");
  2462. ITPRINT2("%ws PartDnsName : %ws\n", TabW, Cxtion->PartnerDnsName);
  2463. ITPRINT2("%ws PartSrvName : %ws\n", TabW, Cxtion->PartSrvName);
  2464. ITPRINT2("%ws PartPrincName: %ws\n", TabW, Cxtion->PartnerPrincName);
  2465. ITPRINT2("%ws PartSid : %ws\n", TabW, Cxtion->PartnerSid);
  2466. ITPRINTGUID(&Cxtion->ReplicaVersionGuid, "%ws OrigGuid : %s\n");
  2467. ITPRINT2("%ws State : %d\n", TabW, Cxtion->State);
  2468. FrsFlagsToStr(Cxtion->Flags, CxtionFlagNameTable, sizeof(FlagBuffer), FlagBuffer);
  2469. ITPRINT3("%ws Flags : %08x Flags [%s]\n", TabW, Cxtion->Flags, FlagBuffer);
  2470. ITPRINT2("%ws Inbound : %s\n", TabW, (Cxtion->Inbound) ? "TRUE" : "FALSE");
  2471. ITPRINT2("%ws JrnlCxtion : %s\n", TabW, (Cxtion->JrnlCxtion) ? "TRUE" : "FALSE");
  2472. ITPRINT2("%ws Options : 0x%08x\n", TabW, Cxtion->Options);
  2473. ITPRINT2("%ws PartnerAuth : %d\n", TabW, Cxtion->PartnerAuthLevel);
  2474. ITPRINT2("%ws TermCoSn : %d\n", TabW, Cxtion->TerminationCoSeqNum);
  2475. ITPRINT2("%ws JoinCmd : 0x%08x\n", TabW, Cxtion->JoinCmd);
  2476. ITPRINT2("%ws CoCount : %d\n", TabW, Cxtion->ChangeOrderCount);
  2477. ITPRINT2("%ws CommQueue : %d\n", TabW, Cxtion->CommQueueIndex);
  2478. ITPRINT2("%ws CoPQ : %08x\n", TabW, Cxtion->CoProcessQueue);
  2479. ITPRINT2("%ws UnjoinTrigger: %d\n", TabW, Cxtion->UnjoinTrigger);
  2480. ITPRINT2("%ws UnjoinReset : %d\n", TabW, Cxtion->UnjoinReset);
  2481. ITPRINT2("%ws Comm Packets : %d\n", TabW, Cxtion->CommPkts);
  2482. ITPRINT2("%ws PartnerMajor : %d\n", TabW, Cxtion->PartnerMajor);
  2483. ITPRINT2("%ws PartnerMinor : %d\n", TabW, Cxtion->PartnerMinor);
  2484. //
  2485. // Don't print the join guid in the logs; they may be readable
  2486. // by anyone. An Info-RPC is secure so return the join guid in
  2487. // case it is needed for debugging.
  2488. //
  2489. if (Info) {
  2490. ITPRINTGUID(&Cxtion->JoinGuid, "%ws JoinGuid : %s\n");
  2491. FileTimeToString((PFILETIME) &Cxtion->LastJoinTime, TimeStr);
  2492. ITPRINT2("%ws LastJoinTime : %s\n" , TabW, TimeStr);
  2493. }
  2494. if (Cxtion->Schedule) {
  2495. ITPRINT1("%ws Schedule\n", TabW);
  2496. FrsPrintTypeSchedule(Severity, Info, Tabs + 3, Cxtion->Schedule, Debsub, uLineNo);
  2497. }
  2498. if (Cxtion->VVector) {
  2499. ITPRINT1("%ws Version Vector\n", TabW);
  2500. }
  2501. if (!Info) {
  2502. DebUnLock();
  2503. }
  2504. if (Cxtion->VVector) {
  2505. FrsPrintTypeVv(Severity, Info, Tabs + 3, Cxtion->VVector, Debsub, uLineNo);
  2506. }
  2507. if (Cxtion->OLCtx) {
  2508. if (!Info) {
  2509. DebLock();
  2510. }
  2511. ITPRINT1("%ws OutLog Partner\n", TabW);
  2512. if (!Info) {
  2513. DebUnLock();
  2514. }
  2515. FrsPrintTypeOutLogPartner(Severity, Info, Tabs + 3, Cxtion->OLCtx,
  2516. -1, "FrsPrintType", Debsub, uLineNo);
  2517. }
  2518. }
  2519. VOID
  2520. FrsPrintTypeCxtions(
  2521. IN ULONG Severity, OPTIONAL
  2522. IN PNTFRSAPI_INFO Info, OPTIONAL
  2523. IN DWORD Tabs, OPTIONAL
  2524. IN PGEN_TABLE Cxtions,
  2525. IN PCHAR Debsub, OPTIONAL
  2526. IN ULONG uLineNo OPTIONAL
  2527. )
  2528. /*++
  2529. Routine Description:
  2530. Print a table of cxtions
  2531. Arguments:
  2532. Severity - for DPRINTs
  2533. Info - RPC output buffer
  2534. Tabs - prettyprint
  2535. Cxtions - Cxtion table
  2536. Debsub - for DPRINTs
  2537. uLineNo - for DPRINTs
  2538. Return Value:
  2539. None.
  2540. --*/
  2541. {
  2542. #undef DEBSUB
  2543. #define DEBSUB "FrsPrintTypeCxtions:"
  2544. PVOID Key;
  2545. PCXTION Cxtion;
  2546. WCHAR TabW[MAX_TAB_WCHARS + 1];
  2547. CHAR Guid[GUID_CHAR_LEN + 1];
  2548. if (!Cxtions) {
  2549. return;
  2550. }
  2551. //
  2552. // Prettyprint indentation
  2553. //
  2554. InfoTabs(Tabs, TabW);
  2555. Key = NULL;
  2556. while (Cxtion = GTabNextDatum(Cxtions, &Key)) {
  2557. FrsPrintTypeCxtion(Severity, Info, Tabs, Cxtion, Debsub, uLineNo);
  2558. }
  2559. }
  2560. VOID
  2561. FrsPrintTypeReplica(
  2562. IN ULONG Severity, OPTIONAL
  2563. IN PNTFRSAPI_INFO Info, OPTIONAL
  2564. IN DWORD Tabs, OPTIONAL
  2565. IN PREPLICA Replica,
  2566. IN PCHAR Debsub, OPTIONAL
  2567. IN ULONG uLineNo OPTIONAL
  2568. )
  2569. /*++
  2570. Routine Description:
  2571. Print a replica and its cxtions.
  2572. Arguments:
  2573. Severity -- Severity level for print. (See debug.c, debug.h)
  2574. Info - Text buffer
  2575. Tabs - Prettyprint prepense
  2576. Replica - Replica struct
  2577. Debsub -- Name of calling subroutine.
  2578. uLineno -- Line number of caller
  2579. MACRO: FRS_PRINT_TYPE
  2580. Return Value:
  2581. none.
  2582. --*/
  2583. {
  2584. #undef DEBSUB
  2585. #define DEBSUB "FrsPrintTypeReplica:"
  2586. CHAR Guid[GUID_CHAR_LEN + 1];
  2587. WCHAR TabW[MAX_TAB_WCHARS + 1];
  2588. CHAR FlagBuffer[120];
  2589. if (!Replica) {
  2590. return;
  2591. }
  2592. InfoTabs(Tabs, TabW);
  2593. if (!Info) {
  2594. DebLock();
  2595. }
  2596. ITPRINTGNAME(Replica->SetName, "%ws Replica: %ws (%s)\n");
  2597. ITPRINTGNAME(Replica->MemberName, "%ws Member : %ws (%s)\n");
  2598. ITPRINTGNAME(Replica->ReplicaName, "%ws Name : %ws (%s)\n");
  2599. ITPRINTGUID(Replica->ReplicaRootGuid, "%ws RootGuid : %s\n");
  2600. ITPRINTGUID(&Replica->ReplicaVersionGuid, "%ws OrigGuid : %s\n");
  2601. ITPRINT2("%ws Reference : %d\n", TabW, Replica->ReferenceCount);
  2602. FrsFlagsToStr(Replica->CnfFlags, ConfigFlagNameTable, sizeof(FlagBuffer), FlagBuffer);
  2603. ITPRINT3("%ws CnfFlags : %08x Flags [%s]\n", TabW,
  2604. Replica->CnfFlags, FlagBuffer);
  2605. ITPRINT2("%ws SetType : %d\n", TabW, Replica->ReplicaSetType);
  2606. ITPRINT2("%ws Consistent : %d\n", TabW, Replica->Consistent);
  2607. ITPRINT2("%ws IsOpen : %d\n", TabW, Replica->IsOpen);
  2608. ITPRINT2("%ws IsJournaling : %d\n", TabW, Replica->IsJournaling);
  2609. ITPRINT2("%ws IsAccepting : %d\n", TabW, Replica->IsAccepting);
  2610. ITPRINT2("%ws IsSeeding : %d\n", TabW, Replica->IsSeeding);
  2611. ITPRINT2("%ws NeedsUpdate : %d\n", TabW, Replica->NeedsUpdate);
  2612. ITPRINT3("%ws ServiceState : %d (%s)\n", TabW,
  2613. Replica->ServiceState, RSS_NAME(Replica->ServiceState));
  2614. ITPRINT2("%ws FStatus : %s\n", TabW, ErrLabelFrs(Replica->FStatus));
  2615. ITPRINT2("%ws Number : %d\n", TabW, Replica->ReplicaNumber);
  2616. ITPRINT2("%ws Root : %ws\n", TabW, Replica->Root);
  2617. ITPRINT2("%ws Stage : %ws\n", TabW, Replica->Stage);
  2618. ITPRINT2("%ws Volume : %ws\n", TabW, Replica->Volume);
  2619. ITPRINT2("%ws FileFilter : %ws\n", TabW, Replica->FileFilterList);
  2620. ITPRINT2("%ws DirFilter : %ws\n", TabW, Replica->DirFilterList);
  2621. ITPRINT2("%ws Expires : %08x %08x\n", TabW,
  2622. PRINTQUAD(Replica->MembershipExpires));
  2623. ITPRINT2("%ws InLogRetry : %d\n", TabW, Replica->InLogRetryCount);
  2624. ITPRINT2("%ws InLogSeq : %d\n", TabW, Replica->InLogSeqNumber);
  2625. ITPRINT2("%ws InLogSeq : %d\n", TabW, Replica->InLogSeqNumber);
  2626. ITPRINT2("%ws ApiState : %d\n", TabW, Replica->NtFrsApi_ServiceState);
  2627. ITPRINT2("%ws ApiStatus : %d\n", TabW, Replica->NtFrsApi_ServiceWStatus);
  2628. ITPRINT2("%ws ApiHack : %d\n", TabW, Replica->NtFrsApi_HackCount);
  2629. ITPRINT2("%ws OutLogSeq : %d\n", TabW, Replica->OutLogSeqNumber);
  2630. ITPRINT2("%ws OutLogJLx : %d\n", TabW, Replica->OutLogJLx);
  2631. ITPRINT2("%ws OutLogJTx : %d\n", TabW, Replica->OutLogJTx);
  2632. ITPRINT2("%ws OutLogMax : %d\n", TabW, Replica->OutLogCOMax);
  2633. ITPRINT2("%ws OutLogState : %d\n", TabW, Replica->OutLogWorkState);
  2634. ITPRINT2("%ws OutLogVV's : %d\n", TabW, Replica->OutLogCountVVJoins);
  2635. ITPRINT2("%ws OutLogClean : %d\n", TabW, Replica->OutLogDoCleanup);
  2636. ITPRINT2("%ws PreinstallFID : %08x %08x\n", TabW,
  2637. PRINTQUAD(Replica->PreInstallFid));
  2638. ITPRINT2("%ws InLogCommit : %08x %08x\n", TabW,
  2639. PRINTQUAD(Replica->InlogCommitUsn));
  2640. ITPRINT2("%ws JrnlStart : %08x %08x\n", TabW,
  2641. PRINTQUAD(Replica->JrnlRecoveryStart));
  2642. ITPRINT2("%ws JrnlEnd : %08x %08x\n", TabW,
  2643. PRINTQUAD(Replica->JrnlRecoveryEnd));
  2644. ITPRINT2("%ws LastUsn : %08x %08x\n", TabW,
  2645. PRINTQUAD(Replica->LastUsnRecordProcessed));
  2646. if (Replica->Schedule) {
  2647. ITPRINT1("%ws Schedule\n", TabW);
  2648. FrsPrintTypeSchedule(Severity, Info, Tabs + 3, Replica->Schedule, Debsub, uLineNo);
  2649. }
  2650. if (Replica->VVector) {
  2651. ITPRINT1("%ws Version Vector\n", TabW);
  2652. }
  2653. if (!Info) {
  2654. DebUnLock();
  2655. }
  2656. FrsPrintTypeVv(Severity, Info, Tabs + 3, Replica->VVector, Debsub, uLineNo);
  2657. FrsPrintTypeCxtions(Severity, Info, Tabs + 1, Replica->Cxtions, Debsub, uLineNo);
  2658. }
  2659. VOID
  2660. FrsPrintType(
  2661. IN ULONG Severity,
  2662. IN PVOID Node,
  2663. IN PCHAR Debsub,
  2664. IN ULONG uLineNo
  2665. )
  2666. /*++
  2667. Routine Description:
  2668. This routine prints out the contents of a given node,
  2669. performing any node specific interpretation.
  2670. Arguments:
  2671. Severity -- Severity level for print. (See debug.c, debug.h)
  2672. Node - The address of the node to print.
  2673. Debsub -- Name of calling subroutine.
  2674. uLineno -- Line number of caller
  2675. MACRO: FRS_PRINT_TYPE
  2676. Return Value:
  2677. none.
  2678. --*/
  2679. {
  2680. #undef DEBSUB
  2681. #define DEBSUB "FrsPrintType:"
  2682. ULONG NodeSize;
  2683. ULONG NodeType;
  2684. ULONG Marker;
  2685. PREPLICA Replica;
  2686. PREPLICA_THREAD_CTX RtCtx;
  2687. PTABLE_CTX TableCtx;
  2688. PTHREAD_CTX ThreadCtx;
  2689. ULONG i;
  2690. PVOLUME_MONITOR_ENTRY pVme;
  2691. PFILTER_TABLE_ENTRY FilterEntry;
  2692. PQHASH_TABLE QhashTable;
  2693. PLIST_ENTRY Entry;
  2694. PCXTION Cxtion;
  2695. SYSTEMTIME ST;
  2696. PWILDCARD_FILTER_ENTRY WildcardEntry;
  2697. POUT_LOG_PARTNER Olp;
  2698. PCONFIG_NODE ConfigNode;
  2699. PULONG pULong;
  2700. PCHANGE_ORDER_ENTRY CoEntry;
  2701. PCHANGE_ORDER_COMMAND CoCmd;
  2702. CHAR GuidStr[GUID_CHAR_LEN];
  2703. CHAR TimeStr[TIME_STRING_LENGTH];
  2704. CHAR FlagBuffer[160];
  2705. if (!DoDebug(Severity, Debsub)) {
  2706. return;
  2707. }
  2708. //
  2709. // Get debug lock so our output stays in one piece.
  2710. //
  2711. DebLock();
  2712. if (Node != NULL) {
  2713. NodeType = (ULONG) (((PFRS_NODE_HEADER) Node)->Type);
  2714. NodeSize = (ULONG) (((PFRS_NODE_HEADER) Node)->Size);
  2715. FRS_DEB_PRINT("Display for Node: ...%s... === === === ===\n",
  2716. NodeTypeNames[NodeType]);
  2717. } else {
  2718. FRS_DEB_PRINT("Display for Node: ...<null>... === === === ===\n\n",
  2719. NULL);
  2720. DebUnLock();
  2721. return;
  2722. }
  2723. switch (NodeType) {
  2724. //
  2725. // Print a Thread Context struct
  2726. //
  2727. case THREAD_CONTEXT_TYPE:
  2728. if (NodeSize != sizeof(THREAD_CTX)) {
  2729. FRS_DEB_PRINT("FrsPrintType - Bad node size %d for THREAD_CONTEXT\n",
  2730. NodeSize);
  2731. break;
  2732. }
  2733. FRS_DEB_PRINT("Address %08x\n", Node);
  2734. ThreadCtx = (PTHREAD_CTX) Node;
  2735. break;
  2736. //
  2737. // Print a Replica struct
  2738. //
  2739. case REPLICA_TYPE:
  2740. if (NodeSize != sizeof(REPLICA)) {
  2741. FRS_DEB_PRINT("FrsPrintType - Bad node size %d for REPLICA\n", NodeSize);
  2742. break;
  2743. }
  2744. DebUnLock();
  2745. FrsPrintTypeReplica(Severity, NULL, 0, (PREPLICA) Node, Debsub, uLineNo);
  2746. DebLock();
  2747. break;
  2748. //
  2749. // Print a Replica Thread Context struct
  2750. //
  2751. case REPLICA_THREAD_TYPE:
  2752. if (NodeSize != sizeof(REPLICA_THREAD_CTX)) {
  2753. FRS_DEB_PRINT("FrsPrintType - Bad node size %d for REPLICA_THREAD_CTX\n",
  2754. NodeSize);
  2755. break;
  2756. }
  2757. FRS_DEB_PRINT("Address %08x\n", Node);
  2758. RtCtx = (PREPLICA_THREAD_CTX) Node;
  2759. //
  2760. // Get the base of the array of TableCtx structs from the replica thread
  2761. // context struct.
  2762. //
  2763. TableCtx = RtCtx->RtCtxTables;
  2764. //
  2765. // Release the memory for each table context struct.
  2766. //
  2767. //for (i=0; i<TABLE_TYPE_MAX; ++i, ++TableCtx) {
  2768. //}
  2769. break;
  2770. //
  2771. // Print a topology node
  2772. //
  2773. case CONFIG_NODE_TYPE:
  2774. if (NodeSize != sizeof(CONFIG_NODE)) {
  2775. FRS_DEB_PRINT("FrsPrintType - Bad node size %d for CONFIG_NODE\n",
  2776. NodeSize);
  2777. break;
  2778. }
  2779. ConfigNode = Node;
  2780. FRS_DEB_PRINT("CONFIG NODE Address %08x\n", ConfigNode);
  2781. FrsPrintGNameForNode(Severity, ConfigNode->Name, L"\t", L"Node",
  2782. Debsub, uLineNo);
  2783. FrsPrintGNameForNode(Severity, ConfigNode->PartnerName, L"\t", L"Partner",
  2784. Debsub, uLineNo);
  2785. FRS_DEB_PRINT("\tDsObjectType %ws\n", DsConfigTypeName[ConfigNode->DsObjectType]);
  2786. FRS_DEB_PRINT("\tConsistent %s\n", (ConfigNode->Consistent) ? "TRUE" : "FALSE");
  2787. FRS_DEB_PRINT("\tInbound %s\n", (ConfigNode->Inbound) ? "TRUE" : "FALSE");
  2788. FRS_DEB_PRINT("\tThisComputer %s\n", (ConfigNode->ThisComputer) ? "TRUE" : "FALSE");
  2789. FRS_DEB_PRINT("\tUsnChanged %ws\n", ConfigNode->UsnChanged);
  2790. FRS_DEB_PRINT("\tDn %ws\n", ConfigNode->Dn);
  2791. FRS_DEB_PRINT("\tPrincName %ws\n", ConfigNode->PrincName);
  2792. FRS_DEB_PRINT("\tDnsName %ws\n", ConfigNode->DnsName);
  2793. FRS_DEB_PRINT("\tPartnerDnsName %ws\n", ConfigNode->PartnerDnsName);
  2794. FRS_DEB_PRINT("\tSid %ws\n", ConfigNode->Sid);
  2795. FRS_DEB_PRINT("\tPartnerSid %ws\n", ConfigNode->PartnerSid);
  2796. FRS_DEB_PRINT("\tPartnerDn %ws\n", ConfigNode->PartnerDn);
  2797. FRS_DEB_PRINT("\tPartnerCoDn %ws\n", ConfigNode->PartnerCoDn);
  2798. FRS_DEB_PRINT("\tSettingsDn %ws\n", ConfigNode->SettingsDn);
  2799. FRS_DEB_PRINT("\tComputerDn %ws\n", ConfigNode->ComputerDn);
  2800. FRS_DEB_PRINT("\tMemberDn %ws\n", ConfigNode->MemberDn);
  2801. FRS_DEB_PRINT("\tSetType %ws\n", ConfigNode->SetType);
  2802. FRS_DEB_PRINT("\tRoot %ws\n", ConfigNode->Root);
  2803. FRS_DEB_PRINT("\tStage %ws\n", ConfigNode->Stage);
  2804. FRS_DEB_PRINT("\tWorking %ws\n", ConfigNode->Working);
  2805. FRS_DEB_PRINT("\tFileFilterList %ws\n", ConfigNode->FileFilterList);
  2806. FRS_DEB_PRINT("\tDirFilterList %ws\n", ConfigNode->DirFilterList);
  2807. FRS_DEB_PRINT("\tSchedule %08x\n",ConfigNode->Schedule);
  2808. FRS_DEB_PRINT("\tScheduleLength %d\n", ConfigNode->ScheduleLength);
  2809. FRS_DEB_PRINT("\tUsnChanged %ws\n", ConfigNode->UsnChanged);
  2810. FRS_DEB_PRINT("\tSameSite %s\n", (ConfigNode->SameSite) ? "TRUE" : "FALSE");
  2811. FRS_DEB_PRINT("\tEnabledCxtion %ws\n", ConfigNode->EnabledCxtion);
  2812. FRS_DEB_PRINT("\tVerifiedOverlap %s\n", (ConfigNode->VerifiedOverlap) ? "TRUE" : "FALSE");
  2813. break;
  2814. //
  2815. // Print a connection
  2816. //
  2817. case CXTION_TYPE:
  2818. if (NodeSize != sizeof(CXTION)) {
  2819. FRS_DEB_PRINT("FrsPrintType - Bad node size %d for CXTION\n",
  2820. NodeSize);
  2821. break;
  2822. }
  2823. DebUnLock();
  2824. FrsPrintTypeCxtion(Severity, NULL, 0, (PCXTION)Node, Debsub, uLineNo);
  2825. DebLock();
  2826. break;
  2827. //
  2828. // Print a guid/rpc handle
  2829. //
  2830. case GHANDLE_TYPE:
  2831. if (NodeSize != sizeof(GHANDLE)) {
  2832. FRS_DEB_PRINT("FrsPrintType - Bad node size %d for GHANDLE\n",
  2833. NodeSize);
  2834. break;
  2835. }
  2836. GuidToStr(&(((PGHANDLE)Node)->Guid), GuidStr);
  2837. FRS_DEB_PRINT2("Address %08x, Cxtion Guid : %s\n", Node, GuidStr);
  2838. break;
  2839. //
  2840. // Print a generic table
  2841. //
  2842. case GEN_TABLE_TYPE:
  2843. if (NodeSize != sizeof(GEN_TABLE)) {
  2844. FRS_DEB_PRINT("FrsPrintType - Bad node size %d for GEN_TABLE\n",
  2845. NodeSize);
  2846. break;
  2847. }
  2848. FRS_DEB_PRINT("Address %08x\n", Node);
  2849. break;
  2850. //
  2851. // Print a generic thread context
  2852. //
  2853. case THREAD_TYPE:
  2854. if (NodeSize != sizeof(FRS_THREAD)) {
  2855. FRS_DEB_PRINT("FrsPrintType - Bad node size %d for FRS_THREAD\n",
  2856. NodeSize);
  2857. break;
  2858. }
  2859. FRS_DEB_PRINT("Address %08x\n", Node);
  2860. break;
  2861. //
  2862. // Print a journal read buffer.
  2863. //
  2864. case JBUFFER_TYPE:
  2865. if (NodeSize != SizeOfJournalBuffer) {
  2866. FRS_DEB_PRINT("FrsPrintType - Bad node size %d for JBUFFER\n",
  2867. NodeSize);
  2868. break;
  2869. }
  2870. FRS_DEB_PRINT("Address %08x\n", Node);
  2871. break;
  2872. //
  2873. // Print a journal volume monitor entry.
  2874. //
  2875. case VOLUME_MONITOR_ENTRY_TYPE:
  2876. if (NodeSize != sizeof(VOLUME_MONITOR_ENTRY)) {
  2877. FRS_DEB_PRINT("FrsPrintType - Bad node size %d for VOLUME_MONITOR_ENTRY\n",
  2878. NodeSize);
  2879. break;
  2880. }
  2881. FRS_DEB_PRINT("Address %08x\n", Node);
  2882. pVme = (PVOLUME_MONITOR_ENTRY) Node;
  2883. break;
  2884. //
  2885. // Print a command packet.
  2886. //
  2887. case COMMAND_PACKET_TYPE:
  2888. if (NodeSize != sizeof(COMMAND_PACKET)) {
  2889. FRS_DEB_PRINT("FrsPrintType - Bad node size %d for COMMAND_PACKET\n",
  2890. NodeSize);
  2891. break;
  2892. }
  2893. FRS_DEB_PRINT("Address %08x\n", Node);
  2894. break;
  2895. //
  2896. // Print a generic hash table struct.
  2897. //
  2898. case GENERIC_HASH_TABLE_TYPE:
  2899. if (NodeSize != sizeof(GENERIC_HASH_TABLE)) {
  2900. FRS_DEB_PRINT("FrsPrintType - Bad node size %d for GENERIC_HASH_TABLE\n",
  2901. NodeSize);
  2902. break;
  2903. }
  2904. FRS_DEB_PRINT("Address %08x\n", Node);
  2905. break;
  2906. //
  2907. // Print a Change Order Entry struct.
  2908. //
  2909. case CHANGE_ORDER_ENTRY_TYPE:
  2910. if (NodeSize != sizeof(CHANGE_ORDER_ENTRY)) {
  2911. FRS_DEB_PRINT("FrsPrintType - Bad node size %d for CHANGE_ORDER_ENTRY\n",
  2912. NodeSize);
  2913. break;
  2914. }
  2915. CoEntry = (PCHANGE_ORDER_ENTRY)Node;
  2916. CoCmd = &CoEntry->Cmd;
  2917. GuidToStr(&CoCmd->ChangeOrderGuid, GuidStr);
  2918. FRS_DEB_PRINT3("Address %08x ***%s CO*** - %s\n",
  2919. CoEntry,
  2920. (CO_FLAG_ON(CoEntry, CO_FLAG_LOCALCO)) ? "LOCAL" : "REMOTE",
  2921. GuidStr);
  2922. FRS_DEB_PRINT3("Node Addr: %08x, HashValue: %08x RC: %d\n",
  2923. CoEntry,
  2924. CoEntry->HashEntryHeader.HashValue,
  2925. CoEntry->HashEntryHeader.ReferenceCount);
  2926. FRS_DEB_PRINT2("List Entry - %08x, %08x\n",
  2927. CoEntry->HashEntryHeader.ListEntry.Flink,
  2928. CoEntry->HashEntryHeader.ListEntry.Blink);
  2929. FRS_DEB_PRINT2("FileRef: %08lx %08lx, ParentRef: %08lx %08lx\n",
  2930. PRINTQUAD(CoEntry->FileReferenceNumber),
  2931. PRINTQUAD(CoEntry->ParentFileReferenceNumber));
  2932. FRS_DEB_PRINT("\n", NULL);
  2933. FRS_DEB_PRINT("STATE: %s\n", PRINT_CO_STATE(CoEntry));
  2934. FrsFlagsToStr(CoEntry->EntryFlags, CoeFlagNameTable, sizeof(FlagBuffer), FlagBuffer);
  2935. FRS_DEB_PRINT2("EntryFlags: %08x, Flags [%s]\n", CoEntry->EntryFlags, FlagBuffer);
  2936. FrsFlagsToStr(CoEntry->IssueCleanup, IscuFlagNameTable, sizeof(FlagBuffer), FlagBuffer);
  2937. FRS_DEB_PRINT2("ISCU Flags: %08x, Flags [%s]\n", CoEntry->IssueCleanup, FlagBuffer);
  2938. FRS_DEB_PRINT("\n", NULL);
  2939. GuidToStr(&CoCmd->OriginatorGuid, GuidStr);
  2940. FRS_DEB_PRINT("OrigGuid : %s\n", GuidStr);
  2941. GuidToStr(&CoCmd->FileGuid, GuidStr);
  2942. FRS_DEB_PRINT("FileGuid : %s\n", GuidStr);
  2943. GuidToStr(&CoCmd->OldParentGuid, GuidStr);
  2944. FRS_DEB_PRINT("OParGuid : %s\n",GuidStr);
  2945. GuidToStr(&CoCmd->NewParentGuid, GuidStr);
  2946. FRS_DEB_PRINT("NParGuid : %s\n", GuidStr);
  2947. GuidToStr(&CoCmd->CxtionGuid, GuidStr);
  2948. FRS_DEB_PRINT2("CxtionGuid: %s (%08x)\n", GuidStr, CoEntry->Cxtion);
  2949. FileTimeToString((PFILETIME) &CoCmd->AckVersion, TimeStr);
  2950. FRS_DEB_PRINT("AckVersion: %s\n", TimeStr);
  2951. FRS_DEB_PRINT("\n", NULL);
  2952. FRS_DEB_PRINT2("FileName: %ws, Length: %d\n", CoEntry->UFileName.Buffer,
  2953. CoCmd->FileNameLength);
  2954. FrsFlagsToStr(CoCmd->ContentCmd, UsnReasonNameTable, sizeof(FlagBuffer), FlagBuffer);
  2955. FRS_DEB_PRINT2("ContentCmd: %08x, Flags [%s]\n", CoCmd->ContentCmd, FlagBuffer);
  2956. FRS_DEB_PRINT("\n", NULL);
  2957. FrsFlagsToStr(CoCmd->Flags, CoFlagNameTable, sizeof(FlagBuffer), FlagBuffer);
  2958. FRS_DEB_PRINT2("CoFlags: %08x, Flags [%s]\n", CoCmd->Flags, FlagBuffer);
  2959. FrsFlagsToStr(CoCmd->IFlags, CoIFlagNameTable, sizeof(FlagBuffer), FlagBuffer);
  2960. DebPrintNoLock(Severity, TRUE,
  2961. "IFlags: %08x, Flags [%s] TimeToRun: %7d, EntryCreateTime: %7d\n",
  2962. Debsub, uLineNo,
  2963. CoCmd->IFlags, FlagBuffer,
  2964. CoEntry->TimeToRun,
  2965. CoEntry->EntryCreateTime);
  2966. DebPrintNoLock(Severity, TRUE,
  2967. "LocationCmd: %s (%d), CO STATE: %s File/Dir: %d\n",
  2968. Debsub, uLineNo,
  2969. CoLocationNames[GET_CO_LOCATION_CMD(CoEntry->Cmd, Command)],
  2970. GET_CO_LOCATION_CMD(CoEntry->Cmd, Command),
  2971. PRINT_CO_STATE(CoEntry),
  2972. GET_CO_LOCATION_CMD(CoEntry->Cmd, DirOrFile));
  2973. FRS_DEB_PRINT("\n", NULL);
  2974. FRS_DEB_PRINT2("OriginalParentFid: %08lx %08lx, NewParentFid: %08lx %08lx\n",
  2975. PRINTQUAD(CoEntry->OriginalParentFid),
  2976. PRINTQUAD(CoEntry->NewParentFid));
  2977. DebPrintNoLock(Severity, TRUE,
  2978. "OriginalReplica: %ws (%d), NewReplica: %ws (%d)\n",
  2979. Debsub, uLineNo,
  2980. CoEntry->OriginalReplica->ReplicaName->Name,
  2981. CoCmd->OriginalReplicaNum,
  2982. CoEntry->NewReplica->ReplicaName->Name,
  2983. CoCmd->NewReplicaNum);
  2984. if (CoCmd->Extension != NULL) {
  2985. pULong = (PULONG) CoCmd->Extension;
  2986. DebPrintNoLock(Severity, TRUE,
  2987. "CO Extension: (%08x) %08x %08x %08x %08x %08x %08x %08x %08x\n",
  2988. Debsub, uLineNo, pULong,
  2989. *(pULong+0), *(pULong+1), *(pULong+2), *(pULong+3),
  2990. *(pULong+4), *(pULong+5), *(pULong+6), *(pULong+7));
  2991. } else {
  2992. FRS_DEB_PRINT("CO Extension: Null\n", NULL);
  2993. }
  2994. FRS_DEB_PRINT("\n", NULL);
  2995. FRS_DEB_PRINT3("File Attributes: %08x, SeqNum: %08x, FileSize: %08x %08x\n",
  2996. CoCmd->FileAttributes,
  2997. CoCmd->SequenceNumber,
  2998. PRINTQUAD(CoCmd->FileSize));
  2999. FRS_DEB_PRINT("FrsVsn: %08x %08x\n", PRINTQUAD(CoCmd->FrsVsn));
  3000. FRS_DEB_PRINT3("Usn: %08x %08x CoFileUsn: %08x %08x JrnlFirstUsn: %08x %08x\n",
  3001. PRINTQUAD(CoCmd->JrnlUsn),
  3002. PRINTQUAD(CoCmd->FileUsn),
  3003. PRINTQUAD(CoCmd->JrnlFirstUsn));
  3004. FRS_DEB_PRINT("Version: %08x ", CoCmd->FileVersionNumber);
  3005. FileTimeToString((PFILETIME) &CoCmd->EventTime.QuadPart, TimeStr);
  3006. DebPrintNoLock(Severity, FALSE, "EventTime: %s\n", Debsub, uLineNo, TimeStr);
  3007. break;
  3008. //
  3009. // Print a Filter Table Entry struct.
  3010. //
  3011. case FILTER_TABLE_ENTRY_TYPE:
  3012. if (NodeSize != sizeof(FILTER_TABLE_ENTRY)) {
  3013. FRS_DEB_PRINT("FrsPrintType - Bad node size %d for FILTER_TABLE_ENTRY\n",
  3014. NodeSize);
  3015. break;
  3016. }
  3017. FRS_DEB_PRINT("Address %08x\n", Node);
  3018. FilterEntry = (PFILTER_TABLE_ENTRY)Node;
  3019. break;
  3020. //
  3021. // Print a QHASH table struct.
  3022. //
  3023. case QHASH_TABLE_TYPE:
  3024. QhashTable = (PQHASH_TABLE)Node;
  3025. if (NodeSize != QhashTable->BaseAllocSize) {
  3026. FRS_DEB_PRINT("FrsPrintType - Bad node size %d for QHASH_TABLE\n",
  3027. NodeSize);
  3028. break;
  3029. }
  3030. FRS_DEB_PRINT("Table Address : %08x\n", QhashTable);
  3031. FRS_DEB_PRINT("BaseAllocSize : %8d\n", QhashTable->BaseAllocSize);
  3032. FRS_DEB_PRINT("ExtensionAllocSize : %8d\n", QhashTable->ExtensionAllocSize);
  3033. FRS_DEB_PRINT("ExtensionListHead : %08x\n", QhashTable->ExtensionListHead);
  3034. FRS_DEB_PRINT("FreeList : %08x\n", QhashTable->FreeList);
  3035. FRS_DEB_PRINT("Lock : %08x\n", QhashTable->Lock);
  3036. FRS_DEB_PRINT("HeapHandle : %08x\n", QhashTable->HeapHandle);
  3037. FRS_DEB_PRINT("HashCalc : %08x\n", QhashTable->HashCalc);
  3038. FRS_DEB_PRINT("NumberEntries : %8d\n", QhashTable->NumberEntries);
  3039. FRS_DEB_PRINT("HashRowBase : %08x\n", QhashTable->HashRowBase);
  3040. break;
  3041. //
  3042. // Print an Output Log Partner struct.
  3043. //
  3044. case OUT_LOG_PARTNER_TYPE:
  3045. if (NodeSize != sizeof(OUT_LOG_PARTNER)) {
  3046. FRS_DEB_PRINT("FrsPrintType - Bad node size %d for OUT_LOG_PARTNER\n",
  3047. NodeSize);
  3048. break;
  3049. }
  3050. DebUnLock();
  3051. FrsPrintTypeOutLogPartner(Severity, NULL, 0, (POUT_LOG_PARTNER)Node,
  3052. -1, "FrsPrintType", Debsub, uLineNo);
  3053. DebLock();
  3054. break;
  3055. //
  3056. // Print a Wildcard file filter Entry struct.
  3057. //
  3058. case WILDCARD_FILTER_ENTRY_TYPE:
  3059. if (NodeSize != sizeof(WILDCARD_FILTER_ENTRY)) {
  3060. FRS_DEB_PRINT("FrsPrintType - Bad node size %d for WILDCARD_FILTER_ENTRY\n",
  3061. NodeSize);
  3062. break;
  3063. }
  3064. FRS_DEB_PRINT( "Address %08x\n", Node);
  3065. WildcardEntry = (PWILDCARD_FILTER_ENTRY)Node;
  3066. DebPrintNoLock(Severity, TRUE,
  3067. "Flags: %08x, Wildcard FileName: %ws, Length: %d\n",
  3068. Debsub, uLineNo,
  3069. WildcardEntry->Flags,
  3070. WildcardEntry->UFileName.Buffer,
  3071. (ULONG)WildcardEntry->UFileName.Length);
  3072. break;
  3073. //
  3074. // Invalid Node Type
  3075. //
  3076. default:
  3077. Node = NULL;
  3078. DebPrintNoLock(0, TRUE,
  3079. "Internal error - invalid node type - %d\n",
  3080. Debsub, uLineNo, NodeType);
  3081. }
  3082. FRS_DEB_PRINT("-----------------------\n", NULL);
  3083. DebUnLock();
  3084. }
  3085. VOID
  3086. FrsAllocUnicodeString(
  3087. PUNICODE_STRING Ustr,
  3088. PWCHAR InternalBuffer,
  3089. PWCHAR Wstr,
  3090. USHORT WstrLength
  3091. )
  3092. /*++
  3093. Routine Description:
  3094. Initialize a unicode string with the contents of Wstr if the two are
  3095. not already the same. If the length of the new string is greater than
  3096. the buffer space currently allocated in Ustr then allocate a new
  3097. buffer for Ustr. In some structures the initial Ustr buffer allocation
  3098. is allocated as part of the initial structure allocation. The address
  3099. of this internal buffer is passed so it can be compared with the address
  3100. in Ustr->Buffer. If they match then no free memory call is made on
  3101. the Ustr->Buffer address.
  3102. Arguments:
  3103. Ustr -- The UNICODE_STRING to init.
  3104. InternalBuffer -- A ptr to the internal buffer address that was preallocated
  3105. with the containing struct. If there was no internal
  3106. buffer pass NULL.
  3107. Wstr -- The new WCHAR string.
  3108. WstrLength -- The length of the new string in bytes not including the
  3109. trailing UNICODE_NULL.
  3110. Return Value:
  3111. None.
  3112. --*/
  3113. {
  3114. #undef DEBSUB
  3115. #define DEBSUB "FrsAllocUnicodeString:"
  3116. //
  3117. // See if the name part changed and if so save it.
  3118. //
  3119. if ((Ustr->Length != WstrLength) ||
  3120. (wcsncmp(Ustr->Buffer, Wstr, Ustr->Length/sizeof(WCHAR)) != 0)) {
  3121. //
  3122. // If string to big (including space for a NULL), alloc new buffer.
  3123. //
  3124. if (WstrLength >= Ustr->MaximumLength) {
  3125. //
  3126. // Alloc room for new one, freeing the old one if not internal alloc.
  3127. //
  3128. if ((Ustr->Buffer != InternalBuffer) && (Ustr->Buffer != NULL)) {
  3129. FrsFree(Ustr->Buffer);
  3130. }
  3131. Ustr->MaximumLength = WstrLength+2;
  3132. Ustr->Buffer = FrsAlloc(WstrLength+2);
  3133. }
  3134. //
  3135. // Copy in new name. Length does not include the trailing NULL at end.
  3136. //
  3137. CopyMemory(Ustr->Buffer, Wstr, WstrLength);
  3138. Ustr->Buffer[WstrLength/2] = UNICODE_NULL;
  3139. Ustr->Length = WstrLength;
  3140. }
  3141. }
  3142. #define CO_TRACE_FORMAT ":: CoG %08x, CxtG %08x, FV %5d, FID %08x %08x, FN: %-15ws, [%s]\n"
  3143. #define REPLICA_TRACE_FORMAT ":S:Adr %08x, Cmd %04x, Flg %04x, %ws (%d), %s, Err %d [%s]\n"
  3144. #define REPLICA_TRACE_FORMAT2 ":S:Adr %08x, %ws (%d), %s, [%s]\n"
  3145. #define CXTION_TRACE_FORMAT ":X: %08x, Nam %ws, Sta %s%s, %ws (%d), %s, Err %d [%s]\n"
  3146. VOID
  3147. ChgOrdTraceCoe(
  3148. IN ULONG Severity,
  3149. IN PCHAR Debsub,
  3150. IN ULONG uLineNo,
  3151. IN PCHANGE_ORDER_ENTRY Coe,
  3152. IN PCHAR Text
  3153. )
  3154. /*++
  3155. Routine Description:
  3156. Print a change order trace record using the change order entry and the
  3157. Text string.
  3158. Arguments:
  3159. Return Value:
  3160. None
  3161. --*/
  3162. {
  3163. #undef DEBSUB
  3164. #define DEBSUB "ChgOrdTraceCoe:"
  3165. ULONGLONG FileRef;
  3166. FileRef = (Coe != NULL) ? Coe->FileReferenceNumber : QUADZERO;
  3167. DebPrint(Severity,
  3168. (PUCHAR) CO_TRACE_FORMAT,
  3169. Debsub,
  3170. uLineNo,
  3171. (Coe != NULL) ? Coe->Cmd.ChangeOrderGuid.Data1 : 0,
  3172. (Coe != NULL) ? Coe->Cmd.CxtionGuid.Data1 : 0,
  3173. (Coe != NULL) ? Coe->Cmd.FileVersionNumber : 0,
  3174. PRINTQUAD(FileRef),
  3175. (Coe != NULL) ? Coe->Cmd.FileName : L"<Null Coe>",
  3176. Text);
  3177. }
  3178. VOID
  3179. ChgOrdTraceCoeW(
  3180. IN ULONG Severity,
  3181. IN PCHAR Debsub,
  3182. IN ULONG uLineNo,
  3183. IN PCHANGE_ORDER_ENTRY Coe,
  3184. IN PCHAR Text,
  3185. IN ULONG WStatus
  3186. )
  3187. /*++
  3188. Routine Description:
  3189. Print a change order trace record using the change order entry and the
  3190. Text string and Win32 status.
  3191. Arguments:
  3192. Return Value:
  3193. None
  3194. --*/
  3195. {
  3196. #undef DEBSUB
  3197. #define DEBSUB "ChgOrdTraceCoeW:"
  3198. CHAR Tstr[256];
  3199. _snprintf(Tstr, sizeof(Tstr), "%s (%s)", Text, ErrLabelW32(WStatus));
  3200. Tstr[sizeof(Tstr)-1] = '\0';
  3201. ChgOrdTraceCoe(Severity, Debsub, uLineNo, Coe, Tstr);
  3202. }
  3203. VOID
  3204. ChgOrdTraceCoeF(
  3205. IN ULONG Severity,
  3206. IN PCHAR Debsub,
  3207. IN ULONG uLineNo,
  3208. IN PCHANGE_ORDER_ENTRY Coe,
  3209. IN PCHAR Text,
  3210. IN ULONG FStatus
  3211. )
  3212. /*++
  3213. Routine Description:
  3214. Print a change order trace record using the change order entry and the
  3215. Text string and Frs Error status.
  3216. Arguments:
  3217. Return Value:
  3218. None
  3219. --*/
  3220. {
  3221. #undef DEBSUB
  3222. #define DEBSUB "ChgOrdTraceCoeF:"
  3223. CHAR Tstr[128];
  3224. _snprintf(Tstr, sizeof(Tstr), "%s (%s)", Text, ErrLabelFrs(FStatus));
  3225. Tstr[sizeof(Tstr)-1] = '\0';
  3226. ChgOrdTraceCoe(Severity, Debsub, uLineNo, Coe, Tstr);
  3227. }
  3228. VOID
  3229. ChgOrdTraceCoeX(
  3230. IN ULONG Severity,
  3231. IN PCHAR Debsub,
  3232. IN ULONG uLineNo,
  3233. IN PCHANGE_ORDER_ENTRY Coe,
  3234. IN PCHAR Text,
  3235. IN ULONG Data
  3236. )
  3237. /*++
  3238. Routine Description:
  3239. Print a change order trace record using the change order entry and the
  3240. Text string and Win32 status.
  3241. Arguments:
  3242. Return Value:
  3243. None
  3244. --*/
  3245. {
  3246. #undef DEBSUB
  3247. #define DEBSUB "ChgOrdTraceCoeX:"
  3248. CHAR Tstr[256];
  3249. _snprintf(Tstr, sizeof(Tstr), "%s (%08x)", Text, Data);
  3250. Tstr[sizeof(Tstr)-1] = '\0';
  3251. ChgOrdTraceCoe(Severity, Debsub, uLineNo, Coe, Tstr);
  3252. }
  3253. VOID
  3254. ChgOrdTraceCoc(
  3255. IN ULONG Severity,
  3256. IN PCHAR Debsub,
  3257. IN ULONG uLineNo,
  3258. IN PCHANGE_ORDER_COMMAND Coc,
  3259. IN PCHAR Text
  3260. )
  3261. /*++
  3262. Routine Description:
  3263. Print a change order trace record using the change order command and the
  3264. Text string.
  3265. Arguments:
  3266. Return Value:
  3267. None
  3268. --*/
  3269. {
  3270. #undef DEBSUB
  3271. #define DEBSUB "ChgOrdTraceCoc:"
  3272. ULONGLONG FileRef = QUADZERO;
  3273. DebPrint(Severity,
  3274. (PUCHAR) CO_TRACE_FORMAT,
  3275. Debsub,
  3276. uLineNo,
  3277. (Coc != NULL) ? Coc->ChangeOrderGuid.Data1 : 0,
  3278. (Coc != NULL) ? Coc->CxtionGuid.Data1 : 0,
  3279. (Coc != NULL) ? Coc->FileVersionNumber : 0,
  3280. PRINTQUAD(FileRef),
  3281. (Coc != NULL) ? Coc->FileName : L"<Null Coc>",
  3282. Text);
  3283. }
  3284. VOID
  3285. ChgOrdTraceCocW(
  3286. IN ULONG Severity,
  3287. IN PCHAR Debsub,
  3288. IN ULONG uLineNo,
  3289. IN PCHANGE_ORDER_COMMAND Coc,
  3290. IN PCHAR Text,
  3291. IN ULONG WStatus
  3292. )
  3293. /*++
  3294. Routine Description:
  3295. Print a change order trace record using the change order command and the
  3296. Text string and Win32 status.
  3297. Arguments:
  3298. Return Value:
  3299. None
  3300. --*/
  3301. {
  3302. #undef DEBSUB
  3303. #define DEBSUB "ChgOrdTraceCocW:"
  3304. CHAR Tstr[256];
  3305. _snprintf(Tstr, sizeof(Tstr), "%s (%s)", Text, ErrLabelW32(WStatus));
  3306. Tstr[sizeof(Tstr)-1] = '\0';
  3307. ChgOrdTraceCoc(Severity, Debsub, uLineNo, Coc, Tstr);
  3308. }
  3309. VOID
  3310. ReplicaStateTrace(
  3311. IN ULONG Severity,
  3312. IN PCHAR Debsub,
  3313. IN ULONG uLineNo,
  3314. IN PCOMMAND_PACKET Cmd,
  3315. IN PREPLICA Replica,
  3316. IN ULONG Status,
  3317. IN PCHAR Text
  3318. )
  3319. /*++
  3320. Routine Description:
  3321. Print a replica state trace record using the command packet and the
  3322. status and Text string.
  3323. Arguments:
  3324. Return Value:
  3325. None
  3326. --*/
  3327. {
  3328. #undef DEBSUB
  3329. #define DEBSUB "ReplicaStateTrace:"
  3330. PWSTR ReplicaName;
  3331. if ((Replica != NULL) &&
  3332. (Replica->ReplicaName != NULL) &&
  3333. (Replica->ReplicaName->Name != NULL)) {
  3334. ReplicaName = Replica->ReplicaName->Name;
  3335. } else {
  3336. ReplicaName = L"<null>";
  3337. }
  3338. DebPrint(Severity,
  3339. (PUCHAR) REPLICA_TRACE_FORMAT,
  3340. Debsub,
  3341. uLineNo,
  3342. PtrToUlong(Cmd),
  3343. (Cmd != NULL) ? Cmd->Command : 0xFFFF,
  3344. (Cmd != NULL) ? Cmd->Flags : 0xFFFF,
  3345. ReplicaName,
  3346. ReplicaAddrToId(Replica),
  3347. (Replica != NULL) ? RSS_NAME(Replica->ServiceState) : "<null>",
  3348. Status,
  3349. Text);
  3350. }
  3351. VOID
  3352. ReplicaStateTrace2(
  3353. IN ULONG Severity,
  3354. IN PCHAR Debsub,
  3355. IN ULONG uLineNo,
  3356. IN PREPLICA Replica,
  3357. IN PCHAR Text
  3358. )
  3359. /*++
  3360. Routine Description:
  3361. Print a cxtion table access trace record for the replica using the
  3362. Text string.
  3363. Arguments:
  3364. Return Value:
  3365. None
  3366. --*/
  3367. {
  3368. #undef DEBSUB
  3369. #define DEBSUB "ReplicaStateTrace2:"
  3370. PWSTR ReplicaName;
  3371. if ((Replica != NULL) &&
  3372. (Replica->ReplicaName != NULL) &&
  3373. (Replica->ReplicaName->Name != NULL)) {
  3374. ReplicaName = Replica->ReplicaName->Name;
  3375. } else {
  3376. ReplicaName = L"<null>";
  3377. }
  3378. DebPrint(Severity,
  3379. (PUCHAR) REPLICA_TRACE_FORMAT2,
  3380. Debsub,
  3381. uLineNo,
  3382. PtrToUlong(Replica),
  3383. ReplicaName,
  3384. ReplicaAddrToId(Replica),
  3385. (Replica != NULL) ? RSS_NAME(Replica->ServiceState) : "<null>",
  3386. Text);
  3387. }
  3388. VOID
  3389. CxtionStateTrace(
  3390. IN ULONG Severity,
  3391. IN PCHAR Debsub,
  3392. IN ULONG uLineNo,
  3393. IN PCXTION Cxtion,
  3394. IN PREPLICA Replica,
  3395. IN ULONG Status,
  3396. IN PCHAR Text
  3397. )
  3398. /*++
  3399. Routine Description:
  3400. Print a connection state trace record using the cxtion and the
  3401. status and Text string.
  3402. Arguments:
  3403. Return Value:
  3404. None
  3405. --*/
  3406. {
  3407. #undef DEBSUB
  3408. #define DEBSUB "CxtionStateTrace:"
  3409. PWSTR ReplicaName = L"<null>";
  3410. PWSTR CxtName = L"<null>";
  3411. PCHAR CxtState = "<null>";
  3412. ULONG Ctxg = 0, Flags = 0;
  3413. PCHAR CxtDirection = "?-";
  3414. CHAR FBuf[120];
  3415. if ((Replica != NULL) &&
  3416. (Replica->ReplicaName != NULL) &&
  3417. (Replica->ReplicaName->Name != NULL)) {
  3418. ReplicaName = Replica->ReplicaName->Name;
  3419. }
  3420. if (Cxtion != NULL) {
  3421. Flags = Cxtion->Flags;
  3422. CxtState = CxtionStateNames[GetCxtionState(Cxtion)];
  3423. CxtDirection = Cxtion->Inbound ? "I-" : "O-";
  3424. if (Cxtion->Name != NULL) {
  3425. if (Cxtion->Name->Name != NULL) {
  3426. CxtName = Cxtion->Name->Name;
  3427. }
  3428. if (Cxtion->Name->Guid != NULL) {
  3429. Ctxg = Cxtion->Name->Guid->Data1;
  3430. }
  3431. }
  3432. }
  3433. DebPrint(Severity,
  3434. (PUCHAR) CXTION_TRACE_FORMAT,
  3435. Debsub,
  3436. uLineNo,
  3437. Ctxg,
  3438. CxtName,
  3439. CxtDirection,
  3440. CxtState,
  3441. ReplicaName,
  3442. ReplicaAddrToId(Replica),
  3443. (Replica != NULL) ? RSS_NAME(Replica->ServiceState) : "<null>",
  3444. Status,
  3445. Text);
  3446. FrsFlagsToStr(Flags, CxtionFlagNameTable, sizeof(FBuf), FBuf);
  3447. DebPrint(Severity, (PUCHAR) ":X: %08x, Flags [%s]\n", Debsub, uLineNo, Ctxg, FBuf);
  3448. }
  3449. VOID
  3450. CmdPktTrace(
  3451. IN ULONG Severity,
  3452. IN PCHAR Debsub,
  3453. IN ULONG uLineNo,
  3454. IN PCOMMAND_PACKET Cmd,
  3455. IN PCHAR Text
  3456. )
  3457. /*++
  3458. Routine Description:
  3459. Print a command packet trace record using the Cmd and Text string.
  3460. Arguments:
  3461. Return Value:
  3462. None
  3463. --*/
  3464. {
  3465. #undef DEBSUB
  3466. #define DEBSUB "CmdPktTrace:"
  3467. ULONG CmdCode = 0, Flags = 0, Ctrl = 0, Tout = 0, TQ = 0, Err = 0;
  3468. if (Cmd != NULL) {
  3469. CmdCode = (ULONG) Cmd->Command;
  3470. Flags = (ULONG) Cmd->Flags;
  3471. Ctrl = (ULONG) Cmd->Control;
  3472. Tout = Cmd->Timeout;
  3473. TQ = PtrToUlong(Cmd->TargetQueue);
  3474. Err = Cmd->ErrorStatus;
  3475. }
  3476. DebPrint(Severity,
  3477. (PUCHAR) ":Cd: %08x, Cmd %04x, Flg %04x, Ctrl %04x, Tout %08x, TQ %08x, Err %d [%s]\n",
  3478. Debsub,
  3479. uLineNo,
  3480. PtrToUlong(Cmd), CmdCode, Flags, Ctrl, Tout, TQ, Err, Text);
  3481. }
  3482. VOID
  3483. SendCmdTrace(
  3484. IN ULONG Severity,
  3485. IN PCHAR Debsub,
  3486. IN ULONG uLineNo,
  3487. IN PCOMMAND_PACKET Cmd,
  3488. IN ULONG WStatus,
  3489. IN PCHAR Text
  3490. )
  3491. /*++
  3492. Routine Description:
  3493. Print a send command packet trace record using the Cmd and the
  3494. status and Text string.
  3495. Arguments:
  3496. Return Value:
  3497. None
  3498. --*/
  3499. {
  3500. #undef DEBSUB
  3501. #define DEBSUB "SendCmdTrace:"
  3502. PCXTION Cxtion;
  3503. PWSTR CxtTo = L"<null>";
  3504. ULONG Ctxg = 0, PktLen = 0;
  3505. if (Cmd != NULL) {
  3506. Cxtion = SRCxtion(Cmd);
  3507. if ((Cxtion != NULL) &&
  3508. (Cxtion->Name != NULL) &&
  3509. (Cxtion->Name->Guid != NULL)) {
  3510. Ctxg = Cxtion->Name->Guid->Data1;
  3511. }
  3512. if (SRCommPkt(Cmd) != NULL) {
  3513. PktLen = SRCommPkt(Cmd)->PktLen;
  3514. }
  3515. if ((SRTo(Cmd) != NULL) && (SRTo(Cmd)->Name != NULL)) {
  3516. CxtTo = SRTo(Cmd)->Name;
  3517. }
  3518. }
  3519. DebPrint(Severity,
  3520. (PUCHAR) ":SR: Cmd %08x, CxtG %08x, WS %s, To %ws Len: (%3d) [%s]\n",
  3521. Debsub,
  3522. uLineNo,
  3523. PtrToUlong(Cmd), Ctxg, ErrLabelW32(WStatus), CxtTo, PktLen, Text);
  3524. }
  3525. VOID
  3526. ReceiveCmdTrace(
  3527. IN ULONG Severity,
  3528. IN PCHAR Debsub,
  3529. IN ULONG uLineNo,
  3530. IN PCOMMAND_PACKET Cmd,
  3531. IN PCXTION Cxtion,
  3532. IN ULONG WStatus,
  3533. IN PCHAR Text
  3534. )
  3535. /*++
  3536. Routine Description:
  3537. Print a rcv command packet trace record using the Cmd and the
  3538. status and Text string.
  3539. Arguments:
  3540. Return Value:
  3541. None
  3542. --*/
  3543. {
  3544. #undef DEBSUB
  3545. #define DEBSUB "ReceiveCmdTrace:"
  3546. PWSTR CxtFrom = L"<null>";
  3547. ULONG Ctxg = 0, PktLen = 0, CmdCode = 0;
  3548. if (Cmd != NULL) {
  3549. CmdCode = (ULONG) Cmd->Command;
  3550. if (Cxtion != NULL) {
  3551. CxtFrom = Cxtion->PartnerDnsName;
  3552. if ((Cxtion->Name != NULL) && (Cxtion->Name->Guid != NULL)) {
  3553. Ctxg = Cxtion->Name->Guid->Data1;
  3554. }
  3555. }
  3556. }
  3557. DebPrint(Severity,
  3558. (PUCHAR) ":SR: Cmd %08x, CxtG %08x, WS %s, From %ws CCod: (%03x) [%s]\n",
  3559. Debsub,
  3560. uLineNo,
  3561. PtrToUlong(Cmd), Ctxg, ErrLabelW32(WStatus), CxtFrom, CmdCode, Text);
  3562. }
  3563. VOID
  3564. StageFileTrace(
  3565. IN ULONG Severity,
  3566. IN PCHAR Debsub,
  3567. IN ULONG uLineNo,
  3568. IN GUID *CoGuid,
  3569. IN PWCHAR FileName,
  3570. IN PULONGLONG pFileSize,
  3571. IN PULONG pFlags,
  3572. IN PCHAR Text
  3573. )
  3574. /*++
  3575. Routine Description:
  3576. Print a stage file acquire/release trace record.
  3577. Arguments:
  3578. Return Value:
  3579. None
  3580. --*/
  3581. {
  3582. #undef DEBSUB
  3583. #define DEBSUB "StageFileTrace:"
  3584. ULONGLONG FileSize = QUADZERO;
  3585. ULONG Flags = 0, CoGuidData = 0;
  3586. CHAR FBuf[120];
  3587. Flags = (pFlags != NULL) ? *pFlags : 0;
  3588. CoGuidData = (CoGuid != NULL) ? CoGuid->Data1 : 0;
  3589. pFileSize = (pFileSize == NULL) ? &FileSize : pFileSize;
  3590. DebPrint(Severity,
  3591. (PUCHAR) ":: CoG %08x, Flgs %08x, %5d, Siz %08x %08x, FN: %-15ws, [%s]\n",
  3592. Debsub,
  3593. uLineNo,
  3594. CoGuidData,
  3595. Flags,
  3596. 0,
  3597. PRINTQUAD(*pFileSize),
  3598. FileName,
  3599. Text);
  3600. FrsFlagsToStr(Flags, StageFlagNameTable, sizeof(FBuf), FBuf);
  3601. DebPrint(Severity,
  3602. (PUCHAR) ":: CoG %08x, Flags [%s]\n",
  3603. Debsub,
  3604. uLineNo,
  3605. CoGuidData,
  3606. FBuf);
  3607. }
  3608. VOID
  3609. SetCxtionStateTrace(
  3610. IN ULONG Severity,
  3611. IN PCHAR Debsub,
  3612. IN ULONG uLineNo,
  3613. IN PCXTION Cxtion,
  3614. IN ULONG NewState
  3615. )
  3616. /*++
  3617. Routine Description:
  3618. Print a change to cxtion state trace record using the Cxtion and the NewState.
  3619. Arguments:
  3620. Return Value:
  3621. None
  3622. --*/
  3623. {
  3624. #undef DEBSUB
  3625. #define DEBSUB "SetCxtionStateTrace:"
  3626. PWSTR CxtName = L"<null>";
  3627. PWSTR PartnerName = L"<null>";
  3628. PWSTR PartSrvName = L"<null>";
  3629. PCHAR CxtionState = "<null>";
  3630. ULONG Ctxg = 0;
  3631. PCHAR CxtDirection = "?-";
  3632. if (Cxtion != NULL) {
  3633. CxtionState = CxtionStateNames[Cxtion->State];
  3634. if (Cxtion->Name != NULL) {
  3635. if (Cxtion->Name->Guid != NULL) {
  3636. Ctxg = Cxtion->Name->Guid->Data1;
  3637. }
  3638. if (Cxtion->Name->Name != NULL) {
  3639. CxtName = Cxtion->Name->Name;
  3640. }
  3641. }
  3642. CxtDirection = Cxtion->Inbound ? "<-" : "->";
  3643. if ((Cxtion->Partner != NULL) && (Cxtion->Partner->Name != NULL)) {
  3644. PartnerName = Cxtion->Partner->Name;
  3645. }
  3646. if (Cxtion->PartSrvName != NULL) {
  3647. PartSrvName = Cxtion->PartSrvName;
  3648. }
  3649. }
  3650. DebPrint(Severity,
  3651. (PUCHAR) ":X: %08x, state change from %s to %s for %ws %s %ws\\%ws\n",
  3652. Debsub,
  3653. uLineNo,
  3654. Ctxg,
  3655. CxtionState,
  3656. CxtionStateNames[NewState],
  3657. CxtName,
  3658. CxtDirection,
  3659. PartnerName,
  3660. PartSrvName);
  3661. }
  3662. #define FRS_TRACK_FORMAT_1 ":T: CoG: %08x CxtG: %08x [%-15s] Name: %ws\n"
  3663. #define FRS_TRACK_FORMAT_2 ":T: EventTime: %-40s Ver: %d\n"
  3664. #define FRS_TRACK_FORMAT_3 ":T: FileG: %-40s FID: %08x %08x\n"
  3665. #define FRS_TRACK_FORMAT_4 ":T: ParentG: %-40s Size: %08x %08x\n"
  3666. #define FRS_TRACK_FORMAT_5 ":T: OrigG: %-40s Attr: %08x\n"
  3667. #define FRS_TRACK_FORMAT_6 ":T: LocnCmd: %-8s State: %-24s ReplicaName: %ws (%d)\n"
  3668. #define FRS_TRACK_FORMAT_7 ":T: CoFlags: %08x [%s]\n"
  3669. #define FRS_TRACK_FORMAT_8 ":T: UsnReason: %08x [%s]\n"
  3670. VOID
  3671. FrsTrackRecord(
  3672. IN ULONG Severity,
  3673. IN PCHAR Debsub,
  3674. IN ULONG uLineNo,
  3675. IN PCHANGE_ORDER_ENTRY Coe,
  3676. IN PCHAR Text
  3677. )
  3678. /*++
  3679. Routine Description:
  3680. Print a change order file update tracking record using the change order
  3681. entry and Text string.
  3682. 7/29-13:40:58 :T: CoG: 779800ea CxtG: 000001bb [RemCo ] Name: Thous_5555_988
  3683. 7/29-13:40:58 :T: EventTime: Sat Jul 29, 2000 12:05:57 Ver: 0
  3684. 7/29-13:40:58 :T: FileG: b49362c3-216d-4ff4-a2d067fd031e436f FID 00050000 0000144e
  3685. 7/29-13:40:58 :T: ParG: 8d60157a-7dc6-4dfc-acf3eca3c6e4d5d8 Size: 00000000 00000030
  3686. 7/29-13:40:58 :T: OrigG: 8071d94a-a659-4ff7-a9467d8d6ad18aec Attr: 00000020
  3687. 7/29-13:40:58 :T: LocnCmd: Create State: IBCO_INSTALL_DEL_RETRY ReplicaName: Replica-A (1)
  3688. 7/29-13:40:58 :T: COFlags
  3689. 7/29-13:40:58 :T: UsnReason: 00000002 [DatExt ]
  3690. Arguments:
  3691. Return Value:
  3692. None
  3693. --*/
  3694. {
  3695. #undef DEBSUB
  3696. #define DEBSUB "FrsTrackRecord:"
  3697. PCHANGE_ORDER_COMMAND CoCmd;
  3698. CHAR FlagBuffer[160];
  3699. CHAR GuidStr1[GUID_CHAR_LEN];
  3700. CHAR TimeStr[TIME_STRING_LENGTH];
  3701. if (!DoDebug(Severity, Debsub) || (Coe == NULL) || (Text == NULL)) {
  3702. return;
  3703. }
  3704. //
  3705. // Get debug lock so our output stays in one piece.
  3706. //
  3707. DebLock();
  3708. CoCmd = &Coe->Cmd;
  3709. DebPrintTrackingNoLock(Severity, (PUCHAR) FRS_TRACK_FORMAT_1,
  3710. CoCmd->ChangeOrderGuid.Data1, CoCmd->CxtionGuid.Data1,
  3711. Text, CoCmd->FileName);
  3712. FileTimeToString((PFILETIME) &CoCmd->EventTime.QuadPart, TimeStr);
  3713. DebPrintTrackingNoLock(Severity, (PUCHAR) FRS_TRACK_FORMAT_2,
  3714. TimeStr, CoCmd->FileVersionNumber);
  3715. GuidToStr(&CoCmd->FileGuid, GuidStr1);
  3716. DebPrintTrackingNoLock(Severity, (PUCHAR) FRS_TRACK_FORMAT_3,
  3717. GuidStr1, PRINTQUAD(Coe->FileReferenceNumber));
  3718. GuidToStr(&CoCmd->NewParentGuid, GuidStr1);
  3719. DebPrintTrackingNoLock(Severity, (PUCHAR) FRS_TRACK_FORMAT_4,
  3720. GuidStr1, PRINTQUAD(CoCmd->FileSize));
  3721. GuidToStr(&CoCmd->OriginatorGuid, GuidStr1);
  3722. DebPrintTrackingNoLock(Severity, (PUCHAR) FRS_TRACK_FORMAT_5,
  3723. GuidStr1, CoCmd->FileAttributes);
  3724. DebPrintTrackingNoLock(Severity, (PUCHAR) FRS_TRACK_FORMAT_6,
  3725. CoLocationNames[GET_CO_LOCATION_CMD(Coe->Cmd, Command)],
  3726. PRINT_CO_STATE(Coe), Coe->NewReplica->ReplicaName->Name,
  3727. CoCmd->NewReplicaNum);
  3728. FrsFlagsToStr(CoCmd->Flags, CoFlagNameTable, sizeof(FlagBuffer), FlagBuffer);
  3729. DebPrintTrackingNoLock(Severity, (PUCHAR) FRS_TRACK_FORMAT_7,
  3730. CoCmd->Flags, FlagBuffer);
  3731. FrsFlagsToStr(CoCmd->ContentCmd, UsnReasonNameTable, sizeof(FlagBuffer), FlagBuffer);
  3732. DebPrintTrackingNoLock(Severity, (PUCHAR) FRS_TRACK_FORMAT_8,
  3733. CoCmd->ContentCmd, FlagBuffer);
  3734. #if 0
  3735. FrsFlagsToStr(CoEntry->EntryFlags, CoeFlagNameTable, sizeof(FlagBuffer), FlagBuffer);
  3736. FRS_DEB_PRINT2("EntryFlags: %08x, Flags [%s]\n", CoEntry->EntryFlags, FlagBuffer);
  3737. FrsFlagsToStr(CoEntry->IssueCleanup, IscuFlagNameTable, sizeof(FlagBuffer), FlagBuffer);
  3738. FRS_DEB_PRINT2("ISCU Flags: %08x, Flags [%s]\n", CoEntry->IssueCleanup, FlagBuffer);
  3739. FrsFlagsToStr(CoCmd->IFlags, CoIFlagNameTable, sizeof(FlagBuffer), FlagBuffer);
  3740. DebPrintNoLock(Severity, TRUE,
  3741. "IFlags: %08x, Flags [%s] TimeToRun: %7d, EntryCreateTime: %7d\n",
  3742. Debsub, uLineNo,
  3743. CoCmd->IFlags, FlagBuffer,
  3744. CoEntry->TimeToRun,
  3745. CoEntry->EntryCreateTime);
  3746. if (CoCmd->Extension != NULL) {
  3747. pULong = (PULONG) CoCmd->Extension;
  3748. DebPrintNoLock(Severity, TRUE,
  3749. "CO Extension: (%08x) %08x %08x %08x %08x %08x %08x %08x %08x\n",
  3750. Debsub, uLineNo, pULong,
  3751. *(pULong+0), *(pULong+1), *(pULong+2), *(pULong+3),
  3752. *(pULong+4), *(pULong+5), *(pULong+6), *(pULong+7));
  3753. } else {
  3754. FRS_DEB_PRINT("CO Extension: Null\n", NULL);
  3755. }
  3756. FRS_DEB_PRINT("FrsVsn: %08x %08x\n", PRINTQUAD(CoCmd->FrsVsn));
  3757. FRS_DEB_PRINT3("Usn: %08x %08x CoFileUsn: %08x %08x JrnlFirstUsn: %08x %08x\n",
  3758. PRINTQUAD(CoCmd->JrnlUsn),
  3759. PRINTQUAD(CoCmd->FileUsn),
  3760. PRINTQUAD(CoCmd->JrnlFirstUsn));
  3761. #endif
  3762. DebUnLock();
  3763. }
  3764. VOID
  3765. FrsPrintLongUStr(
  3766. IN ULONG Severity,
  3767. IN PCHAR Debsub,
  3768. IN ULONG uLineNo,
  3769. IN PWCHAR UStr
  3770. )
  3771. /*++
  3772. Routine Description:
  3773. Print a long unicode string on multiple lines.
  3774. Arguments:
  3775. Return Value:
  3776. None
  3777. --*/
  3778. {
  3779. #undef DEBSUB
  3780. #define DEBSUB "FrsPrintLongUStr:"
  3781. ULONG i, j, Len;
  3782. WCHAR Usave;
  3783. if (!DoDebug(Severity, Debsub) || (UStr == NULL)) {
  3784. return;
  3785. }
  3786. //
  3787. // Get debug lock so our output stays in one piece.
  3788. //
  3789. DebLock();
  3790. Len = wcslen(UStr);
  3791. i = 0;
  3792. j = 0;
  3793. while (i < Len) {
  3794. i += 60;
  3795. if (i > Len) {
  3796. i = Len;
  3797. }
  3798. Usave = UStr[i];
  3799. UStr[i] = UNICODE_NULL;
  3800. FRS_DEB_PRINT("++ %ws\n", &UStr[j]);
  3801. UStr[i] = Usave;
  3802. j = i;
  3803. }
  3804. DebUnLock();
  3805. }