mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4810 lines
121 KiB
4810 lines
121 KiB
/*++
|
|
|
|
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 <ntreppch.h>
|
|
#pragma hdrstop
|
|
|
|
#undef DEBSUB
|
|
#define DEBSUB "FRSALLOC:"
|
|
|
|
#include <frs.h>
|
|
#include <ntfrsapi.h>
|
|
#include <info.h>
|
|
#include <perrepsr.h>
|
|
|
|
#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; i<TABLE_TYPE_MAX; ++i, ++TableCtx) {
|
|
//
|
|
// Marking the TableType as INVALID causes DbsAllocTableCtx()
|
|
// to allocate the DB support structs on the first call.
|
|
//
|
|
TableCtx->TableType = 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; i<TABLE_TYPE_MAX; ++i, ++TableCtx)
|
|
DbsFreeTableCtx(TableCtx, NodeType);
|
|
|
|
break;
|
|
|
|
//
|
|
// Free a topology node
|
|
//
|
|
case CONFIG_NODE_TYPE:
|
|
if (NodeSize != sizeof(CONFIG_NODE)) {
|
|
DPRINT1(0, "FrsFree - Bad node size %d for CONFIG_NODE\n", NodeSize);
|
|
XRAISEGENEXCEPTION(FrsErrorInternalError);
|
|
}
|
|
ConfigNode = (PCONFIG_NODE) Node;
|
|
FrsFreeGName(ConfigNode->Name);
|
|
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: ...<null>... === === === ===\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; i<TABLE_TYPE_MAX; ++i, ++TableCtx) {
|
|
//}
|
|
|
|
break;
|
|
|
|
//
|
|
// Print a topology node
|
|
//
|
|
case CONFIG_NODE_TYPE:
|
|
if (NodeSize != sizeof(CONFIG_NODE)) {
|
|
FRS_DEB_PRINT("FrsPrintType - Bad node size %d for CONFIG_NODE\n",
|
|
NodeSize);
|
|
break;
|
|
}
|
|
ConfigNode = Node;
|
|
FRS_DEB_PRINT("CONFIG NODE Address %08x\n", ConfigNode);
|
|
|
|
FrsPrintGNameForNode(Severity, ConfigNode->Name, 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"<Null Coe>",
|
|
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"<Null Coc>",
|
|
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"<null>";
|
|
}
|
|
|
|
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) : "<null>",
|
|
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"<null>";
|
|
}
|
|
|
|
DebPrint(Severity,
|
|
(PUCHAR) REPLICA_TRACE_FORMAT2,
|
|
Debsub,
|
|
uLineNo,
|
|
PtrToUlong(Replica),
|
|
ReplicaName,
|
|
ReplicaAddrToId(Replica),
|
|
(Replica != NULL) ? RSS_NAME(Replica->ServiceState) : "<null>",
|
|
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"<null>";
|
|
PWSTR CxtName = L"<null>";
|
|
PCHAR CxtState = "<null>";
|
|
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) : "<null>",
|
|
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"<null>";
|
|
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"<null>";
|
|
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"<null>";
|
|
PWSTR PartnerName = L"<null>";
|
|
PWSTR PartSrvName = L"<null>";
|
|
|
|
PCHAR CxtionState = "<null>";
|
|
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();
|
|
|
|
}
|
|
|