/*++ Copyright (c) 1997-1999 Microsoft Corporation Module Name: frsalloc.c Abstract: Routines for allocating and freeing memory structures in the NT File Replication Service. Author: David Orbits (davidor) - 3-Mar-1997 Revision History: --*/ #include #pragma hdrstop #undef DEBSUB #define DEBSUB "FRSALLOC:" #include #include #include #include #pragma warning( disable:4102) // unreferenced label // // Check for allocation problems // #define DBG_NUM_MEM_STACK (8) #define MAX_MEM_ON_FREE_LIST (1024) #define MAX_MEM_INDEX (1024) #define FRS_DEB_PRINT(_f, _d) \ DebPrintNoLock(Severity, TRUE, _f, Debsub, uLineNo, _d) #define FRS_DEB_PRINT2(_f, _d1, _d2) \ DebPrintNoLock(Severity, TRUE, _f, Debsub, uLineNo, _d1, _d2) #define FRS_DEB_PRINT3(_f, _d1, _d2, _d3) \ DebPrintNoLock(Severity, TRUE, _f, Debsub, uLineNo, _d1, _d2, _d3) CRITICAL_SECTION MemLock; typedef struct _MEM MEM, *PMEM; struct _MEM { PMEM Next; ULONG_PTR *Begin; ULONG_PTR *End; DWORD OrigSize; ULONG_PTR Stack[DBG_NUM_MEM_STACK]; }; PMEM MemList; PMEM FreeMemList; DWORD MemOnFreeList; DWORD TotalAlloced; DWORD TotalAllocCalls; DWORD TotalFreed; DWORD TotalFreeCalls; DWORD TotalDelta; DWORD TotalDeltaMax; DWORD TotalTrigger = 10000; ULONG TypesAllocatedCount[NODE_TYPE_MAX]; ULONG TypesAllocatedMax[NODE_TYPE_MAX]; ULONG TypesAllocated[NODE_TYPE_MAX]; ULONG SizesAllocatedCount[MAX_MEM_INDEX]; ULONG SizesAllocatedMax[MAX_MEM_INDEX]; ULONG SizesAllocated[MAX_MEM_INDEX]; ULONG DbgBreakSize = 2; LONG DbgBreakTrigger = 1; LONG DbgBreakReset = 1; LONG DbgBreakResetInc = 0; PULONG_PTR MaxAllocAddr; PULONG_PTR MinAllocAddr; DWORD ReAllocs; DWORD NewAllocs; // // Keep these in the same order as the Node Type ENUM. // PCHAR NodeTypeNames[]= { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "THREAD_CONTEXT_TYPE", "REPLICA_TYPE", "REPLICA_THREAD_TYPE", "CONFIG_NODE_TYPE", "CXTION_TYPE", "GUID/RPC HANDLE", "THREAD_TYPE", "GEN_TABLE_TYPE", "JBUFFER_TYPE", "VOLUME_MONITOR_ENTRY_TYPE", "COMMAND_PACKET_TYPE", "GENERIC_HASH_TABLE_TYPE", "CHANGE_ORDER_ENTRY_TYPE", "FILTER_TABLE_ENTRY_TYPE", "QHASH_TABLE_TYPE", "OUT_LOG_PARTNER_TYPE", "WILDCARD_FILTER_ENTRY_TYPE", "NODE_TYPE_MAX" }; extern PCHAR CoLocationNames[]; extern FLAG_NAME_TABLE StageFlagNameTable[]; extern FLAG_NAME_TABLE OlpFlagNameTable[]; extern PCHAR OLPartnerStateNames[]; extern PWCHAR DsConfigTypeName[]; extern PGEN_TABLE VolSerialNumberToDriveTable; VOID FrsDisplayUsnReason( ULONG ReasonMask, PCHAR Buffer, LONG MaxLength ); PFRS_THREAD ThSupEnumThreads( PFRS_THREAD FrsThread ); VOID DbgPrintThreadIds( IN ULONG Severity ); VOID DbsDataInitCocExtension( IN PCHANGE_ORDER_RECORD_EXTENSION CocExt ); VOID SndCsDestroyCxtion( IN PCXTION Cxtion, IN DWORD CxtionFlags ); VOID FrsInitializeMemAlloc( VOID ) /*++ Routine Description: Initialize the memory allocation subsystem Arguments: None. Return Value: None. --*/ { #undef DEBSUB #define DEBSUB "FrsInitializeMemAlloc:" InitializeCriticalSection(&MemLock); // // Get Debugmem and DebugMemCompact from ntfrs config section in the registry // CfgRegReadDWord(FKC_DEBUG_MEM, NULL, 0, &DebugInfo.Mem); CfgRegReadDWord(FKC_DEBUG_MEM_COMPACT, NULL, 0, &DebugInfo.MemCompact); } VOID FrsPrintAllocStats( IN ULONG Severity, IN PNTFRSAPI_INFO Info, OPTIONAL IN DWORD Tabs ) /*++ Routine Description: Print the memory stats into the info buffer or using DPRINT (Info == NULL). Arguments: Severity - for DPRINT Info - for IPRINT (use DPRINT if NULL) Tabs - indentation for prettyprint Return Value: None. --*/ { #undef DEBSUB #define DEBSUB "FrsPrintAllocStats:" ULONG i; WCHAR TabW[MAX_TAB_WCHARS + 1]; InfoTabs(Tabs, TabW); IDPRINT0(Severity, Info, "\n"); IDPRINT1(Severity, Info, "%wsNTFRS MEMORY USAGE:\n", TabW); IDPRINT2(Severity, Info, "%ws ENABLE STATS : %s\n", TabW, (DebugInfo.Mem) ? "TRUE" : "FALSE"); IDPRINT3(Severity, Info, "%ws Alloced : %6d KB (%d calls)\n", TabW, TotalAlloced / 1024, TotalAllocCalls); IDPRINT3(Severity, Info, "%ws Freed : %6d KB (%d calls)\n", TabW, TotalFreed / 1024, TotalFreeCalls); IDPRINT2(Severity, Info, "%ws Delta : %6d KB\n", TabW, TotalDelta / 1024); IDPRINT2(Severity, Info, "%ws Max delta : %6d KB\n", TabW, TotalDeltaMax / 1024); IDPRINT2(Severity, Info, "%ws Addr Range : %6d KB\n", TabW, (((PCHAR)MaxAllocAddr) - ((PCHAR)MinAllocAddr)) / 1024); IDPRINT2(Severity, Info, "%ws OnFreeList : %d\n", TabW, MemOnFreeList); IDPRINT2(Severity, Info, "%ws ReAllocs : %d\n", TabW, ReAllocs); IDPRINT2(Severity, Info, "%ws NewAllocs : %d\n", TabW, NewAllocs); IDPRINT2(Severity, Info, "%ws MinAddr : 0x%08x\n", TabW, MinAllocAddr); IDPRINT2(Severity, Info, "%ws MaxAddr : 0x%08x\n", TabW, MaxAllocAddr); for (i = 0; i < NODE_TYPE_MAX; ++i) { if (!TypesAllocatedCount[i]) { continue; } IDPRINT5(Severity, Info, "%ws %-26s: %6d Calls, %6d Max, %6d busy\n", TabW, NodeTypeNames[i], TypesAllocatedCount[i], TypesAllocatedMax[i], TypesAllocated[i]); } IDPRINT0(Severity, Info, "\n"); for (i = 0; i < MAX_MEM_INDEX; ++i) { if (!SizesAllocatedCount[i]) { continue; } IDPRINT6(Severity, Info, "%ws %6d to %6d : %6d Calls, %6d Max, %6d busy\n", TabW, i << 4, ((i + 1) << 4) - 1, SizesAllocatedCount[i], SizesAllocatedMax[i], SizesAllocated[i]); } IDPRINT0(Severity, Info, "\n"); } VOID FrsPrintThreadStats( IN ULONG Severity, IN PNTFRSAPI_INFO Info, OPTIONAL IN DWORD Tabs ) /*++ Routine Description: Print the thread stats into the info buffer or using DPRINT (Info == NULL). Arguments: Severity - for DPRINT Info - for IPRINT (use DPRINT if NULL) Tabs - indentation for prettyprint Return Value: None. --*/ { #undef DEBSUB #define DEBSUB "FrsPrintThreadStats:" ULONGLONG CreateTime; ULONGLONG ExitTime; ULONGLONG KernelTime; ULONGLONG UserTime; PFRS_THREAD FrsThread; WCHAR TabW[MAX_TAB_WCHARS + 1]; InfoTabs(Tabs, TabW); IDPRINT0(Severity, Info, "\n"); IDPRINT1(Severity, Info, "%wsNTFRS THREAD USAGE:\n", TabW); // // Thread CPU Times // FrsThread = NULL; while (FrsThread = ThSupEnumThreads(FrsThread)) { if (HANDLE_IS_VALID(FrsThread->Handle)) { if (GetThreadTimes(FrsThread->Handle, (PFILETIME)&CreateTime, (PFILETIME)&ExitTime, (PFILETIME)&KernelTime, (PFILETIME)&UserTime)) { // // Hasn't exited, yet // if (ExitTime < CreateTime) { ExitTime = CreateTime; } IDPRINT5(Severity, Info, "%ws %-15ws: %8d CPU Seconds (%d kernel, %d elapsed)\n", TabW, FrsThread->Name, (DWORD)((KernelTime + UserTime) / (10 * 1000 * 1000)), (DWORD)((KernelTime) / (10 * 1000 * 1000)), (DWORD)((ExitTime - CreateTime) / (10 * 1000 * 1000))); } } } // // Process CPU Times // if (GetProcessTimes(ProcessHandle, (PFILETIME)&CreateTime, (PFILETIME)&ExitTime, (PFILETIME)&KernelTime, (PFILETIME)&UserTime)) { // // Hasn't exited, yet // if (ExitTime < CreateTime) { ExitTime = CreateTime; } IDPRINT5(Severity, Info, "%ws %-15ws: %8d CPU Seconds (%d kernel, %d elapsed)\n", TabW, L"PROCESS", (DWORD)((KernelTime + UserTime) / (10 * 1000 * 1000)), (DWORD)((KernelTime) / (10 * 1000 * 1000)), (DWORD)((ExitTime - CreateTime) / (10 * 1000 * 1000))); } IDPRINT0(Severity, Info, "\n"); } VOID FrsPrintStageStats( IN ULONG Severity, IN PNTFRSAPI_INFO Info, OPTIONAL IN DWORD Tabs ) /*++ Routine Description: Print the staging area stats into the info buffer or using DPRINT (Info == NULL). Arguments: Severity - for DPRINT Info - for IPRINT (use DPRINT if NULL) Tabs - indentation for prettyprint Return Value: None. --*/ { #undef DEBSUB #define DEBSUB "FrsPrintStageStats:" PVOID Key; PSTAGE_ENTRY SEntry; DWORD SizeInKb; WCHAR TabW[MAX_TAB_WCHARS + 1]; CHAR Guid[GUID_CHAR_LEN + 1]; extern DWORD StagingAreaAllocated; extern PGEN_TABLE StagingAreaTable; InfoTabs(Tabs, TabW); try { GTabLockTable(StagingAreaTable); IDPRINT0(Severity, Info, "\n"); IDPRINT3(Severity, Info, "%wsNTFRS STAGE USAGE: %d KB of %d KB allocated\n", TabW, StagingAreaAllocated, StagingLimitInKb); SizeInKb = 0; Key = NULL; while (SEntry = GTabNextDatumNoLock(StagingAreaTable, &Key)) { GuidToStr(&SEntry->FileOrCoGuid, Guid); IDPRINT2(Severity, Info, "%ws %s\n", TabW, Guid); IDPRINT2(Severity, Info, "%ws Flags: %08x\n", TabW, SEntry->Flags); IDPRINT2(Severity, Info, "%ws Size : %d\n", TabW, SEntry->FileSizeInKb); SizeInKb += SEntry->FileSizeInKb; } IDPRINT2(Severity, Info, "%ws Calculated Usage is %d KB\n", TabW, SizeInKb); IDPRINT0(Severity, Info, "\n"); } finally { GTabUnLockTable(StagingAreaTable); } } VOID MyDbgBreak( VOID ) { } VOID DbgCheck( IN PMEM Mem ) /*++ Routine Description: Check a memory block. Memory lock must be held. Arguments: Mem - memory block Return Value: None. --*/ { #undef DEBSUB #define DEBSUB "DbgCheck:" PULONG_PTR pDWord; ULONG_PTR Pattern; // // Begins at first byte at the end of the user's allocation // Pattern = (ULONG_PTR)(Mem->End) | (Mem->OrigSize << 24); // // Check for overwritten memory // if ( (ULONG_PTR)*Mem->Begin != (ULONG_PTR)Mem->Begin ) { DPRINT2(0, "Begin Memory @ 0x%08x has been overwritten with 0x%08x\n", Mem->Begin, *Mem->Begin); } else if (memcmp(((PCHAR)Mem->Begin) + Mem->OrigSize + 8, (PCHAR)&Pattern, sizeof(Pattern))) { DPRINT1(0, "End Memory @ 0x%08x has been overwritten\n", ((PCHAR)Mem->Begin) + Mem->OrigSize + 8); } else { return; } DPRINT(0, "Memory's stack trace\n"); STACK_PRINT(0, Mem->Stack, DBG_NUM_MEM_STACK); DPRINT(0, "Caller's stack trace\n"); STACK_TRACE_AND_PRINT(0); DPRINT(0, "Corrupted block of memory\n"); for (pDWord = Mem->Begin; pDWord != Mem->End; ++pDWord) { DPRINT2(0, "0x%08x: 0x%08x\n", pDWord, *pDWord); } exit(1); } VOID DbgCheckAll( VOID ) /*++ Routine Description: Check all memory blocks. Arguments: Mem - memory block Return Value: None. --*/ { #undef DEBSUB #define DEBSUB "DbgCheckAll:" PMEM Mem; // // Don't check the entire list of allocated memory blocks // if (DebugInfo.Mem < 2) { return; } EnterCriticalSection(&MemLock); for (Mem = MemList; Mem; Mem = Mem->Next) { // // Check for overwritten memory // DbgCheck(Mem); } LeaveCriticalSection(&MemLock); } VOID FrsUnInitializeMemAlloc( VOID ) /*++ Routine Description: Initialize the memory allocation subsystem Arguments: None. Return Value: None. --*/ { #undef DEBSUB #define DEBSUB "FrsUnInitializeMemAlloc:" PMEM Mem; EnterCriticalSection(&MemLock); for (Mem = MemList; Mem; Mem = Mem->Next) { // // Check for overwritten memory // DbgCheck(Mem); DPRINT2(1, "\t%d bytes @ 0x%08x\n", ((PCHAR)Mem->End) - ((PCHAR)Mem->Begin), Mem->Begin); STACK_PRINT(1, Mem->Stack, DBG_NUM_MEM_STACK); } LeaveCriticalSection(&MemLock); } PMEM DbgAlloc( IN ULONG_PTR *Begin, IN ULONG_PTR *End, IN DWORD OrigSize ) /*++ Routine Description: Add a new allocation to our list of allocated memory after checking for overlaps. Arguments: Begin - beginning of newly allocated memory End - end of same OrigSize - Size requested by caller Return Value: None. --*/ { #undef DEBSUB #define DEBSUB "DbgAlloc:" PMEM *PMem; PMEM Mem; ULONG Calls; ULONG_PTR Pattern; DWORD MemIndex; // // Approximate stats // if (!DebugInfo.Mem) { // // Memory stats // Calls = ++TotalAllocCalls; TotalAlloced += (DWORD)((PUCHAR)End - (PUCHAR)Begin); if (Begin > MaxAllocAddr) { ++NewAllocs; MaxAllocAddr = Begin; } else { if (!MinAllocAddr) { MinAllocAddr = Begin; } ++ReAllocs; } // // Tracking memory sizes // MemIndex = OrigSize >> 4; if (MemIndex >= MAX_MEM_INDEX) { MemIndex = (MAX_MEM_INDEX - 1); } SizesAllocatedCount[MemIndex]++; // // Print memory stats every so often // if (!(Calls % TotalTrigger)) { DbgPrintThreadIds(DebugInfo.LogSeverity); FrsPrintAllocStats(DebugInfo.LogSeverity, NULL, 0); } return NULL; } // // Verify heap consistency // DbgCheckAll(); EnterCriticalSection(&MemLock); PMem = &MemList; for (Mem = *PMem; Mem; Mem = *PMem) { // // Check for overwritten memory // DbgCheck(Mem); // // Check for overlap // if ((Begin >= Mem->Begin && Begin < Mem->End) || (Mem->Begin >= Begin && Mem->Begin < End) || (Mem->End > Begin && Mem->End < End) || (End > Mem->Begin && End < Mem->End)) { // // DUP ALLOCATION (OVERLAP DETECTED) // Release lock in case DPRINT calls allocation routines // LeaveCriticalSection(&MemLock); DPRINT4(0, "ERROR -- DUP ALLOC: 0x%x to 0x%x is already allocated to 0x%x to 0x%x; EXITING\n", Begin, End, Mem->Begin, Mem->End); FRS_ASSERT(!"Duplicate memory allocation"); } // // This memory should be linked later in the sorted memory list // if (Begin > Mem->Begin) { PMem = &Mem->Next; continue; } // // This memory should be linked here in the sorted memory list // break; } // // Allocate a memory block header // Mem = FreeMemList; if (Mem) { --MemOnFreeList; FreeMemList = Mem->Next; } else { Mem = (PVOID)malloc(sizeof(MEM)); if (Mem == NULL) { RaiseException(ERROR_OUTOFMEMORY, 0, 0, NULL); } ZeroMemory(Mem, sizeof(MEM)); } // // Initialize the header and the header/trailer for memory overrun detection. // Mem->OrigSize = OrigSize; Mem->End = End; Mem->Begin = Begin; // // Initialize the header/trailer for memory overrun detection. // *Mem->Begin = (ULONG_PTR)Begin; *(Mem->Begin + 1) = OrigSize; Pattern = (ULONG_PTR)(Mem->End) | (Mem->OrigSize << 24); CopyMemory(((PCHAR)Begin) + Mem->OrigSize + 8, (PCHAR)&Pattern, sizeof(Pattern)); // // Add to sorted list // Mem->Next = *PMem; *PMem = Mem; // // Note: stackwalk won't work from here; see frsalloctype() // // DbgStackTrace(Mem->Stack, DBG_NUM_MEM_STACK) // // Memory stats // Calls = ++TotalAllocCalls; TotalAlloced += (DWORD)((PUCHAR)End - (PUCHAR)Begin); TotalDelta = TotalAlloced - TotalFreed; if (TotalDelta > TotalDeltaMax) { TotalDeltaMax = TotalDelta; } if (Begin > MaxAllocAddr) { ++NewAllocs; MaxAllocAddr = Begin; } else { if (!MinAllocAddr) { MinAllocAddr = Begin; } ++ReAllocs; } // // Tracking memory sizes // MemIndex = OrigSize >> 4; if (MemIndex >= MAX_MEM_INDEX) { MemIndex = (MAX_MEM_INDEX - 1); } SizesAllocated[MemIndex]++; SizesAllocatedCount[MemIndex]++; if (SizesAllocated[MemIndex] > SizesAllocatedMax[MemIndex]) { SizesAllocatedMax[MemIndex] = SizesAllocated[MemIndex]; } // // Done // LeaveCriticalSection(&MemLock); // // Print memory stats every so often // if (!(Calls % TotalTrigger)) { DbgPrintThreadIds(DebugInfo.LogSeverity); FrsPrintAllocStats(DebugInfo.LogSeverity, NULL, 0); } DbgCheckAll(); return Mem; } VOID DbgFree( IN PULONG_PTR Begin ) /*++ Routine Description: Remove allocated memory from list Arguments: Begin - allocated (maybe) memory Return Value: TRUE - found it FALSE - didn't find it --*/ { #undef DEBSUB #define DEBSUB "DbgFree:" PMEM *PMem; PMEM Mem; DWORD MemIndex; // // Freeing NULL pointer is allowed // if (Begin == NULL || !DebugInfo.Mem) { return; } DbgCheckAll(); EnterCriticalSection(&MemLock); PMem = &MemList; for (Mem = *PMem; Mem; Mem = *PMem) { // // Check for overwritten memory // DbgCheck(Mem); // // Not the right one // if (Begin > Mem->Begin) { PMem = &Mem->Next; continue; } if (Begin != Mem->Begin) { break; } // // Found it; remove from list and free it // ++TotalFreeCalls; TotalFreed += (DWORD)((PUCHAR)Mem->End - (PUCHAR)Mem->Begin); TotalDelta = TotalAlloced - TotalFreed; MemIndex = Mem->OrigSize >> 4; if (MemIndex >= MAX_MEM_INDEX) { MemIndex = (MAX_MEM_INDEX - 1); } SizesAllocated[MemIndex]--; *PMem = Mem->Next; if (MemOnFreeList > MAX_MEM_ON_FREE_LIST) { free(Mem); } else { ++MemOnFreeList; Mem->Next = FreeMemList; FreeMemList = Mem; } LeaveCriticalSection(&MemLock); DbgCheckAll(); return; } LeaveCriticalSection(&MemLock); DPRINT1(0, "ERROR -- Memory @ 0x%x is not allocated\n", Begin); FRS_ASSERT(!"Memory free error, not allocated"); } BOOL DbgIsAlloc( IN PULONG_PTR Begin ) /*++ Routine Description: Is Begin alloced? Arguments: Begin - allocated (maybe) memory Return Value: TRUE - found it FALSE - didn't find it --*/ { #undef DEBSUB #define DEBSUB "DbgIsAlloc:" PMEM *PMem; PMEM Mem; if (!DebugInfo.Mem) { return TRUE; } // // NULL pointer is always alloced // if (Begin == NULL) { return TRUE; } DbgCheckAll(); EnterCriticalSection(&MemLock); PMem = &MemList; for (Mem = *PMem; Mem; Mem = *PMem) { // // Check for overwritten memory // DbgCheck(Mem); // // Not the right one // if (Begin > Mem->Begin) { PMem = &Mem->Next; continue; } if (Begin != Mem->Begin) { break; } LeaveCriticalSection(&MemLock); DbgCheckAll(); return TRUE; } LeaveCriticalSection(&MemLock); DbgCheckAll(); return FALSE; } PVOID FrsAlloc( IN DWORD OrigSize ) /*++ Routine Description: Allocate memory. Raise an exception if there is no memory. Arguments: Size - size of the memory request Return Value: Allocated memory. --*/ { #undef DEBSUB #define DEBSUB "FrsAlloc:" PVOID Node; DWORD Size; PMEM Mem; // // FRS_ASSERT is added here to satisfy prefix. The return value from FrsAlloc is not checked anywhere // in the code. // FRS_ASSERT(OrigSize != 0); Size = OrigSize; if (DebugInfo.Mem) { // // Check for debug break // if (OrigSize == DbgBreakSize) { if (DbgBreakTrigger) { if (--DbgBreakTrigger <= 0) { DbgBreakTrigger = DbgBreakReset; DbgBreakReset += DbgBreakResetInc; MyDbgBreak(); } } } // // Adjust size for header/trailer // Size = (((OrigSize + 7) >> 3) << 3) + 16; } // // Raise an exception if there is no memory // Node = (PVOID)malloc(Size); if (Node == NULL) { RaiseException(ERROR_OUTOFMEMORY, 0, 0, NULL); } ZeroMemory(Node, Size); // // Even with mem alloc tracing off call DbgAlloc to capture mem alloc stats. // Mem = DbgAlloc(Node, (PULONG_PTR)(((PCHAR)Node) + Size), OrigSize); // // Note: should be in dbgalloc(); but stackwalk won't work // if (DebugInfo.Mem) { DbgStackTrace(Mem->Stack, DBG_NUM_MEM_STACK); ((PCHAR)Node) += 8; } return Node; } PVOID FrsRealloc( PVOID OldNode, DWORD OrigSize ) /*++ Routine Description: Reallocate memory. Raise an exception if there is no memory. Arguments: Size - size of the memory request Return Value: Reallocated memory. --*/ { #undef DEBSUB #define DEBSUB "FrsRealloc:" PVOID Node; DWORD Size; PMEM Mem; if (!OldNode) { // // Need to check if OrigSize == 0 as FrsAlloc asserts if called with 0 as the first parameter (prefix fix). // if (OrigSize == 0) { return NULL; } return FrsAlloc(OrigSize); } Size = OrigSize; if (DebugInfo.Mem) { ((PCHAR)OldNode) -= 8; DbgFree(OldNode); // // Adjust size for header/trailer // Size = (((OrigSize + 7) >> 3) << 3) + 16; } // // Raise an exception if there is no memory // Node = (PVOID)realloc(OldNode, Size); if (Node == NULL) { RaiseException(ERROR_OUTOFMEMORY, 0, 0, NULL); } // // Even with mem alloc tracing off call DbgAlloc to capture mem alloc stats. // Mem = DbgAlloc(Node, (PULONG_PTR)(((PCHAR)Node) + Size), OrigSize); // // Note: should be in dbgalloc(); but stackwalk won't work // if (DebugInfo.Mem) { DbgStackTrace(Mem->Stack, DBG_NUM_MEM_STACK); ((PCHAR)Node) += 8; } return Node; } PVOID FrsFree( PVOID Node ) /*++ Routine Description: Free memory allocated with FrsAlloc Arguments: Node - memory allocated with FrsAlloc Return Value: None. --*/ { #undef DEBSUB #define DEBSUB "FrsFree:" if (!Node) { return NULL; } if (DebugInfo.Mem) { ((PCHAR)Node) -= 8; DbgFree(Node); } free(Node); if (DebugInfo.MemCompact) { HeapCompact(GetProcessHeap(), 0); } return NULL; } PCHAR FrsWtoA( PWCHAR Wstr ) /*++ Routine Description: Translate a wide char string into a newly allocated char string. Arguments: Wstr - wide char string Return Value: Duplicated string. Free with FrsFree(). --*/ { #undef DEBSUB #define DEBSUB "FrsWtoA:" PCHAR Astr; // // E.g., when duplicating NodePartner when none exists // if (Wstr == NULL) return NULL; Astr = FrsAlloc(wcslen(Wstr) + 1); sprintf(Astr, "%ws", Wstr); return Astr; } PWCHAR FrsWcsTrim( PWCHAR Wstr, WCHAR Trim ) /*++ Routine Description: Remove the Trim char from the trailing end of the string by replacing any occurance with a L'\0'. Skip over any leading Trim chars and return a ptr to the first non-TRIM char found. If we hit the end of the string return the pointer to the terminating null. Arguments: Wstr - wide char string Trim - Char to trim. Return Value: ptr to first non Trim char. --*/ { #undef DEBSUB #define DEBSUB "FrsWcsTrim:" LONG Len, Index; if (Wstr == NULL) return NULL; // // Len = wcslen(Wstr); Index = Len - 1; while (Index >= 0) { if (Wstr[Index] != Trim) { break; } Index--; } Wstr[++Index] = UNICODE_NULL; Len = Index; Index = 0; while (Index < Len) { if (Wstr[Index] != Trim) { break; } Index++; } return Wstr + Index; } PWCHAR FrsAtoW( PCHAR Astr ) /*++ Routine Description: Translate a wide char string into a newly allocated char string. Arguments: Wstr - wide char string Return Value: Duplicated string. Free with FrsFree(). --*/ { PWCHAR Wstr; // // E.g., when duplicating NodePartner when none exists // if (Astr == NULL) { return NULL; } Wstr = FrsAlloc((strlen(Astr) + 1) * sizeof(WCHAR)); swprintf(Wstr, L"%hs", Astr); return Wstr; } PWCHAR FrsWcsDup( PWCHAR OldStr ) /*++ Routine Description: Duplicate a string using our memory allocater Arguments: OldArg - string to duplicate Return Value: Duplicated string. Free with FrsFree(). --*/ { #undef DEBSUB #define DEBSUB "FrsWcsDup:" PWCHAR NewStr; // // E.g., when duplicating NodePartner when none exists // if (OldStr == NULL) { return NULL; } NewStr = FrsAlloc((wcslen(OldStr) + 1) * sizeof(WCHAR)); wcscpy(NewStr, OldStr); return NewStr; } VOID FrsBuildVolSerialNumberToDriveTable( VOID ) /*++ Routine Description: New way to get the current configuration from the DS and merge it with the active replicas. Arguments: None. Return Value: None. --*/ { #undef DEBSUB #define DEBSUB "FrsBuildVolSerialNumberToDriveTable:" ULONG MaxFileNameLen; DWORD FileSystemFlags; PWCHAR DrivePtr = NULL; DWORD WStatus; PVOLUME_INFO_NODE VolumeInfoNode; UINT DriveType; ULONG VolumeSerialNumber = 0; WCHAR LogicalDrives[MAX_PATH]; WCHAR VolumeGuidName[MAX_PATH]; // // Initialize the VolSerialNumberToDriveTable. // if (VolSerialNumberToDriveTable == NULL) { VolSerialNumberToDriveTable = GTabAllocNumberTable(); } // // Get the logical drive strings. // if (!GetLogicalDriveStrings(MAX_PATH, LogicalDrives) || (VolSerialNumberToDriveTable == NULL)) { DPRINT_WS(1, "WARN - Getting logical drives. It may not be possible to start on this server.", GetLastError()); return; } // // Lock the table during rebuild to synchronize with the many callers of // FrsWcsVolume() in other threads. // GTabLockTable(VolSerialNumberToDriveTable); GTabEmptyTableNoLock(VolSerialNumberToDriveTable, FrsFree); DrivePtr = LogicalDrives; while (wcscmp(DrivePtr,L"")) { DriveType = GetDriveType(DrivePtr); // // Skip remote drives and CDROM drives. // if ((DriveType == DRIVE_REMOTE) || (DriveType == DRIVE_CDROM)) { DPRINT1(4, "Skipping Drive %ws. Invalid drive type.\n", DrivePtr); DrivePtr = DrivePtr + wcslen(DrivePtr) + 1; continue; } if (!GetVolumeInformation(DrivePtr, VolumeGuidName, MAX_PATH, &VolumeSerialNumber, &MaxFileNameLen, &FileSystemFlags, NULL, 0)){ DPRINT1_WS(1,"WARN - GetvolumeInformation for %ws;", DrivePtr, GetLastError()); DrivePtr = DrivePtr + wcslen(DrivePtr) + 1; continue; } VolumeInfoNode = FrsAlloc(sizeof(VOLUME_INFO_NODE)); wcscpy(VolumeInfoNode->DriveName, L"\\\\.\\"); wcscat(VolumeInfoNode->DriveName, DrivePtr); // // Remove the trailing back slash. // VolumeInfoNode->DriveName[wcslen(VolumeInfoNode->DriveName) - 1] = L'\0'; VolumeInfoNode->VolumeSerialNumber = VolumeSerialNumber; GTabInsertEntryNoLock(VolSerialNumberToDriveTable, VolumeInfoNode, &(VolumeInfoNode->VolumeSerialNumber), NULL); DrivePtr = DrivePtr + wcslen(DrivePtr) + 1; } GTabUnLockTable(VolSerialNumberToDriveTable); return; } PWCHAR FrsWcsVolume( PWCHAR Path ) /*++ Routine Description: Get the drive from the VolSerialNumberToDriveTable. The volume serial number is used to locate the drive since a mount point can take us to another drive. Arguments: Path Return Value: Duplicated string containing drive:\ from Path or NULL. --*/ { #undef DEBSUB #define DEBSUB "FrsWcsVolume:" PWCHAR Volume = NULL; HANDLE DirHandle; DWORD WStatus; NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock; DWORD VolumeInfoLength; PFILE_FS_VOLUME_INFORMATION VolumeInfo; PVOLUME_INFO_NODE VolumeInfoNode; // // Get the volume Guid for the path. // // Always open the path by masking off the FILE_OPEN_REPARSE_POINT flag // because we want to open the destination dir not the junction if the root // happens to be a mount point. // WStatus = FrsOpenSourceFileW(&DirHandle, Path, GENERIC_READ, FILE_OPEN_FOR_BACKUP_INTENT); CLEANUP1_WS(4,"ERROR - Could not open %ws;", Path, WStatus, RETURN); VolumeInfoLength = sizeof(FILE_FS_VOLUME_INFORMATION) + MAXIMUM_VOLUME_LABEL_LENGTH; VolumeInfo = FrsAlloc(VolumeInfoLength); Status = NtQueryVolumeInformationFile(DirHandle, &IoStatusBlock, VolumeInfo, VolumeInfoLength, FileFsVolumeInformation); NtClose(DirHandle); if (NT_SUCCESS(Status)) { // // Build the table if it does not yet exist. This table is rebuilt at the // start of each DS poll cycle so we have updated information about // the volumes on the machine. // if (VolSerialNumberToDriveTable == NULL) { FrsBuildVolSerialNumberToDriveTable(); } VolumeInfoNode = GTabLookup(VolSerialNumberToDriveTable, &(VolumeInfo->VolumeSerialNumber), NULL); if (VolumeInfoNode) { Volume = FrsWcsDup(VolumeInfoNode->DriveName); } } else { DPRINT1_NT(1,"WARN - NtQueryVolumeInformationFile failed for %ws;", Path, Status); } VolumeInfo = FrsFree(VolumeInfo); RETURN: return Volume; } PWCHAR FrsWcsCat3( PWCHAR First, PWCHAR Second, PWCHAR Third ) /*++ Routine Description: Concatenate three strings into a new string using our memory allocater Arguments: First - First string in the concat Second - Second string in the concat Third - Third string in the concat Return Value: Return concatenated string. Free with FrsFree(). --*/ { #undef DEBSUB #define DEBSUB "FrsWcscat3:" PCHAR New; DWORD BytesFirst; DWORD BytesSecond; DWORD BytesThird; if (!First || !Second || !Third) { return NULL; } // // Allocate a buffer for the concatentated string // BytesFirst = wcslen(First) * sizeof(WCHAR); BytesSecond = wcslen(Second) * sizeof(WCHAR); BytesThird = (wcslen(Third) + 1) * sizeof(WCHAR); New = (PCHAR)FrsAlloc(BytesFirst + BytesSecond + BytesThird); CopyMemory(&New[0], First, BytesFirst); CopyMemory(&New[BytesFirst], Second, BytesSecond); CopyMemory(&New[BytesFirst + BytesSecond], Third, BytesThird); return (PWCHAR)New; } PWCHAR FrsWcsCat( PWCHAR First, PWCHAR Second ) /*++ Routine Description: Concatenate two strings into a new string using our memory allocater Arguments: First - First string in the concat Second - Second string in the concat Return Value: Duplicated and concatentated string. Free with FrsFree(). --*/ { #undef DEBSUB #define DEBSUB "FrsWcscat:" DWORD Bytes; PWCHAR New; FRS_ASSERT(First != NULL && Second != NULL); // size of new string Bytes = (wcslen(First) + wcslen(Second) + 1) * sizeof(WCHAR); New = (PWCHAR)FrsAlloc(Bytes); // Not as efficient as I would like but this routine is seldom used wcscpy(New, First); wcscat(New, Second); return New; } PCHAR FrsCsCat( PCHAR First, PCHAR Second ) /*++ Routine Description: Concatenate two strings into a new string using our memory allocater Arguments: First - First string in the concat Second - Second string in the concat Return Value: Duplicated and concatentated string. Free with FrsFree(). --*/ { #undef DEBSUB #define DEBSUB "FrsCscat:" DWORD Bytes; PCHAR New; FRS_ASSERT(First != NULL && Second != NULL); // size of new string Bytes = strlen(First) + strlen(Second) + 1; New = (PCHAR)FrsAlloc(Bytes); // Not as efficient as I would like but this routine is seldom used strcpy(New, First); strcat(New, Second); return New; } PWCHAR FrsWcsPath( PWCHAR First, PWCHAR Second ) /*++ Routine Description: Concatenate two strings into a pathname Arguments: First - First string in the concat Second - Second string in the concat Return Value: Dup of First\Second. Free with FrsFree(); --*/ { #undef DEBSUB #define DEBSUB "FrsWcsPath:" return FrsWcsCat3(First, L"\\", Second); } PCHAR FrsCsPath( PCHAR First, PCHAR Second ) /*++ Routine Description: Concatenate two strings into a pathname Arguments: First - First string in the concat Second - Second string in the concat Return Value: Duplicated and concatentated string. Free with FrsFree(). --*/ { #undef DEBSUB #define DEBSUB "FrsCsPath:" PCHAR TmpPath; PCHAR FinalPath; // // Very inefficient but seldom called // TmpPath = FrsCsCat(First, "\\"); FinalPath = FrsCsCat(TmpPath, Second); FrsFree(TmpPath); return FinalPath; } PVOID FrsAllocTypeSize( IN NODE_TYPE NodeType, IN ULONG SizeDelta ) /*++ Routine Description: This routine allocates memory for the given node type and performs any node specific initialization/allocation. The node is zeroed and the size/type fields are filled in. Arguments: NodeType - The type of node to allocate. SizeDelta - The amount of storage to allocate in ADDITION to the base type. Return Value: The node address is returned here. An exception is raised if memory could not be allocated. --*/ { #undef DEBSUB #define DEBSUB "FrsAllocTypeSize:" PVOID Node; ULONG NodeSize; PREPLICA Replica; PREPLICA_THREAD_CTX RtCtx; PTHREAD_CTX ThreadCtx; PTABLE_CTX TableCtx; ULONG i; PJBUFFER Jbuffer; PVOLUME_MONITOR_ENTRY pVme; PFILTER_TABLE_ENTRY FilterEntry; PQHASH_TABLE QhashTable; PCXTION Cxtion; PCONFIG_NODE ConfigNode; PCHANGE_ORDER_ENTRY ChangeOrder; PGHANDLE GHandle; PWILDCARD_FILTER_ENTRY WildcardEntry; switch (NodeType) { // // Allocate a Thread Context struct // case THREAD_CONTEXT_TYPE: NodeSize = sizeof(THREAD_CTX); Node = FrsAlloc(NodeSize); // // No session or DB open yet. // ThreadCtx = (PTHREAD_CTX) Node; ThreadCtx->JSesid = JET_sesidNil; ThreadCtx->JDbid = JET_dbidNil; ThreadCtx->JInstance = GJetInstance; FrsRtlInitializeList(&ThreadCtx->ThreadCtxListHead); break; // // Allocate a Replica struct and the config table ctx struct. // case REPLICA_TYPE: NodeSize = sizeof(REPLICA); Node = FrsAlloc(NodeSize); Replica = (PREPLICA) Node; // // Config record flags (CONFIG_FLAG_... in schema.h) // SetFlag(Replica->CnfFlags, CONFIG_FLAG_MULTIMASTER); InitializeCriticalSection(&Replica->ReplicaLock); FrsRtlInitializeList(&Replica->ReplicaCtxListHead); InitializeListHead(&Replica->FileNameFilterHead); InitializeListHead(&Replica->FileNameInclFilterHead); InitializeListHead(&Replica->DirNameFilterHead); InitializeListHead(&Replica->DirNameInclFilterHead); Replica->ConfigTable.TableType = TABLE_TYPE_INVALID; DbsAllocTableCtx(ConfigTablex, &Replica->ConfigTable); Replica->VVector = GTabAllocTable(); Replica->Cxtions = GTabAllocTable(); Replica->FStatus = FrsErrorSuccess; Replica->Consistent = TRUE; InitializeCriticalSection(&Replica->OutLogLock); InitializeListHead(&Replica->OutLogEligible); InitializeListHead(&Replica->OutLogStandBy); InitializeListHead(&Replica->OutLogActive); InitializeListHead(&Replica->OutLogInActive); Replica->OutLogWorkState = OL_REPLICA_INITIALIZING; Replica->ServiceState = REPLICA_STATE_ALLOCATED; Replica->OutLogJLx = 1; // // No preinstall directory, yet // Replica->PreInstallHandle = INVALID_HANDLE_VALUE; // // Initialize the NewStage fiend. // Replica->NewStage = NULL; // // Initialize InitSyncCxtionsMasterList and InitSyncCxtionsWorkingList. // Replica->InitSyncCxtionsMasterList = NULL; Replica->InitSyncCxtionsWorkingList = NULL; Replica->InitSyncQueue = NULL; // // Add memory for the counter data structure, set the back pointer // and bump ref count. // Replica->PerfRepSetData = (PHT_REPLICA_SET_DATA) FrsAlloc (sizeof(HT_REPLICA_SET_DATA)); Replica->PerfRepSetData->RepBackPtr = Replica; InterlockedIncrement(&Replica->ReferenceCount); break; // // Allocate a Replica Thread Context struct and the table context structs. // case REPLICA_THREAD_TYPE: NodeSize = sizeof(REPLICA_THREAD_CTX); Node = FrsAlloc(NodeSize); // // Get the base of the array of TableCtx structs from the replica thread // context struct and the base of the table create structs. // RtCtx = (PREPLICA_THREAD_CTX) Node; TableCtx = RtCtx->RtCtxTables; // // Open the initial set of tables for the replica set. // for (i=0; iTableType = TABLE_TYPE_INVALID; // // If the SizeDelta parameter is non-zero then do not allocate // the TableCtx internal structs. The caller will do it. // if (SizeDelta == 0) { DbsAllocTableCtx(i, TableCtx); } else { // // Mark table as not open by a session yet. // TableCtx->Tid = JET_tableidNil; TableCtx->Sesid = JET_sesidNil; TableCtx->ReplicaNumber = FRS_UNDEFINED_REPLICA_NUMBER; } } break; // // Allocate a topology node // case CONFIG_NODE_TYPE: NodeSize = sizeof(CONFIG_NODE); Node = FrsAlloc(NodeSize); ConfigNode = (PCONFIG_NODE) Node; ConfigNode->Consistent = TRUE; break; // // Allocate a connection // case CXTION_TYPE: NodeSize = sizeof(CXTION); Node = FrsAlloc(NodeSize); Cxtion = Node; Cxtion->CoeTable = GTabAllocTable(); // // Allocate memory for the counter data structure // Cxtion->PerfRepConnData = (PHT_REPLICA_CONN_DATA) FrsAlloc (sizeof(HT_REPLICA_CONN_DATA)); break; // // Allocate a list of bound rpc handles indexed by server guid // case GHANDLE_TYPE: NodeSize = sizeof(GHANDLE); Node = FrsAlloc(NodeSize); GHandle = Node; InitializeCriticalSection(&GHandle->Lock); break; // // Allocate a generic table // case GEN_TABLE_TYPE: NodeSize = sizeof(GEN_TABLE); Node = FrsAlloc(NodeSize); break; // // Allocate a generic thread context // case THREAD_TYPE: NodeSize = sizeof(FRS_THREAD); Node = FrsAlloc(NodeSize); break; // // Allocate a journal read buffer. // case JBUFFER_TYPE: NodeSize = SizeOfJournalBuffer; Node = FrsAlloc(NodeSize); // // Init the data buffer size and start address. // Jbuffer = (PJBUFFER) Node; Jbuffer->BufferSize = NodeSize - SizeOfJournalBufferDesc; Jbuffer->DataBuffer = &Jbuffer->Buffer[0]; break; // // Allocate a journal volume monitor entry. // case VOLUME_MONITOR_ENTRY_TYPE: NodeSize = sizeof(VOLUME_MONITOR_ENTRY); Node = FrsAlloc(NodeSize); pVme = (PVOLUME_MONITOR_ENTRY) Node; FrsRtlInitializeList(&pVme->ReplicaListHead); InitializeCriticalSection(&pVme->Lock); InitializeCriticalSection(&pVme->QuadWriteLock); pVme->Event = CreateEvent(NULL, TRUE, FALSE, NULL); pVme->JournalState = JRNL_STATE_ALLOCATED; break; // // Allocate a command packet. // case COMMAND_PACKET_TYPE: NodeSize = sizeof(COMMAND_PACKET); Node = FrsAlloc(NodeSize + SizeDelta); break; // // Allocate a generic hash table struct. // case GENERIC_HASH_TABLE_TYPE: NodeSize = sizeof(GENERIC_HASH_TABLE); Node = FrsAlloc(NodeSize); break; // // Allocate a Change Order Entry struct. Caller allocates Extension as necc. // case CHANGE_ORDER_ENTRY_TYPE: NodeSize = sizeof(CHANGE_ORDER_ENTRY); Node = FrsAlloc(NodeSize + SizeDelta); ChangeOrder = (PCHANGE_ORDER_ENTRY)Node; // // Init the unicode filename string to point to internal alloc. // ChangeOrder->UFileName.Buffer = ChangeOrder->Cmd.FileName; ChangeOrder->UFileName.MaximumLength = (USHORT) (SIZEOF(CHANGE_ORDER_ENTRY, Cmd.FileName) + SizeDelta); ChangeOrder->UFileName.Length = 0; break; // // Allocate a Filter Table Entry struct. // case FILTER_TABLE_ENTRY_TYPE: NodeSize = sizeof(FILTER_TABLE_ENTRY); Node = FrsAlloc(NodeSize + SizeDelta); FilterEntry = (PFILTER_TABLE_ENTRY)Node; // // Init the unicode filename string to point to internal alloc. // FilterEntry->UFileName.Buffer = FilterEntry->DFileName; FilterEntry->UFileName.MaximumLength = (USHORT)SizeDelta + sizeof(WCHAR); FilterEntry->UFileName.Length = 0; InitializeListHead(&FilterEntry->ChildHead); break; // // Allocate a QHASH table struct. Just alloc the // base table. An extension is allocated on the first collision. // *NOTE* caller specifies the size of the actual hash table and // the extension. Caller also must store an address to a hash calc // function. // case QHASH_TABLE_TYPE: NodeSize = sizeof(QHASH_TABLE); Node = FrsAlloc(NodeSize + SizeDelta); QhashTable = (PQHASH_TABLE)Node; InitializeCriticalSection(&QhashTable->Lock); InitializeListHead(&QhashTable->ExtensionListHead); QhashTable->BaseAllocSize = NodeSize + SizeDelta; QhashTable->NumberEntries = SizeDelta / sizeof(QHASH_ENTRY); if (SizeDelta <= QHASH_EXTENSION_MAX) { QhashTable->ExtensionAllocSize = sizeof(LIST_ENTRY) + SizeDelta; } else { QhashTable->ExtensionAllocSize = sizeof(LIST_ENTRY) + QHASH_EXTENSION_MAX; } QhashTable->HashRowBase = (PQHASH_ENTRY) (QhashTable + 1); SET_QHASH_TABLE_HASH_CALC(QhashTable, NULL); QhashTable->FreeList.Next = NULL; break; // // Allocate an Output Log Partner struct. // This is ultimately hooked to a Connection struct which provides the // Guid and version vector. // case OUT_LOG_PARTNER_TYPE: NodeSize = sizeof(OUT_LOG_PARTNER); Node = FrsAlloc(NodeSize); break; // // Allocate a WildcardEntry filter Entry struct. // case WILDCARD_FILTER_ENTRY_TYPE: NodeSize = sizeof(WILDCARD_FILTER_ENTRY); Node = FrsAlloc(NodeSize + SizeDelta); WildcardEntry = (PWILDCARD_FILTER_ENTRY)Node; // // Init the unicode filename string to point to internal alloc. // WildcardEntry->UFileName.Buffer = WildcardEntry->FileName; WildcardEntry->UFileName.MaximumLength = (USHORT)SizeDelta; WildcardEntry->UFileName.Length = 0; break; // // Invalid Node Type // default: Node = NULL; DPRINT1(0, "Internal error - invalid node type - %d\n", NodeType); XRAISEGENEXCEPTION(FrsErrorInternalError); } // // Set up the header for later checking in FrsFreeType // ((PFRS_NODE_HEADER) Node)->Type = (USHORT) NodeType; ((PFRS_NODE_HEADER) Node)->Size = (USHORT) NodeSize; // // Tracking memory expansion // EnterCriticalSection(&MemLock); TypesAllocated[NodeType]++; TypesAllocatedCount[NodeType]++; if (TypesAllocated[NodeType] > TypesAllocatedMax[NodeType]) { TypesAllocatedMax[NodeType] = TypesAllocated[NodeType]; } LeaveCriticalSection(&MemLock); // // Return node address to caller. // return Node; } PVOID FrsFreeType( IN PVOID Node ) /*++ Routine Description: This routine frees memory for the given node, performing any node specific cleanup. It marks the freed memory with the hex string 0xDEADBEnn where the low byte (nn) is set to the node type being freed to catch users of stale pointers. Arguments: Node - The address of the node to free. Return Value: NULL. Typical call is: ptr = FrsFreeType(ptr) to catch errors. --*/ { #undef DEBSUB #define DEBSUB "FrsFreeType:" ULONG NodeSize; ULONG NodeType; ULONG Marker; PREPLICA Replica; PREPLICA_THREAD_CTX RtCtx; PTABLE_CTX TableCtx; PTHREAD_CTX ThreadCtx; ULONG i; PVOLUME_MONITOR_ENTRY pVme; PFILTER_TABLE_ENTRY FilterEntry; PQHASH_TABLE QhashTable; PLIST_ENTRY Entry; PCXTION Cxtion; PCONFIG_NODE ConfigNode; PCHANGE_ORDER_ENTRY ChangeOrder; PGHANDLE GHandle; PHANDLE_LIST HandleList; PWILDCARD_FILTER_ENTRY WildcardEntry; POUT_LOG_PARTNER OutLogPartner; if (Node == NULL) { return NULL; } NodeType = (ULONG) (((PFRS_NODE_HEADER) Node)->Type); NodeSize = (ULONG) (((PFRS_NODE_HEADER) Node)->Size); switch (NodeType) { // // Free a Thread Context struct // case THREAD_CONTEXT_TYPE: if (NodeSize != sizeof(THREAD_CTX)) { DPRINT1(0, "FrsFree - Bad node size %d for THREAD_CONTEXT\n", NodeSize); XRAISEGENEXCEPTION(FrsErrorInternalError); } ThreadCtx = (PTHREAD_CTX) Node; FrsRtlDeleteList(&ThreadCtx->ThreadCtxListHead); break; // // Free a Replica struct // case REPLICA_TYPE: if (NodeSize != sizeof(REPLICA)) { DPRINT1(0, "FrsFree - Bad node size %d for REPLICA\n", NodeSize); XRAISEGENEXCEPTION(FrsErrorInternalError); } Replica = (PREPLICA) Node; // // Free the config table context. // DbsFreeTableCtx(&Replica->ConfigTable, NodeType); FrsRtlDeleteList(&Replica->ReplicaCtxListHead); // // Empty the file and directory filter lists // FrsEmptyNameFilter(&Replica->FileNameFilterHead); FrsEmptyNameFilter(&Replica->FileNameInclFilterHead); FrsEmptyNameFilter(&Replica->DirNameFilterHead); FrsEmptyNameFilter(&Replica->DirNameInclFilterHead); FrsFree(Replica->FileFilterList); FrsFree(Replica->FileInclFilterList); FrsFree(Replica->DirFilterList); FrsFree(Replica->DirInclFilterList); DeleteCriticalSection(&Replica->ReplicaLock); DeleteCriticalSection(&Replica->OutLogLock); if (Replica->OutLogRecordLock != NULL) { // // Free the record lock table. // Replica->OutLogRecordLock = FrsFreeType(Replica->OutLogRecordLock); } // // queue // if (Replica->Queue) { FrsRtlDeleteQueue(Replica->Queue); FrsFree(Replica->Queue); } // // free the initsync queue. // if (Replica->InitSyncQueue) { FrsRtlDeleteQueue(Replica->InitSyncQueue); Replica->InitSyncQueue = FrsFree(Replica->InitSyncQueue); } // // Names // FrsFree(Replica->Root); FrsFree(Replica->Stage); FrsFree(Replica->NewStage); FrsFree(Replica->Volume); FrsFreeGName(Replica->ReplicaName); FrsFreeGName(Replica->SetName); FrsFreeGName(Replica->MemberName); // // Root Guid // FrsFree(Replica->ReplicaRootGuid); // // Status of sysvol seeding // FrsFree(Replica->NtFrsApi_ServiceDisplay); // // Schedule // FrsFree(Replica->Schedule); // // VVector // VVFree(Replica->VVector); // // Cxtions // GTabFreeTable(Replica->Cxtions, FrsFreeType); // // Preinstall directory // FRS_CLOSE(Replica->PreInstallHandle); // // Free the counter data structure memory // if (Replica->PerfRepSetData != NULL) { if (Replica->PerfRepSetData->oid != NULL) { if (Replica->PerfRepSetData->oid->name != NULL) { Replica->PerfRepSetData->oid->name = FrsFree(Replica->PerfRepSetData->oid->name); } Replica->PerfRepSetData->oid = FrsFree(Replica->PerfRepSetData->oid); } Replica->PerfRepSetData = FrsFree(Replica->PerfRepSetData); } break; // // Free a Replica Thread Context struct // case REPLICA_THREAD_TYPE: if (NodeSize != sizeof(REPLICA_THREAD_CTX)) { DPRINT1(0, "FrsFree - Bad node size %d for REPLICA_THREAD_CTX\n", NodeSize); XRAISEGENEXCEPTION(FrsErrorInternalError); } RtCtx = (PREPLICA_THREAD_CTX) Node; // // Get the base of the array of TableCtx structs from the replica thread // context struct. // TableCtx = RtCtx->RtCtxTables; // // Release the memory for each table context struct. // for (i=0; iName); FrsFreeGName(ConfigNode->PartnerName); FrsFree(ConfigNode->Root); FrsFree(ConfigNode->Stage); FrsFree(ConfigNode->Schedule); FrsFree(ConfigNode->Dn); FrsFree(ConfigNode->PrincName); FrsFree(ConfigNode->PartnerDn); FrsFree(ConfigNode->PartnerCoDn); FrsFree(ConfigNode->SettingsDn); FrsFree(ConfigNode->ComputerDn); FrsFree(ConfigNode->MemberDn); FrsFree(ConfigNode->Working); FrsFree(ConfigNode->SetType); FrsFree(ConfigNode->FileFilterList); FrsFree(ConfigNode->DirFilterList); FrsFree(ConfigNode->UsnChanged); FrsFree(ConfigNode->DnsName); FrsFree(ConfigNode->PartnerDnsName); FrsFree(ConfigNode->Sid); FrsFree(ConfigNode->PartnerSid); FrsFree(ConfigNode->EnabledCxtion); break; // // Free a connection // case CXTION_TYPE: if (NodeSize != sizeof(CXTION)) { DPRINT1(0, "FrsFree - Bad node size %d for CXTION\n", NodeSize); XRAISEGENEXCEPTION(FrsErrorInternalError); } Cxtion = (PCXTION) Node; VVFreeOutbound(Cxtion->VVector); // // Free the CompressionTable that was build for the outbound partner. // GTabFreeTable(Cxtion->CompressionTable, FrsFree); // // Free the OutLogPartner context. // FrsFreeType(Cxtion->OLCtx); SndCsDestroyCxtion(Cxtion, CXTION_FLAGS_UNJOIN_GUID_VALID); if (Cxtion->CommTimeoutCmd) { // // Try to catch the case where a Comm Time Out wait command is // getting freed while it is still on the timeout queue. This is // related to a bug where we get into a comm timeout loop with an // invalid command code. // FRS_ASSERT(!CxtionFlagIs(Cxtion, CXTION_FLAGS_TIMEOUT_SET)); FRS_ASSERT(!CmdWaitFlagIs(Cxtion->CommTimeoutCmd, CMD_PKT_WAIT_FLAGS_ONLIST)); FrsFreeType(Cxtion->CommTimeoutCmd); } // // A cxtion doesn't actually "own" the join command packet; it // only maintains a reference to prevent extraneous join commands // from flooding the replica's queue. // Cxtion->JoinCmd = NULL; // // VvJoin Command Server (1 per cxtion) // if (Cxtion->VvJoinCs) { FrsRunDownCommandServer(Cxtion->VvJoinCs, &Cxtion->VvJoinCs->Queue); FrsDeleteCommandServer(Cxtion->VvJoinCs); FrsFree(Cxtion->VvJoinCs); } if (!Cxtion->ChangeOrderCount) { GTabFreeTable(Cxtion->CoeTable, NULL); } FrsFreeGName(Cxtion->Name); FrsFreeGName(Cxtion->Partner); FrsFree(Cxtion->PartnerPrincName); FrsFree(Cxtion->Schedule); FrsFree(Cxtion->PartSrvName); FrsFree(Cxtion->PartnerDnsName); FrsFree(Cxtion->PartnerSid); // // Delete the connection from the perfmon tables. // Free the counter data structure memory // if (Cxtion->PerfRepConnData != NULL) { if (Cxtion->PerfRepConnData->oid != NULL) { DeletePerfmonInstance(REPLICACONN, Cxtion->PerfRepConnData); } Cxtion->PerfRepConnData = FrsFree(Cxtion->PerfRepConnData); } break; // // Free a guid/rpc handle // case GHANDLE_TYPE: if (NodeSize != sizeof(GHANDLE)) { DPRINT2(0, "FrsFree - Bad node size %d (%d) for GHANDLE\n", NodeSize, sizeof(GHANDLE)); XRAISEGENEXCEPTION(FrsErrorInternalError); } GHandle = (PGHANDLE)Node; while (HandleList = GHandle->HandleList) { GHandle->HandleList = HandleList->Next; FrsRpcUnBindFromServer(&HandleList->RpcHandle); FrsFree(HandleList); } DeleteCriticalSection(&GHandle->Lock); break; // // Free a generic table // case GEN_TABLE_TYPE: if (NodeSize != sizeof(GEN_TABLE)) { DPRINT1(0, "FrsFree - Bad node size %d for GEN_TABLE\n", NodeSize); XRAISEGENEXCEPTION(FrsErrorInternalError); } break; // // Free a generic thread context // case THREAD_TYPE: if (NodeSize != sizeof(FRS_THREAD)) { DPRINT1(0, "FrsFree - Bad node size %d for FRS_THREAD\n", NodeSize); XRAISEGENEXCEPTION(FrsErrorInternalError); } break; // // Free a journal read buffer. // case JBUFFER_TYPE: if (NodeSize != SizeOfJournalBuffer) { DPRINT1(0, "FrsFree - Bad node size %d for JBUFFER\n", NodeSize); XRAISEGENEXCEPTION(FrsErrorInternalError); } break; // // Free a journal volume monitor entry. // case VOLUME_MONITOR_ENTRY_TYPE: if (NodeSize != sizeof(VOLUME_MONITOR_ENTRY)) { DPRINT1(0, "FrsFree - Bad node size %d for VOLUME_MONITOR_ENTRY\n", NodeSize); XRAISEGENEXCEPTION(FrsErrorInternalError); } pVme = (PVOLUME_MONITOR_ENTRY) Node; FrsRtlDeleteList(&pVme->ReplicaListHead); DeleteCriticalSection(&pVme->Lock); DeleteCriticalSection(&pVme->QuadWriteLock); FRS_CLOSE(pVme->Event); // // Release the change order hash table. // GhtDestroyTable(pVme->ChangeOrderTable); // // Release the Filter Hash Table. // GhtDestroyTable(pVme->FilterTable); break; // // Free a command packet. // case COMMAND_PACKET_TYPE: if (NodeSize != sizeof(COMMAND_PACKET)) { DPRINT1(0, "FrsFree - Bad node size %d for COMMAND_PACKET\n", NodeSize); XRAISEGENEXCEPTION(FrsErrorInternalError); } break; // // Free a generic hash table struct. // case GENERIC_HASH_TABLE_TYPE: if (NodeSize != sizeof(GENERIC_HASH_TABLE)) { DPRINT1(0, "FrsFree - Bad node size %d for GENERIC_HASH_TABLE\n", NodeSize); XRAISEGENEXCEPTION(FrsErrorInternalError); } break; // // Free a Change Order Entry struct. // case CHANGE_ORDER_ENTRY_TYPE: if (NodeSize != sizeof(CHANGE_ORDER_ENTRY)) { DPRINT1(0, "FrsFree - Bad node size %d for CHANGE_ORDER_ENTRY\n", NodeSize); XRAISEGENEXCEPTION(FrsErrorInternalError); } ChangeOrder = (PCHANGE_ORDER_ENTRY)Node; // // If we allocated a new name string then free it. // if (ChangeOrder->UFileName.Buffer != ChangeOrder->Cmd.FileName) { FrsFree(ChangeOrder->UFileName.Buffer); } // // Free the change order extenstion. // if (ChangeOrder->Cmd.Extension != NULL) { FrsFree(ChangeOrder->Cmd.Extension); } break; // // Free a Filter Table Entry struct. // case FILTER_TABLE_ENTRY_TYPE: if (NodeSize != sizeof(FILTER_TABLE_ENTRY)) { DPRINT1(0, "FrsFree - Bad node size %d for FILTER_TABLE_ENTRY\n", NodeSize); XRAISEGENEXCEPTION(FrsErrorInternalError); } FilterEntry = (PFILTER_TABLE_ENTRY)Node; // // If we allocated a new name string then free it. // if (FilterEntry->UFileName.Buffer != FilterEntry->DFileName) { FrsFree(FilterEntry->UFileName.Buffer); } break; // // Free a QHASH table struct. // case QHASH_TABLE_TYPE: if (NodeSize != sizeof(QHASH_TABLE)) { DPRINT1(0, "FrsFree - Bad node size %d for QHASH_TABLE\n", NodeSize); XRAISEGENEXCEPTION(FrsErrorInternalError); } QhashTable = (PQHASH_TABLE)Node; QHashEmptyLargeKeyTable(QhashTable); // // Free up all the extensions we allocated. // while (!IsListEmpty(&QhashTable->ExtensionListHead)) { Entry = GetListHead(&QhashTable->ExtensionListHead); FrsRemoveEntryList(Entry); FrsFree(Entry); } DeleteCriticalSection(&QhashTable->Lock); break; // // Free an Output Log Partner struct. // case OUT_LOG_PARTNER_TYPE: if (NodeSize != sizeof(OUT_LOG_PARTNER)) { DPRINT1(0, "FrsFree - Bad node size %d for OUT_LOG_PARTNER\n", NodeSize); XRAISEGENEXCEPTION(FrsErrorInternalError); } OutLogPartner = (POUT_LOG_PARTNER)Node; // // Free the Must send QHash Table. // OutLogPartner->MustSendTable = FrsFreeType(OutLogPartner->MustSendTable); break; // // Free a Wildcard file filter Entry struct. // case WILDCARD_FILTER_ENTRY_TYPE: if (NodeSize != sizeof(WILDCARD_FILTER_ENTRY)) { DPRINT1(0, "FrsFree - Bad node size %d for WILDCARD_FILTER_ENTRY\n", NodeSize); XRAISEGENEXCEPTION(FrsErrorInternalError); } WildcardEntry = (PWILDCARD_FILTER_ENTRY)Node; // // Free the name buffer if it no longer points at the initial alloc. // if (WildcardEntry->UFileName.Buffer != WildcardEntry->FileName) { FrsFree(WildcardEntry->UFileName.Buffer); } break; // // Invalid Node Type // default: Node = NULL; DPRINT1(0, "Internal error - invalid node type - %d\n", NodeType); XRAISEGENEXCEPTION(FrsErrorInternalError); } EnterCriticalSection(&MemLock); TypesAllocated[NodeType]--; LeaveCriticalSection(&MemLock); // // Fill the node with a marker then free it. // Marker = (ULONG) 0xDEADBE00 + NodeType; FillMemory(Node, NodeSize, (BYTE)Marker); return FrsFree(Node); } VOID FrsFreeTypeList( PLIST_ENTRY Head ) /*++ Routine Description: Free all the "typed" entries on the specified list. Note: This routine requires that the LIST_ENTRY struct in each list entry immediately follow the FRS_NODE_HEADER and of course that the list entry is actually linked through that LIST_ENTRY struct. Arguments: Head -- ptr to the list head. Thread Return Value: None. --*/ { #undef DEBSUB #define DEBSUB "FrsFreeTypeList:" PLIST_ENTRY Entry; PFRS_NODE_HEADER Header; Entry = RemoveHeadList(Head); while (Entry != Head) { Header = (PFRS_NODE_HEADER) CONTAINING_RECORD(Entry, COMMAND_PACKET, ListEntry); if ((Header->Type >= NODE_TYPE_MIN) && (Header->Type < NODE_TYPE_MAX)) { FrsFreeType(Header); } else { DPRINT(0, "Node type out of range. Not freed.\n"); } Entry = RemoveHeadList(Head); } } VOID FrsPrintGNameForNode( IN ULONG Severity, IN PGNAME GName, IN PWCHAR Indent, IN PWCHAR Id, IN PCHAR Debsub, IN ULONG uLineNo ) /*++ Routine Description: Pretty print a gname for FrsPrintNode() Arguments: Severity -- Severity level for print. (See debug.c, debug.h) GName - The address of the GName to print. Indent - line indentation Id - identifies the gname Debsub -- Name of calling subroutine. uLineno -- Line number of caller Return Value: none. --*/ { CHAR GuidStr[GUID_CHAR_LEN]; if (GName) { if (GName->Name) { FRS_DEB_PRINT3("%ws%ws: %ws\n", Indent, Id, GName->Name); } else { FRS_DEB_PRINT3("%wsNO %ws->NAME for %08x\n", Indent, Id, GName); } if (GName->Guid) { GuidToStr(GName->Guid, GuidStr); FRS_DEB_PRINT3("%ws%wsGuid: %s\n", Indent, Id, GuidStr); } else { FRS_DEB_PRINT3("%wsNO %ws->GUID for %08x\n", Indent, Id, GName); } } else { FRS_DEB_PRINT3("%wsNO %ws for %08x\n", Indent, Id, GName); } } VOID FrsPrintTypeSchedule( IN ULONG Severity, OPTIONAL IN PNTFRSAPI_INFO Info, OPTIONAL IN DWORD Tabs, OPTIONAL IN PSCHEDULE Schedule, IN PCHAR Debsub, OPTIONAL IN ULONG uLineNo OPTIONAL ) /*++ Routine Description: Print a schedule. Arguments: Severity - for DPRINTs Info - RPC output buffer Tabs - prettyprint Schedule - schedule blob Debsub - for DPRINTs uLineNo - for DPRINTs Return Value: None. --*/ { ULONG i; ULONG Day; ULONG Hour; ULONG LineLen; PUCHAR ScheduleData; CHAR Line[256]; WCHAR TabW[MAX_TAB_WCHARS + 1]; if (!Schedule) { return; } InfoTabs(Tabs, TabW); for (i = 0; i < Schedule->NumberOfSchedules; ++i) { ScheduleData = ((PUCHAR)Schedule) + Schedule->Schedules[i].Offset; if (Schedule->Schedules[i].Type != SCHEDULE_INTERVAL) { continue; } for (Day = 0; Day < 7; ++Day) { _snprintf(Line, sizeof(Line), "%wsDay %1d: ", TabW, Day + 1); for (Hour = 0; Hour < 24; ++Hour) { LineLen = strlen(Line); _snprintf(&Line[LineLen], sizeof(Line) - LineLen, "%1x", *(ScheduleData + (Day * 24) + Hour) & 0x0F); } ITPRINT1("%s\n", Line); } } } VOID FrsPrintTypeVv( IN ULONG Severity, OPTIONAL IN PNTFRSAPI_INFO Info, OPTIONAL IN DWORD Tabs, OPTIONAL IN PGEN_TABLE Vv, IN PCHAR Debsub, OPTIONAL IN ULONG uLineNo OPTIONAL ) /*++ Routine Description: Print a version vector Arguments: Severity - for DPRINTs Info - RPC output buffer Tabs - prettyprint Vv - Version vector table Debsub - for DPRINTs uLineNo - for DPRINTs Return Value: None. --*/ { #undef DEBSUB #define DEBSUB "FrsPrintTypeVv:" PVOID Key; PVV_ENTRY MasterVVEntry; WCHAR TabW[MAX_TAB_WCHARS + 1]; CHAR Guid[GUID_CHAR_LEN + 1]; if (!Vv) { return; } InfoTabs(Tabs, TabW); Key = NULL; while (MasterVVEntry = GTabNextDatum(Vv, &Key)) { if (!Info) { DebLock(); } GuidToStr(&MasterVVEntry->GVsn.Guid, Guid); ITPRINT3("%wsVvEntry: %s = %08x %08x\n", TabW, Guid, PRINTQUAD(MasterVVEntry->GVsn.Vsn)); if (!Info) { DebUnLock(); } } } VOID FrsPrintTypeOutLogAVToStr( POUT_LOG_PARTNER OutLogPartner, ULONG RetireCOx, PCHAR *OutStr1, PCHAR *OutStr2, PCHAR *OutStr3 ) { #undef DEBSUB #define DEBSUB "FrsPrintTypeOutLogAVToStr:" PCHAR Str, Str2, Str3; ULONG j, Slotx, MaxSlotx, COx, Fill, Scan; // // Caller frees strings with FrsFree(Str). // Str = FrsAlloc(3*(ACK_VECTOR_SIZE+4)); Str2 = Str + (ACK_VECTOR_SIZE+4); Str3 = Str2 + (ACK_VECTOR_SIZE+4); COx = OutLogPartner->COTx; Slotx = AVSlot(OutLogPartner->COTx, OutLogPartner); MaxSlotx = Slotx + ACK_VECTOR_SIZE; while (Slotx < MaxSlotx) { j = Slotx & (ACK_VECTOR_SIZE-1); if (ReadAVBitBySlot(Slotx, OutLogPartner) == 0) { Str[j] = '.'; } else { Str[j] = '1'; } if (COx == OutLogPartner->COTx) { Str2[j] = 'T'; } else if (COx == OutLogPartner->COLx) { Str2[j] = 'L'; } else { Str2[j] = '_'; } if (COx == RetireCOx) { Str3[j] = '^'; } else { Str3[j] = ' '; } COx += 1; Slotx += 1; } Str[ACK_VECTOR_SIZE] = '\0'; Str2[ACK_VECTOR_SIZE] = '\0'; Str3[ACK_VECTOR_SIZE] = '\0'; // // Compress out blocks of 8 // Fill = 0; Scan = 0; while (Scan < ACK_VECTOR_SIZE) { for (j=Scan; j < Scan+8; j++) { if ((Str[j] != '.') || (Str2[j] != '_') || (Str3[j] != ' ')) { break; } } if (j == Scan+8) { // Compress out this block Str[Fill] = Str2[Fill] = Str3[Fill] = '-'; Fill += 1; } else { // Copy this block to fill point of strings. for (j=Scan; j < Scan+8; j++) { Str[Fill] = Str[j]; Str2[Fill] = Str2[j]; Str3[Fill] = Str3[j]; Fill += 1; } } Scan += 8; } Str[Fill] = Str2[Fill] = Str3[Fill] = '\0'; *OutStr1 = Str; *OutStr2 = Str2; *OutStr3 = Str3; return; } VOID FrsPrintTypeOutLogPartner( IN ULONG Severity, OPTIONAL IN PNTFRSAPI_INFO Info, OPTIONAL IN DWORD Tabs, OPTIONAL IN POUT_LOG_PARTNER Olp, IN ULONG RetireCox, IN PCHAR Description, IN PCHAR Debsub, OPTIONAL IN ULONG uLineNo OPTIONAL ) /*++ Routine Description: Print an outlog partner Arguments: Severity - for DPRINTs Info - RPC output buffer Tabs - prettyprint Olp - Out log partner struct RetireCox - change order index for ack vector Description - description of caller Debsub - for DPRINTs uLineNo - for DPRINTs Return Value: None. --*/ { #undef DEBSUB #define DEBSUB "FrsPrintTypeOutLogPartner:" PCHAR OutStr1, OutStr2, OutStr3; CHAR FBuf[120]; CHAR TimeStr[TIME_STRING_LENGTH]; WCHAR TabW[MAX_TAB_WCHARS + 1]; InfoTabs(Tabs, TabW); if (!Info) { DebLock(); } ITPRINT2("%wsOutLogPartner : %s\n", TabW, Description); if (Olp->Cxtion && Olp->Cxtion->Name) { ITPRINT2( "%wsCxtion : %ws\n", TabW, Olp->Cxtion->Name->Name); if (Olp->Cxtion->Partner && Olp->Cxtion->Partner->Name) { ITPRINT2( "%wsPartner : %ws\n", TabW, Olp->Cxtion->Partner->Name); } } FrsFlagsToStr(Olp->Flags, OlpFlagNameTable, sizeof(FBuf), FBuf); ITPRINT3("%wsFlags : %08x Flags [%s]\n", TabW, Olp->Flags, FBuf); ITPRINT2("%wsState : %s\n", TabW, OLPartnerStateNames[Olp->State]); ITPRINT2("%wsCoTx : %8d\n", TabW, Olp->COTx); ITPRINT2("%wsCoLx : %8d\n", TabW, Olp->COLx); ITPRINT2("%wsCOLxRestart : %8d\n", TabW, Olp->COLxRestart); ITPRINT2("%wsCOLxVVJoinDone : %8d\n", TabW, Olp->COLxVVJoinDone); ITPRINT2("%wsCoTxSave : %8d\n", TabW, Olp->COTxNormalModeSave); ITPRINT2("%wsCoTslot : %8d\n", TabW, Olp->COTslot); ITPRINT2("%wsOutstandingCos : %8d\n", TabW, Olp->OutstandingCos); ITPRINT2("%wsOutstandingQuota: %8d\n", TabW, Olp->OutstandingQuota); FileTimeToString((PFILETIME) &Olp->AckVersion, TimeStr); ITPRINT2("%wsAckVersion : %s\n" , TabW, TimeStr); if (RetireCox != -1) { ITPRINT2("%wsRetireCox : %8d\n", TabW, RetireCox); } FrsPrintTypeOutLogAVToStr(Olp, RetireCox, &OutStr1, &OutStr2, &OutStr3); // // keep output together. // ITPRINT2("%wsAck: |%s|\n", TabW, OutStr1); ITPRINT2("%wsAck: |%s|\n", TabW, OutStr2); ITPRINT2("%wsAck: |%s|\n", TabW, OutStr3); FrsFree(OutStr1); if (!Info) { DebUnLock(); } } VOID FrsPrintTypeCxtion( IN ULONG Severity, OPTIONAL IN PNTFRSAPI_INFO Info, OPTIONAL IN DWORD Tabs, OPTIONAL IN PCXTION Cxtion, IN PCHAR Debsub, OPTIONAL IN ULONG uLineNo OPTIONAL ) /*++ Routine Description: Print a cxtion Arguments: Severity - for DPRINTs Info - RPC output buffer Tabs - prettyprint Cxtion Debsub - for DPRINTs uLineNo - for DPRINTs Return Value: None. --*/ { #undef DEBSUB #define DEBSUB "FrsPrintTypeCxtion:" WCHAR TabW[MAX_TAB_WCHARS + 1]; CHAR Guid[GUID_CHAR_LEN + 1]; CHAR TimeStr[TIME_STRING_LENGTH]; CHAR FlagBuffer[120]; if (!Cxtion) { return; } // // Prettyprint indentation // InfoTabs(Tabs, TabW); if (!Info) { DebLock(); } ITPRINT0("\n"); ITPRINTGNAME(Cxtion->Name, "%ws Cxtion: %ws (%s)\n"); ITPRINTGNAME(Cxtion->Partner, "%ws Partner : %ws (%s)\n"); ITPRINT2("%ws PartDnsName : %ws\n", TabW, Cxtion->PartnerDnsName); ITPRINT2("%ws PartSrvName : %ws\n", TabW, Cxtion->PartSrvName); ITPRINT2("%ws PartPrincName: %ws\n", TabW, Cxtion->PartnerPrincName); ITPRINT2("%ws PartSid : %ws\n", TabW, Cxtion->PartnerSid); ITPRINTGUID(&Cxtion->ReplicaVersionGuid, "%ws OrigGuid : %s\n"); ITPRINT2("%ws State : %d\n", TabW, Cxtion->State); FrsFlagsToStr(Cxtion->Flags, CxtionFlagNameTable, sizeof(FlagBuffer), FlagBuffer); ITPRINT3("%ws Flags : %08x Flags [%s]\n", TabW, Cxtion->Flags, FlagBuffer); ITPRINT2("%ws Inbound : %s\n", TabW, (Cxtion->Inbound) ? "TRUE" : "FALSE"); ITPRINT2("%ws JrnlCxtion : %s\n", TabW, (Cxtion->JrnlCxtion) ? "TRUE" : "FALSE"); ITPRINT2("%ws Options : 0x%08x\n", TabW, Cxtion->Options); ITPRINT2("%ws PartnerAuth : %d\n", TabW, Cxtion->PartnerAuthLevel); ITPRINT2("%ws TermCoSn : %d\n", TabW, Cxtion->TerminationCoSeqNum); ITPRINT2("%ws JoinCmd : 0x%08x\n", TabW, Cxtion->JoinCmd); ITPRINT2("%ws CoCount : %d\n", TabW, Cxtion->ChangeOrderCount); ITPRINT2("%ws CommQueue : %d\n", TabW, Cxtion->CommQueueIndex); ITPRINT2("%ws CoPQ : %08x\n", TabW, Cxtion->CoProcessQueue); ITPRINT2("%ws UnjoinTrigger: %d\n", TabW, Cxtion->UnjoinTrigger); ITPRINT2("%ws UnjoinReset : %d\n", TabW, Cxtion->UnjoinReset); ITPRINT2("%ws Comm Packets : %d\n", TabW, Cxtion->CommPkts); ITPRINT2("%ws PartnerMajor : %d\n", TabW, Cxtion->PartnerMajor); ITPRINT2("%ws PartnerMinor : %d\n", TabW, Cxtion->PartnerMinor); // // Don't print the join guid in the logs; they may be readable // by anyone. An Info-RPC is secure so return the join guid in // case it is needed for debugging. // if (Info) { ITPRINTGUID(&Cxtion->JoinGuid, "%ws JoinGuid : %s\n"); FileTimeToString((PFILETIME) &Cxtion->LastJoinTime, TimeStr); ITPRINT2("%ws LastJoinTime : %s\n" , TabW, TimeStr); } if (Cxtion->Schedule) { ITPRINT1("%ws Schedule\n", TabW); FrsPrintTypeSchedule(Severity, Info, Tabs + 3, Cxtion->Schedule, Debsub, uLineNo); } if (Cxtion->VVector) { ITPRINT1("%ws Version Vector\n", TabW); } if (!Info) { DebUnLock(); } if (Cxtion->VVector) { FrsPrintTypeVv(Severity, Info, Tabs + 3, Cxtion->VVector, Debsub, uLineNo); } if (Cxtion->OLCtx) { if (!Info) { DebLock(); } ITPRINT1("%ws OutLog Partner\n", TabW); if (!Info) { DebUnLock(); } FrsPrintTypeOutLogPartner(Severity, Info, Tabs + 3, Cxtion->OLCtx, -1, "FrsPrintType", Debsub, uLineNo); } } VOID FrsPrintTypeCxtions( IN ULONG Severity, OPTIONAL IN PNTFRSAPI_INFO Info, OPTIONAL IN DWORD Tabs, OPTIONAL IN PGEN_TABLE Cxtions, IN PCHAR Debsub, OPTIONAL IN ULONG uLineNo OPTIONAL ) /*++ Routine Description: Print a table of cxtions Arguments: Severity - for DPRINTs Info - RPC output buffer Tabs - prettyprint Cxtions - Cxtion table Debsub - for DPRINTs uLineNo - for DPRINTs Return Value: None. --*/ { #undef DEBSUB #define DEBSUB "FrsPrintTypeCxtions:" PVOID Key; PCXTION Cxtion; WCHAR TabW[MAX_TAB_WCHARS + 1]; CHAR Guid[GUID_CHAR_LEN + 1]; if (!Cxtions) { return; } // // Prettyprint indentation // InfoTabs(Tabs, TabW); Key = NULL; while (Cxtion = GTabNextDatum(Cxtions, &Key)) { FrsPrintTypeCxtion(Severity, Info, Tabs, Cxtion, Debsub, uLineNo); } } VOID FrsPrintTypeReplica( IN ULONG Severity, OPTIONAL IN PNTFRSAPI_INFO Info, OPTIONAL IN DWORD Tabs, OPTIONAL IN PREPLICA Replica, IN PCHAR Debsub, OPTIONAL IN ULONG uLineNo OPTIONAL ) /*++ Routine Description: Print a replica and its cxtions. Arguments: Severity -- Severity level for print. (See debug.c, debug.h) Info - Text buffer Tabs - Prettyprint prepense Replica - Replica struct Debsub -- Name of calling subroutine. uLineno -- Line number of caller MACRO: FRS_PRINT_TYPE Return Value: none. --*/ { #undef DEBSUB #define DEBSUB "FrsPrintTypeReplica:" CHAR Guid[GUID_CHAR_LEN + 1]; WCHAR TabW[MAX_TAB_WCHARS + 1]; CHAR FlagBuffer[120]; if (!Replica) { return; } InfoTabs(Tabs, TabW); if (!Info) { DebLock(); } ITPRINTGNAME(Replica->SetName, "%ws Replica: %ws (%s)\n"); ITPRINTGNAME(Replica->MemberName, "%ws Member : %ws (%s)\n"); ITPRINTGNAME(Replica->ReplicaName, "%ws Name : %ws (%s)\n"); ITPRINTGUID(Replica->ReplicaRootGuid, "%ws RootGuid : %s\n"); ITPRINTGUID(&Replica->ReplicaVersionGuid, "%ws OrigGuid : %s\n"); ITPRINT2("%ws Reference : %d\n", TabW, Replica->ReferenceCount); FrsFlagsToStr(Replica->CnfFlags, ConfigFlagNameTable, sizeof(FlagBuffer), FlagBuffer); ITPRINT3("%ws CnfFlags : %08x Flags [%s]\n", TabW, Replica->CnfFlags, FlagBuffer); ITPRINT2("%ws SetType : %d\n", TabW, Replica->ReplicaSetType); ITPRINT2("%ws Consistent : %d\n", TabW, Replica->Consistent); ITPRINT2("%ws IsOpen : %d\n", TabW, Replica->IsOpen); ITPRINT2("%ws IsJournaling : %d\n", TabW, Replica->IsJournaling); ITPRINT2("%ws IsAccepting : %d\n", TabW, Replica->IsAccepting); ITPRINT2("%ws IsSeeding : %d\n", TabW, Replica->IsSeeding); ITPRINT2("%ws NeedsUpdate : %d\n", TabW, Replica->NeedsUpdate); ITPRINT3("%ws ServiceState : %d (%s)\n", TabW, Replica->ServiceState, RSS_NAME(Replica->ServiceState)); ITPRINT2("%ws FStatus : %s\n", TabW, ErrLabelFrs(Replica->FStatus)); ITPRINT2("%ws Number : %d\n", TabW, Replica->ReplicaNumber); ITPRINT2("%ws Root : %ws\n", TabW, Replica->Root); ITPRINT2("%ws Stage : %ws\n", TabW, Replica->Stage); ITPRINT2("%ws Volume : %ws\n", TabW, Replica->Volume); ITPRINT2("%ws FileFilter : %ws\n", TabW, Replica->FileFilterList); ITPRINT2("%ws DirFilter : %ws\n", TabW, Replica->DirFilterList); ITPRINT2("%ws Expires : %08x %08x\n", TabW, PRINTQUAD(Replica->MembershipExpires)); ITPRINT2("%ws InLogRetry : %d\n", TabW, Replica->InLogRetryCount); ITPRINT2("%ws InLogSeq : %d\n", TabW, Replica->InLogSeqNumber); ITPRINT2("%ws InLogSeq : %d\n", TabW, Replica->InLogSeqNumber); ITPRINT2("%ws ApiState : %d\n", TabW, Replica->NtFrsApi_ServiceState); ITPRINT2("%ws ApiStatus : %d\n", TabW, Replica->NtFrsApi_ServiceWStatus); ITPRINT2("%ws ApiHack : %d\n", TabW, Replica->NtFrsApi_HackCount); ITPRINT2("%ws OutLogSeq : %d\n", TabW, Replica->OutLogSeqNumber); ITPRINT2("%ws OutLogJLx : %d\n", TabW, Replica->OutLogJLx); ITPRINT2("%ws OutLogJTx : %d\n", TabW, Replica->OutLogJTx); ITPRINT2("%ws OutLogMax : %d\n", TabW, Replica->OutLogCOMax); ITPRINT2("%ws OutLogState : %d\n", TabW, Replica->OutLogWorkState); ITPRINT2("%ws OutLogVV's : %d\n", TabW, Replica->OutLogCountVVJoins); ITPRINT2("%ws OutLogClean : %d\n", TabW, Replica->OutLogDoCleanup); ITPRINT2("%ws PreinstallFID : %08x %08x\n", TabW, PRINTQUAD(Replica->PreInstallFid)); ITPRINT2("%ws InLogCommit : %08x %08x\n", TabW, PRINTQUAD(Replica->InlogCommitUsn)); ITPRINT2("%ws JrnlStart : %08x %08x\n", TabW, PRINTQUAD(Replica->JrnlRecoveryStart)); ITPRINT2("%ws JrnlEnd : %08x %08x\n", TabW, PRINTQUAD(Replica->JrnlRecoveryEnd)); ITPRINT2("%ws LastUsn : %08x %08x\n", TabW, PRINTQUAD(Replica->LastUsnRecordProcessed)); if (Replica->Schedule) { ITPRINT1("%ws Schedule\n", TabW); FrsPrintTypeSchedule(Severity, Info, Tabs + 3, Replica->Schedule, Debsub, uLineNo); } if (Replica->VVector) { ITPRINT1("%ws Version Vector\n", TabW); } if (!Info) { DebUnLock(); } FrsPrintTypeVv(Severity, Info, Tabs + 3, Replica->VVector, Debsub, uLineNo); FrsPrintTypeCxtions(Severity, Info, Tabs + 1, Replica->Cxtions, Debsub, uLineNo); } VOID FrsPrintType( IN ULONG Severity, IN PVOID Node, IN PCHAR Debsub, IN ULONG uLineNo ) /*++ Routine Description: This routine prints out the contents of a given node, performing any node specific interpretation. Arguments: Severity -- Severity level for print. (See debug.c, debug.h) Node - The address of the node to print. Debsub -- Name of calling subroutine. uLineno -- Line number of caller MACRO: FRS_PRINT_TYPE Return Value: none. --*/ { #undef DEBSUB #define DEBSUB "FrsPrintType:" ULONG NodeSize; ULONG NodeType; ULONG Marker; PREPLICA Replica; PREPLICA_THREAD_CTX RtCtx; PTABLE_CTX TableCtx; PTHREAD_CTX ThreadCtx; ULONG i; PVOLUME_MONITOR_ENTRY pVme; PFILTER_TABLE_ENTRY FilterEntry; PQHASH_TABLE QhashTable; PLIST_ENTRY Entry; PCXTION Cxtion; SYSTEMTIME ST; PWILDCARD_FILTER_ENTRY WildcardEntry; POUT_LOG_PARTNER Olp; PCONFIG_NODE ConfigNode; PULONG pULong; PCHANGE_ORDER_ENTRY CoEntry; PCHANGE_ORDER_COMMAND CoCmd; CHAR GuidStr[GUID_CHAR_LEN]; CHAR TimeStr[TIME_STRING_LENGTH]; CHAR FlagBuffer[160]; if (!DoDebug(Severity, Debsub)) { return; } // // Get debug lock so our output stays in one piece. // DebLock(); if (Node != NULL) { NodeType = (ULONG) (((PFRS_NODE_HEADER) Node)->Type); NodeSize = (ULONG) (((PFRS_NODE_HEADER) Node)->Size); FRS_DEB_PRINT("Display for Node: ...%s... === === === ===\n", NodeTypeNames[NodeType]); } else { FRS_DEB_PRINT("Display for Node: ...... === === === ===\n\n", NULL); DebUnLock(); return; } switch (NodeType) { // // Print a Thread Context struct // case THREAD_CONTEXT_TYPE: if (NodeSize != sizeof(THREAD_CTX)) { FRS_DEB_PRINT("FrsPrintType - Bad node size %d for THREAD_CONTEXT\n", NodeSize); break; } FRS_DEB_PRINT("Address %08x\n", Node); ThreadCtx = (PTHREAD_CTX) Node; break; // // Print a Replica struct // case REPLICA_TYPE: if (NodeSize != sizeof(REPLICA)) { FRS_DEB_PRINT("FrsPrintType - Bad node size %d for REPLICA\n", NodeSize); break; } DebUnLock(); FrsPrintTypeReplica(Severity, NULL, 0, (PREPLICA) Node, Debsub, uLineNo); DebLock(); break; // // Print a Replica Thread Context struct // case REPLICA_THREAD_TYPE: if (NodeSize != sizeof(REPLICA_THREAD_CTX)) { FRS_DEB_PRINT("FrsPrintType - Bad node size %d for REPLICA_THREAD_CTX\n", NodeSize); break; } FRS_DEB_PRINT("Address %08x\n", Node); RtCtx = (PREPLICA_THREAD_CTX) Node; // // Get the base of the array of TableCtx structs from the replica thread // context struct. // TableCtx = RtCtx->RtCtxTables; // // Release the memory for each table context struct. // //for (i=0; iName, L"\t", L"Node", Debsub, uLineNo); FrsPrintGNameForNode(Severity, ConfigNode->PartnerName, L"\t", L"Partner", Debsub, uLineNo); FRS_DEB_PRINT("\tDsObjectType %ws\n", DsConfigTypeName[ConfigNode->DsObjectType]); FRS_DEB_PRINT("\tConsistent %s\n", (ConfigNode->Consistent) ? "TRUE" : "FALSE"); FRS_DEB_PRINT("\tInbound %s\n", (ConfigNode->Inbound) ? "TRUE" : "FALSE"); FRS_DEB_PRINT("\tThisComputer %s\n", (ConfigNode->ThisComputer) ? "TRUE" : "FALSE"); FRS_DEB_PRINT("\tUsnChanged %ws\n", ConfigNode->UsnChanged); FRS_DEB_PRINT("\tDn %ws\n", ConfigNode->Dn); FRS_DEB_PRINT("\tPrincName %ws\n", ConfigNode->PrincName); FRS_DEB_PRINT("\tDnsName %ws\n", ConfigNode->DnsName); FRS_DEB_PRINT("\tPartnerDnsName %ws\n", ConfigNode->PartnerDnsName); FRS_DEB_PRINT("\tSid %ws\n", ConfigNode->Sid); FRS_DEB_PRINT("\tPartnerSid %ws\n", ConfigNode->PartnerSid); FRS_DEB_PRINT("\tPartnerDn %ws\n", ConfigNode->PartnerDn); FRS_DEB_PRINT("\tPartnerCoDn %ws\n", ConfigNode->PartnerCoDn); FRS_DEB_PRINT("\tSettingsDn %ws\n", ConfigNode->SettingsDn); FRS_DEB_PRINT("\tComputerDn %ws\n", ConfigNode->ComputerDn); FRS_DEB_PRINT("\tMemberDn %ws\n", ConfigNode->MemberDn); FRS_DEB_PRINT("\tSetType %ws\n", ConfigNode->SetType); FRS_DEB_PRINT("\tRoot %ws\n", ConfigNode->Root); FRS_DEB_PRINT("\tStage %ws\n", ConfigNode->Stage); FRS_DEB_PRINT("\tWorking %ws\n", ConfigNode->Working); FRS_DEB_PRINT("\tFileFilterList %ws\n", ConfigNode->FileFilterList); FRS_DEB_PRINT("\tDirFilterList %ws\n", ConfigNode->DirFilterList); FRS_DEB_PRINT("\tSchedule %08x\n",ConfigNode->Schedule); FRS_DEB_PRINT("\tScheduleLength %d\n", ConfigNode->ScheduleLength); FRS_DEB_PRINT("\tUsnChanged %ws\n", ConfigNode->UsnChanged); FRS_DEB_PRINT("\tSameSite %s\n", (ConfigNode->SameSite) ? "TRUE" : "FALSE"); FRS_DEB_PRINT("\tEnabledCxtion %ws\n", ConfigNode->EnabledCxtion); FRS_DEB_PRINT("\tVerifiedOverlap %s\n", (ConfigNode->VerifiedOverlap) ? "TRUE" : "FALSE"); break; // // Print a connection // case CXTION_TYPE: if (NodeSize != sizeof(CXTION)) { FRS_DEB_PRINT("FrsPrintType - Bad node size %d for CXTION\n", NodeSize); break; } DebUnLock(); FrsPrintTypeCxtion(Severity, NULL, 0, (PCXTION)Node, Debsub, uLineNo); DebLock(); break; // // Print a guid/rpc handle // case GHANDLE_TYPE: if (NodeSize != sizeof(GHANDLE)) { FRS_DEB_PRINT("FrsPrintType - Bad node size %d for GHANDLE\n", NodeSize); break; } GuidToStr(&(((PGHANDLE)Node)->Guid), GuidStr); FRS_DEB_PRINT2("Address %08x, Cxtion Guid : %s\n", Node, GuidStr); break; // // Print a generic table // case GEN_TABLE_TYPE: if (NodeSize != sizeof(GEN_TABLE)) { FRS_DEB_PRINT("FrsPrintType - Bad node size %d for GEN_TABLE\n", NodeSize); break; } FRS_DEB_PRINT("Address %08x\n", Node); break; // // Print a generic thread context // case THREAD_TYPE: if (NodeSize != sizeof(FRS_THREAD)) { FRS_DEB_PRINT("FrsPrintType - Bad node size %d for FRS_THREAD\n", NodeSize); break; } FRS_DEB_PRINT("Address %08x\n", Node); break; // // Print a journal read buffer. // case JBUFFER_TYPE: if (NodeSize != SizeOfJournalBuffer) { FRS_DEB_PRINT("FrsPrintType - Bad node size %d for JBUFFER\n", NodeSize); break; } FRS_DEB_PRINT("Address %08x\n", Node); break; // // Print a journal volume monitor entry. // case VOLUME_MONITOR_ENTRY_TYPE: if (NodeSize != sizeof(VOLUME_MONITOR_ENTRY)) { FRS_DEB_PRINT("FrsPrintType - Bad node size %d for VOLUME_MONITOR_ENTRY\n", NodeSize); break; } FRS_DEB_PRINT("Address %08x\n", Node); pVme = (PVOLUME_MONITOR_ENTRY) Node; break; // // Print a command packet. // case COMMAND_PACKET_TYPE: if (NodeSize != sizeof(COMMAND_PACKET)) { FRS_DEB_PRINT("FrsPrintType - Bad node size %d for COMMAND_PACKET\n", NodeSize); break; } FRS_DEB_PRINT("Address %08x\n", Node); break; // // Print a generic hash table struct. // case GENERIC_HASH_TABLE_TYPE: if (NodeSize != sizeof(GENERIC_HASH_TABLE)) { FRS_DEB_PRINT("FrsPrintType - Bad node size %d for GENERIC_HASH_TABLE\n", NodeSize); break; } FRS_DEB_PRINT("Address %08x\n", Node); break; // // Print a Change Order Entry struct. // case CHANGE_ORDER_ENTRY_TYPE: if (NodeSize != sizeof(CHANGE_ORDER_ENTRY)) { FRS_DEB_PRINT("FrsPrintType - Bad node size %d for CHANGE_ORDER_ENTRY\n", NodeSize); break; } CoEntry = (PCHANGE_ORDER_ENTRY)Node; CoCmd = &CoEntry->Cmd; GuidToStr(&CoCmd->ChangeOrderGuid, GuidStr); FRS_DEB_PRINT3("Address %08x ***%s CO*** - %s\n", CoEntry, (CO_FLAG_ON(CoEntry, CO_FLAG_LOCALCO)) ? "LOCAL" : "REMOTE", GuidStr); FRS_DEB_PRINT3("Node Addr: %08x, HashValue: %08x RC: %d\n", CoEntry, CoEntry->HashEntryHeader.HashValue, CoEntry->HashEntryHeader.ReferenceCount); FRS_DEB_PRINT2("List Entry - %08x, %08x\n", CoEntry->HashEntryHeader.ListEntry.Flink, CoEntry->HashEntryHeader.ListEntry.Blink); FRS_DEB_PRINT2("FileRef: %08lx %08lx, ParentRef: %08lx %08lx\n", PRINTQUAD(CoEntry->FileReferenceNumber), PRINTQUAD(CoEntry->ParentFileReferenceNumber)); FRS_DEB_PRINT("\n", NULL); FRS_DEB_PRINT("STATE: %s\n", PRINT_CO_STATE(CoEntry)); FrsFlagsToStr(CoEntry->EntryFlags, CoeFlagNameTable, sizeof(FlagBuffer), FlagBuffer); FRS_DEB_PRINT2("EntryFlags: %08x, Flags [%s]\n", CoEntry->EntryFlags, FlagBuffer); FrsFlagsToStr(CoEntry->IssueCleanup, IscuFlagNameTable, sizeof(FlagBuffer), FlagBuffer); FRS_DEB_PRINT2("ISCU Flags: %08x, Flags [%s]\n", CoEntry->IssueCleanup, FlagBuffer); FRS_DEB_PRINT("\n", NULL); GuidToStr(&CoCmd->OriginatorGuid, GuidStr); FRS_DEB_PRINT("OrigGuid : %s\n", GuidStr); GuidToStr(&CoCmd->FileGuid, GuidStr); FRS_DEB_PRINT("FileGuid : %s\n", GuidStr); GuidToStr(&CoCmd->OldParentGuid, GuidStr); FRS_DEB_PRINT("OParGuid : %s\n",GuidStr); GuidToStr(&CoCmd->NewParentGuid, GuidStr); FRS_DEB_PRINT("NParGuid : %s\n", GuidStr); GuidToStr(&CoCmd->CxtionGuid, GuidStr); FRS_DEB_PRINT2("CxtionGuid: %s (%08x)\n", GuidStr, CoEntry->Cxtion); FileTimeToString((PFILETIME) &CoCmd->AckVersion, TimeStr); FRS_DEB_PRINT("AckVersion: %s\n", TimeStr); FRS_DEB_PRINT("\n", NULL); FRS_DEB_PRINT2("FileName: %ws, Length: %d\n", CoEntry->UFileName.Buffer, CoCmd->FileNameLength); FrsFlagsToStr(CoCmd->ContentCmd, UsnReasonNameTable, sizeof(FlagBuffer), FlagBuffer); FRS_DEB_PRINT2("ContentCmd: %08x, Flags [%s]\n", CoCmd->ContentCmd, FlagBuffer); FRS_DEB_PRINT("\n", NULL); FrsFlagsToStr(CoCmd->Flags, CoFlagNameTable, sizeof(FlagBuffer), FlagBuffer); FRS_DEB_PRINT2("CoFlags: %08x, Flags [%s]\n", CoCmd->Flags, FlagBuffer); FrsFlagsToStr(CoCmd->IFlags, CoIFlagNameTable, sizeof(FlagBuffer), FlagBuffer); DebPrintNoLock(Severity, TRUE, "IFlags: %08x, Flags [%s] TimeToRun: %7d, EntryCreateTime: %7d\n", Debsub, uLineNo, CoCmd->IFlags, FlagBuffer, CoEntry->TimeToRun, CoEntry->EntryCreateTime); DebPrintNoLock(Severity, TRUE, "LocationCmd: %s (%d), CO STATE: %s File/Dir: %d\n", Debsub, uLineNo, CoLocationNames[GET_CO_LOCATION_CMD(CoEntry->Cmd, Command)], GET_CO_LOCATION_CMD(CoEntry->Cmd, Command), PRINT_CO_STATE(CoEntry), GET_CO_LOCATION_CMD(CoEntry->Cmd, DirOrFile)); FRS_DEB_PRINT("\n", NULL); FRS_DEB_PRINT2("OriginalParentFid: %08lx %08lx, NewParentFid: %08lx %08lx\n", PRINTQUAD(CoEntry->OriginalParentFid), PRINTQUAD(CoEntry->NewParentFid)); DebPrintNoLock(Severity, TRUE, "OriginalReplica: %ws (%d), NewReplica: %ws (%d)\n", Debsub, uLineNo, CoEntry->OriginalReplica->ReplicaName->Name, CoCmd->OriginalReplicaNum, CoEntry->NewReplica->ReplicaName->Name, CoCmd->NewReplicaNum); if (CoCmd->Extension != NULL) { pULong = (PULONG) CoCmd->Extension; DebPrintNoLock(Severity, TRUE, "CO Extension: (%08x) %08x %08x %08x %08x %08x %08x %08x %08x\n", Debsub, uLineNo, pULong, *(pULong+0), *(pULong+1), *(pULong+2), *(pULong+3), *(pULong+4), *(pULong+5), *(pULong+6), *(pULong+7)); } else { FRS_DEB_PRINT("CO Extension: Null\n", NULL); } FRS_DEB_PRINT("\n", NULL); FRS_DEB_PRINT3("File Attributes: %08x, SeqNum: %08x, FileSize: %08x %08x\n", CoCmd->FileAttributes, CoCmd->SequenceNumber, PRINTQUAD(CoCmd->FileSize)); FRS_DEB_PRINT("FrsVsn: %08x %08x\n", PRINTQUAD(CoCmd->FrsVsn)); FRS_DEB_PRINT3("Usn: %08x %08x CoFileUsn: %08x %08x JrnlFirstUsn: %08x %08x\n", PRINTQUAD(CoCmd->JrnlUsn), PRINTQUAD(CoCmd->FileUsn), PRINTQUAD(CoCmd->JrnlFirstUsn)); FRS_DEB_PRINT("Version: %08x ", CoCmd->FileVersionNumber); FileTimeToString((PFILETIME) &CoCmd->EventTime.QuadPart, TimeStr); DebPrintNoLock(Severity, FALSE, "EventTime: %s\n", Debsub, uLineNo, TimeStr); break; // // Print a Filter Table Entry struct. // case FILTER_TABLE_ENTRY_TYPE: if (NodeSize != sizeof(FILTER_TABLE_ENTRY)) { FRS_DEB_PRINT("FrsPrintType - Bad node size %d for FILTER_TABLE_ENTRY\n", NodeSize); break; } FRS_DEB_PRINT("Address %08x\n", Node); FilterEntry = (PFILTER_TABLE_ENTRY)Node; break; // // Print a QHASH table struct. // case QHASH_TABLE_TYPE: QhashTable = (PQHASH_TABLE)Node; if (NodeSize != QhashTable->BaseAllocSize) { FRS_DEB_PRINT("FrsPrintType - Bad node size %d for QHASH_TABLE\n", NodeSize); break; } FRS_DEB_PRINT("Table Address : %08x\n", QhashTable); FRS_DEB_PRINT("BaseAllocSize : %8d\n", QhashTable->BaseAllocSize); FRS_DEB_PRINT("ExtensionAllocSize : %8d\n", QhashTable->ExtensionAllocSize); FRS_DEB_PRINT("ExtensionListHead : %08x\n", QhashTable->ExtensionListHead); FRS_DEB_PRINT("FreeList : %08x\n", QhashTable->FreeList); FRS_DEB_PRINT("Lock : %08x\n", QhashTable->Lock); FRS_DEB_PRINT("HeapHandle : %08x\n", QhashTable->HeapHandle); FRS_DEB_PRINT("HashCalc : %08x\n", QhashTable->HashCalc); FRS_DEB_PRINT("NumberEntries : %8d\n", QhashTable->NumberEntries); FRS_DEB_PRINT("HashRowBase : %08x\n", QhashTable->HashRowBase); break; // // Print an Output Log Partner struct. // case OUT_LOG_PARTNER_TYPE: if (NodeSize != sizeof(OUT_LOG_PARTNER)) { FRS_DEB_PRINT("FrsPrintType - Bad node size %d for OUT_LOG_PARTNER\n", NodeSize); break; } DebUnLock(); FrsPrintTypeOutLogPartner(Severity, NULL, 0, (POUT_LOG_PARTNER)Node, -1, "FrsPrintType", Debsub, uLineNo); DebLock(); break; // // Print a Wildcard file filter Entry struct. // case WILDCARD_FILTER_ENTRY_TYPE: if (NodeSize != sizeof(WILDCARD_FILTER_ENTRY)) { FRS_DEB_PRINT("FrsPrintType - Bad node size %d for WILDCARD_FILTER_ENTRY\n", NodeSize); break; } FRS_DEB_PRINT( "Address %08x\n", Node); WildcardEntry = (PWILDCARD_FILTER_ENTRY)Node; DebPrintNoLock(Severity, TRUE, "Flags: %08x, Wildcard FileName: %ws, Length: %d\n", Debsub, uLineNo, WildcardEntry->Flags, WildcardEntry->UFileName.Buffer, (ULONG)WildcardEntry->UFileName.Length); break; // // Invalid Node Type // default: Node = NULL; DebPrintNoLock(0, TRUE, "Internal error - invalid node type - %d\n", Debsub, uLineNo, NodeType); } FRS_DEB_PRINT("-----------------------\n", NULL); DebUnLock(); } VOID FrsAllocUnicodeString( PUNICODE_STRING Ustr, PWCHAR InternalBuffer, PWCHAR Wstr, USHORT WstrLength ) /*++ Routine Description: Initialize a unicode string with the contents of Wstr if the two are not already the same. If the length of the new string is greater than the buffer space currently allocated in Ustr then allocate a new buffer for Ustr. In some structures the initial Ustr buffer allocation is allocated as part of the initial structure allocation. The address of this internal buffer is passed so it can be compared with the address in Ustr->Buffer. If they match then no free memory call is made on the Ustr->Buffer address. Arguments: Ustr -- The UNICODE_STRING to init. InternalBuffer -- A ptr to the internal buffer address that was preallocated with the containing struct. If there was no internal buffer pass NULL. Wstr -- The new WCHAR string. WstrLength -- The length of the new string in bytes not including the trailing UNICODE_NULL. Return Value: None. --*/ { #undef DEBSUB #define DEBSUB "FrsAllocUnicodeString:" // // See if the name part changed and if so save it. // if ((Ustr->Length != WstrLength) || (wcsncmp(Ustr->Buffer, Wstr, Ustr->Length/sizeof(WCHAR)) != 0)) { // // If string to big (including space for a NULL), alloc new buffer. // if (WstrLength >= Ustr->MaximumLength) { // // Alloc room for new one, freeing the old one if not internal alloc. // if ((Ustr->Buffer != InternalBuffer) && (Ustr->Buffer != NULL)) { FrsFree(Ustr->Buffer); } Ustr->MaximumLength = WstrLength+2; Ustr->Buffer = FrsAlloc(WstrLength+2); } // // Copy in new name. Length does not include the trailing NULL at end. // CopyMemory(Ustr->Buffer, Wstr, WstrLength); Ustr->Buffer[WstrLength/2] = UNICODE_NULL; Ustr->Length = WstrLength; } } #define CO_TRACE_FORMAT ":: CoG %08x, CxtG %08x, FV %5d, FID %08x %08x, FN: %-15ws, [%s]\n" #define REPLICA_TRACE_FORMAT ":S:Adr %08x, Cmd %04x, Flg %04x, %ws (%d), %s, Err %d [%s]\n" #define REPLICA_TRACE_FORMAT2 ":S:Adr %08x, %ws (%d), %s, [%s]\n" #define CXTION_TRACE_FORMAT ":X: %08x, Nam %ws, Sta %s%s, %ws (%d), %s, Err %d [%s]\n" VOID ChgOrdTraceCoe( IN ULONG Severity, IN PCHAR Debsub, IN ULONG uLineNo, IN PCHANGE_ORDER_ENTRY Coe, IN PCHAR Text ) /*++ Routine Description: Print a change order trace record using the change order entry and the Text string. Arguments: Return Value: None --*/ { #undef DEBSUB #define DEBSUB "ChgOrdTraceCoe:" ULONGLONG FileRef; FileRef = (Coe != NULL) ? Coe->FileReferenceNumber : QUADZERO; DebPrint(Severity, (PUCHAR) CO_TRACE_FORMAT, Debsub, uLineNo, (Coe != NULL) ? Coe->Cmd.ChangeOrderGuid.Data1 : 0, (Coe != NULL) ? Coe->Cmd.CxtionGuid.Data1 : 0, (Coe != NULL) ? Coe->Cmd.FileVersionNumber : 0, PRINTQUAD(FileRef), (Coe != NULL) ? Coe->Cmd.FileName : L"", Text); } VOID ChgOrdTraceCoeW( IN ULONG Severity, IN PCHAR Debsub, IN ULONG uLineNo, IN PCHANGE_ORDER_ENTRY Coe, IN PCHAR Text, IN ULONG WStatus ) /*++ Routine Description: Print a change order trace record using the change order entry and the Text string and Win32 status. Arguments: Return Value: None --*/ { #undef DEBSUB #define DEBSUB "ChgOrdTraceCoeW:" CHAR Tstr[256]; _snprintf(Tstr, sizeof(Tstr), "%s (%s)", Text, ErrLabelW32(WStatus)); Tstr[sizeof(Tstr)-1] = '\0'; ChgOrdTraceCoe(Severity, Debsub, uLineNo, Coe, Tstr); } VOID ChgOrdTraceCoeF( IN ULONG Severity, IN PCHAR Debsub, IN ULONG uLineNo, IN PCHANGE_ORDER_ENTRY Coe, IN PCHAR Text, IN ULONG FStatus ) /*++ Routine Description: Print a change order trace record using the change order entry and the Text string and Frs Error status. Arguments: Return Value: None --*/ { #undef DEBSUB #define DEBSUB "ChgOrdTraceCoeF:" CHAR Tstr[128]; _snprintf(Tstr, sizeof(Tstr), "%s (%s)", Text, ErrLabelFrs(FStatus)); Tstr[sizeof(Tstr)-1] = '\0'; ChgOrdTraceCoe(Severity, Debsub, uLineNo, Coe, Tstr); } VOID ChgOrdTraceCoeX( IN ULONG Severity, IN PCHAR Debsub, IN ULONG uLineNo, IN PCHANGE_ORDER_ENTRY Coe, IN PCHAR Text, IN ULONG Data ) /*++ Routine Description: Print a change order trace record using the change order entry and the Text string and Win32 status. Arguments: Return Value: None --*/ { #undef DEBSUB #define DEBSUB "ChgOrdTraceCoeX:" CHAR Tstr[256]; _snprintf(Tstr, sizeof(Tstr), "%s (%08x)", Text, Data); Tstr[sizeof(Tstr)-1] = '\0'; ChgOrdTraceCoe(Severity, Debsub, uLineNo, Coe, Tstr); } VOID ChgOrdTraceCoc( IN ULONG Severity, IN PCHAR Debsub, IN ULONG uLineNo, IN PCHANGE_ORDER_COMMAND Coc, IN PCHAR Text ) /*++ Routine Description: Print a change order trace record using the change order command and the Text string. Arguments: Return Value: None --*/ { #undef DEBSUB #define DEBSUB "ChgOrdTraceCoc:" ULONGLONG FileRef = QUADZERO; DebPrint(Severity, (PUCHAR) CO_TRACE_FORMAT, Debsub, uLineNo, (Coc != NULL) ? Coc->ChangeOrderGuid.Data1 : 0, (Coc != NULL) ? Coc->CxtionGuid.Data1 : 0, (Coc != NULL) ? Coc->FileVersionNumber : 0, PRINTQUAD(FileRef), (Coc != NULL) ? Coc->FileName : L"", Text); } VOID ChgOrdTraceCocW( IN ULONG Severity, IN PCHAR Debsub, IN ULONG uLineNo, IN PCHANGE_ORDER_COMMAND Coc, IN PCHAR Text, IN ULONG WStatus ) /*++ Routine Description: Print a change order trace record using the change order command and the Text string and Win32 status. Arguments: Return Value: None --*/ { #undef DEBSUB #define DEBSUB "ChgOrdTraceCocW:" CHAR Tstr[256]; _snprintf(Tstr, sizeof(Tstr), "%s (%s)", Text, ErrLabelW32(WStatus)); Tstr[sizeof(Tstr)-1] = '\0'; ChgOrdTraceCoc(Severity, Debsub, uLineNo, Coc, Tstr); } VOID ReplicaStateTrace( IN ULONG Severity, IN PCHAR Debsub, IN ULONG uLineNo, IN PCOMMAND_PACKET Cmd, IN PREPLICA Replica, IN ULONG Status, IN PCHAR Text ) /*++ Routine Description: Print a replica state trace record using the command packet and the status and Text string. Arguments: Return Value: None --*/ { #undef DEBSUB #define DEBSUB "ReplicaStateTrace:" PWSTR ReplicaName; if ((Replica != NULL) && (Replica->ReplicaName != NULL) && (Replica->ReplicaName->Name != NULL)) { ReplicaName = Replica->ReplicaName->Name; } else { ReplicaName = L""; } DebPrint(Severity, (PUCHAR) REPLICA_TRACE_FORMAT, Debsub, uLineNo, PtrToUlong(Cmd), (Cmd != NULL) ? Cmd->Command : 0xFFFF, (Cmd != NULL) ? Cmd->Flags : 0xFFFF, ReplicaName, ReplicaAddrToId(Replica), (Replica != NULL) ? RSS_NAME(Replica->ServiceState) : "", Status, Text); } VOID ReplicaStateTrace2( IN ULONG Severity, IN PCHAR Debsub, IN ULONG uLineNo, IN PREPLICA Replica, IN PCHAR Text ) /*++ Routine Description: Print a cxtion table access trace record for the replica using the Text string. Arguments: Return Value: None --*/ { #undef DEBSUB #define DEBSUB "ReplicaStateTrace2:" PWSTR ReplicaName; if ((Replica != NULL) && (Replica->ReplicaName != NULL) && (Replica->ReplicaName->Name != NULL)) { ReplicaName = Replica->ReplicaName->Name; } else { ReplicaName = L""; } DebPrint(Severity, (PUCHAR) REPLICA_TRACE_FORMAT2, Debsub, uLineNo, PtrToUlong(Replica), ReplicaName, ReplicaAddrToId(Replica), (Replica != NULL) ? RSS_NAME(Replica->ServiceState) : "", Text); } VOID CxtionStateTrace( IN ULONG Severity, IN PCHAR Debsub, IN ULONG uLineNo, IN PCXTION Cxtion, IN PREPLICA Replica, IN ULONG Status, IN PCHAR Text ) /*++ Routine Description: Print a connection state trace record using the cxtion and the status and Text string. Arguments: Return Value: None --*/ { #undef DEBSUB #define DEBSUB "CxtionStateTrace:" PWSTR ReplicaName = L""; PWSTR CxtName = L""; PCHAR CxtState = ""; ULONG Ctxg = 0, Flags = 0; PCHAR CxtDirection = "?-"; CHAR FBuf[120]; if ((Replica != NULL) && (Replica->ReplicaName != NULL) && (Replica->ReplicaName->Name != NULL)) { ReplicaName = Replica->ReplicaName->Name; } if (Cxtion != NULL) { Flags = Cxtion->Flags; CxtState = CxtionStateNames[GetCxtionState(Cxtion)]; CxtDirection = Cxtion->Inbound ? "I-" : "O-"; if (Cxtion->Name != NULL) { if (Cxtion->Name->Name != NULL) { CxtName = Cxtion->Name->Name; } if (Cxtion->Name->Guid != NULL) { Ctxg = Cxtion->Name->Guid->Data1; } } } DebPrint(Severity, (PUCHAR) CXTION_TRACE_FORMAT, Debsub, uLineNo, Ctxg, CxtName, CxtDirection, CxtState, ReplicaName, ReplicaAddrToId(Replica), (Replica != NULL) ? RSS_NAME(Replica->ServiceState) : "", Status, Text); FrsFlagsToStr(Flags, CxtionFlagNameTable, sizeof(FBuf), FBuf); DebPrint(Severity, (PUCHAR) ":X: %08x, Flags [%s]\n", Debsub, uLineNo, Ctxg, FBuf); } VOID CmdPktTrace( IN ULONG Severity, IN PCHAR Debsub, IN ULONG uLineNo, IN PCOMMAND_PACKET Cmd, IN PCHAR Text ) /*++ Routine Description: Print a command packet trace record using the Cmd and Text string. Arguments: Return Value: None --*/ { #undef DEBSUB #define DEBSUB "CmdPktTrace:" ULONG CmdCode = 0, Flags = 0, Ctrl = 0, Tout = 0, TQ = 0, Err = 0; if (Cmd != NULL) { CmdCode = (ULONG) Cmd->Command; Flags = (ULONG) Cmd->Flags; Ctrl = (ULONG) Cmd->Control; Tout = Cmd->Timeout; TQ = PtrToUlong(Cmd->TargetQueue); Err = Cmd->ErrorStatus; } DebPrint(Severity, (PUCHAR) ":Cd: %08x, Cmd %04x, Flg %04x, Ctrl %04x, Tout %08x, TQ %08x, Err %d [%s]\n", Debsub, uLineNo, PtrToUlong(Cmd), CmdCode, Flags, Ctrl, Tout, TQ, Err, Text); } VOID SendCmdTrace( IN ULONG Severity, IN PCHAR Debsub, IN ULONG uLineNo, IN PCOMMAND_PACKET Cmd, IN ULONG WStatus, IN PCHAR Text ) /*++ Routine Description: Print a send command packet trace record using the Cmd and the status and Text string. Arguments: Return Value: None --*/ { #undef DEBSUB #define DEBSUB "SendCmdTrace:" PCXTION Cxtion; PWSTR CxtTo = L""; ULONG Ctxg = 0, PktLen = 0; if (Cmd != NULL) { Cxtion = SRCxtion(Cmd); if ((Cxtion != NULL) && (Cxtion->Name != NULL) && (Cxtion->Name->Guid != NULL)) { Ctxg = Cxtion->Name->Guid->Data1; } if (SRCommPkt(Cmd) != NULL) { PktLen = SRCommPkt(Cmd)->PktLen; } if ((SRTo(Cmd) != NULL) && (SRTo(Cmd)->Name != NULL)) { CxtTo = SRTo(Cmd)->Name; } } DebPrint(Severity, (PUCHAR) ":SR: Cmd %08x, CxtG %08x, WS %s, To %ws Len: (%3d) [%s]\n", Debsub, uLineNo, PtrToUlong(Cmd), Ctxg, ErrLabelW32(WStatus), CxtTo, PktLen, Text); } VOID ReceiveCmdTrace( IN ULONG Severity, IN PCHAR Debsub, IN ULONG uLineNo, IN PCOMMAND_PACKET Cmd, IN PCXTION Cxtion, IN ULONG WStatus, IN PCHAR Text ) /*++ Routine Description: Print a rcv command packet trace record using the Cmd and the status and Text string. Arguments: Return Value: None --*/ { #undef DEBSUB #define DEBSUB "ReceiveCmdTrace:" PWSTR CxtFrom = L""; ULONG Ctxg = 0, PktLen = 0, CmdCode = 0; if (Cmd != NULL) { CmdCode = (ULONG) Cmd->Command; if (Cxtion != NULL) { CxtFrom = Cxtion->PartnerDnsName; if ((Cxtion->Name != NULL) && (Cxtion->Name->Guid != NULL)) { Ctxg = Cxtion->Name->Guid->Data1; } } } DebPrint(Severity, (PUCHAR) ":SR: Cmd %08x, CxtG %08x, WS %s, From %ws CCod: (%03x) [%s]\n", Debsub, uLineNo, PtrToUlong(Cmd), Ctxg, ErrLabelW32(WStatus), CxtFrom, CmdCode, Text); } VOID StageFileTrace( IN ULONG Severity, IN PCHAR Debsub, IN ULONG uLineNo, IN GUID *CoGuid, IN PWCHAR FileName, IN PULONGLONG pFileSize, IN PULONG pFlags, IN PCHAR Text ) /*++ Routine Description: Print a stage file acquire/release trace record. Arguments: Return Value: None --*/ { #undef DEBSUB #define DEBSUB "StageFileTrace:" ULONGLONG FileSize = QUADZERO; ULONG Flags = 0, CoGuidData = 0; CHAR FBuf[120]; Flags = (pFlags != NULL) ? *pFlags : 0; CoGuidData = (CoGuid != NULL) ? CoGuid->Data1 : 0; pFileSize = (pFileSize == NULL) ? &FileSize : pFileSize; DebPrint(Severity, (PUCHAR) ":: CoG %08x, Flgs %08x, %5d, Siz %08x %08x, FN: %-15ws, [%s]\n", Debsub, uLineNo, CoGuidData, Flags, 0, PRINTQUAD(*pFileSize), FileName, Text); FrsFlagsToStr(Flags, StageFlagNameTable, sizeof(FBuf), FBuf); DebPrint(Severity, (PUCHAR) ":: CoG %08x, Flags [%s]\n", Debsub, uLineNo, CoGuidData, FBuf); } VOID SetCxtionStateTrace( IN ULONG Severity, IN PCHAR Debsub, IN ULONG uLineNo, IN PCXTION Cxtion, IN ULONG NewState ) /*++ Routine Description: Print a change to cxtion state trace record using the Cxtion and the NewState. Arguments: Return Value: None --*/ { #undef DEBSUB #define DEBSUB "SetCxtionStateTrace:" PWSTR CxtName = L""; PWSTR PartnerName = L""; PWSTR PartSrvName = L""; PCHAR CxtionState = ""; ULONG Ctxg = 0; PCHAR CxtDirection = "?-"; if (Cxtion != NULL) { CxtionState = CxtionStateNames[Cxtion->State]; if (Cxtion->Name != NULL) { if (Cxtion->Name->Guid != NULL) { Ctxg = Cxtion->Name->Guid->Data1; } if (Cxtion->Name->Name != NULL) { CxtName = Cxtion->Name->Name; } } CxtDirection = Cxtion->Inbound ? "<-" : "->"; if ((Cxtion->Partner != NULL) && (Cxtion->Partner->Name != NULL)) { PartnerName = Cxtion->Partner->Name; } if (Cxtion->PartSrvName != NULL) { PartSrvName = Cxtion->PartSrvName; } } DebPrint(Severity, (PUCHAR) ":X: %08x, state change from %s to %s for %ws %s %ws\\%ws\n", Debsub, uLineNo, Ctxg, CxtionState, CxtionStateNames[NewState], CxtName, CxtDirection, PartnerName, PartSrvName); } #define FRS_TRACK_FORMAT_1 ":T: CoG: %08x CxtG: %08x [%-15s] Name: %ws\n" #define FRS_TRACK_FORMAT_2 ":T: EventTime: %-40s Ver: %d\n" #define FRS_TRACK_FORMAT_3 ":T: FileG: %-40s FID: %08x %08x\n" #define FRS_TRACK_FORMAT_4 ":T: ParentG: %-40s Size: %08x %08x\n" #define FRS_TRACK_FORMAT_5 ":T: OrigG: %-40s Attr: %08x\n" #define FRS_TRACK_FORMAT_6 ":T: LocnCmd: %-8s State: %-24s ReplicaName: %ws (%d)\n" #define FRS_TRACK_FORMAT_7 ":T: CoFlags: %08x [%s]\n" #define FRS_TRACK_FORMAT_8 ":T: UsnReason: %08x [%s]\n" VOID FrsTrackRecord( IN ULONG Severity, IN PCHAR Debsub, IN ULONG uLineNo, IN PCHANGE_ORDER_ENTRY Coe, IN PCHAR Text ) /*++ Routine Description: Print a change order file update tracking record using the change order entry and Text string. 7/29-13:40:58 :T: CoG: 779800ea CxtG: 000001bb [RemCo ] Name: Thous_5555_988 7/29-13:40:58 :T: EventTime: Sat Jul 29, 2000 12:05:57 Ver: 0 7/29-13:40:58 :T: FileG: b49362c3-216d-4ff4-a2d067fd031e436f FID 00050000 0000144e 7/29-13:40:58 :T: ParG: 8d60157a-7dc6-4dfc-acf3eca3c6e4d5d8 Size: 00000000 00000030 7/29-13:40:58 :T: OrigG: 8071d94a-a659-4ff7-a9467d8d6ad18aec Attr: 00000020 7/29-13:40:58 :T: LocnCmd: Create State: IBCO_INSTALL_DEL_RETRY ReplicaName: Replica-A (1) 7/29-13:40:58 :T: COFlags 7/29-13:40:58 :T: UsnReason: 00000002 [DatExt ] Arguments: Return Value: None --*/ { #undef DEBSUB #define DEBSUB "FrsTrackRecord:" PCHANGE_ORDER_COMMAND CoCmd; CHAR FlagBuffer[160]; CHAR GuidStr1[GUID_CHAR_LEN]; CHAR TimeStr[TIME_STRING_LENGTH]; if (!DoDebug(Severity, Debsub) || (Coe == NULL) || (Text == NULL)) { return; } // // Get debug lock so our output stays in one piece. // DebLock(); CoCmd = &Coe->Cmd; DebPrintTrackingNoLock(Severity, (PUCHAR) FRS_TRACK_FORMAT_1, CoCmd->ChangeOrderGuid.Data1, CoCmd->CxtionGuid.Data1, Text, CoCmd->FileName); FileTimeToString((PFILETIME) &CoCmd->EventTime.QuadPart, TimeStr); DebPrintTrackingNoLock(Severity, (PUCHAR) FRS_TRACK_FORMAT_2, TimeStr, CoCmd->FileVersionNumber); GuidToStr(&CoCmd->FileGuid, GuidStr1); DebPrintTrackingNoLock(Severity, (PUCHAR) FRS_TRACK_FORMAT_3, GuidStr1, PRINTQUAD(Coe->FileReferenceNumber)); GuidToStr(&CoCmd->NewParentGuid, GuidStr1); DebPrintTrackingNoLock(Severity, (PUCHAR) FRS_TRACK_FORMAT_4, GuidStr1, PRINTQUAD(CoCmd->FileSize)); GuidToStr(&CoCmd->OriginatorGuid, GuidStr1); DebPrintTrackingNoLock(Severity, (PUCHAR) FRS_TRACK_FORMAT_5, GuidStr1, CoCmd->FileAttributes); DebPrintTrackingNoLock(Severity, (PUCHAR) FRS_TRACK_FORMAT_6, CoLocationNames[GET_CO_LOCATION_CMD(Coe->Cmd, Command)], PRINT_CO_STATE(Coe), Coe->NewReplica->ReplicaName->Name, CoCmd->NewReplicaNum); FrsFlagsToStr(CoCmd->Flags, CoFlagNameTable, sizeof(FlagBuffer), FlagBuffer); DebPrintTrackingNoLock(Severity, (PUCHAR) FRS_TRACK_FORMAT_7, CoCmd->Flags, FlagBuffer); FrsFlagsToStr(CoCmd->ContentCmd, UsnReasonNameTable, sizeof(FlagBuffer), FlagBuffer); DebPrintTrackingNoLock(Severity, (PUCHAR) FRS_TRACK_FORMAT_8, CoCmd->ContentCmd, FlagBuffer); #if 0 FrsFlagsToStr(CoEntry->EntryFlags, CoeFlagNameTable, sizeof(FlagBuffer), FlagBuffer); FRS_DEB_PRINT2("EntryFlags: %08x, Flags [%s]\n", CoEntry->EntryFlags, FlagBuffer); FrsFlagsToStr(CoEntry->IssueCleanup, IscuFlagNameTable, sizeof(FlagBuffer), FlagBuffer); FRS_DEB_PRINT2("ISCU Flags: %08x, Flags [%s]\n", CoEntry->IssueCleanup, FlagBuffer); FrsFlagsToStr(CoCmd->IFlags, CoIFlagNameTable, sizeof(FlagBuffer), FlagBuffer); DebPrintNoLock(Severity, TRUE, "IFlags: %08x, Flags [%s] TimeToRun: %7d, EntryCreateTime: %7d\n", Debsub, uLineNo, CoCmd->IFlags, FlagBuffer, CoEntry->TimeToRun, CoEntry->EntryCreateTime); if (CoCmd->Extension != NULL) { pULong = (PULONG) CoCmd->Extension; DebPrintNoLock(Severity, TRUE, "CO Extension: (%08x) %08x %08x %08x %08x %08x %08x %08x %08x\n", Debsub, uLineNo, pULong, *(pULong+0), *(pULong+1), *(pULong+2), *(pULong+3), *(pULong+4), *(pULong+5), *(pULong+6), *(pULong+7)); } else { FRS_DEB_PRINT("CO Extension: Null\n", NULL); } FRS_DEB_PRINT("FrsVsn: %08x %08x\n", PRINTQUAD(CoCmd->FrsVsn)); FRS_DEB_PRINT3("Usn: %08x %08x CoFileUsn: %08x %08x JrnlFirstUsn: %08x %08x\n", PRINTQUAD(CoCmd->JrnlUsn), PRINTQUAD(CoCmd->FileUsn), PRINTQUAD(CoCmd->JrnlFirstUsn)); #endif DebUnLock(); } VOID FrsPrintLongUStr( IN ULONG Severity, IN PCHAR Debsub, IN ULONG uLineNo, IN PWCHAR UStr ) /*++ Routine Description: Print a long unicode string on multiple lines. Arguments: Return Value: None --*/ { #undef DEBSUB #define DEBSUB "FrsPrintLongUStr:" ULONG i, j, Len; WCHAR Usave; if (!DoDebug(Severity, Debsub) || (UStr == NULL)) { return; } // // Get debug lock so our output stays in one piece. // DebLock(); Len = wcslen(UStr); i = 0; j = 0; while (i < Len) { i += 60; if (i > Len) { i = Len; } Usave = UStr[i]; UStr[i] = UNICODE_NULL; FRS_DEB_PRINT("++ %ws\n", &UStr[j]); UStr[i] = Usave; j = i; } DebUnLock(); }