Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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