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

1167 lines
52 KiB

  1. /*++
  2. Module Name:
  3. frsexts.cxx
  4. Abstract:
  5. Author:
  6. Sudarshan Chitre (sudarc) 12-May-1999
  7. Revision History:
  8. 12-May-1999 sudarc
  9. --*/
  10. #include "frsexts.h"
  11. WINDBG_EXTENSION_APIS ExtensionApis;
  12. HANDLE ProcessHandle = 0;
  13. BOOL fKD = 0;
  14. #define MAX_ARGS 4
  15. //
  16. // stuff not common to kernel-mode and user-mode DLLs
  17. //
  18. #undef DECLARE_API
  19. #define DECLARE_API(s) \
  20. VOID \
  21. s( \
  22. HANDLE hCurrentProcess, \
  23. HANDLE hCurrentThread, \
  24. DWORD dwCurrentPc, \
  25. PWINDBG_EXTENSION_APIS pExtensionApis, \
  26. LPSTR lpArgumentString \
  27. )
  28. #define INIT_DPRINTF() { if (!fKD) ExtensionApis = *pExtensionApis; ProcessHandle = hCurrentProcess; }
  29. #define MIN(x, y) ((x) < (y)) ? x:y
  30. // define our own operators new and delete, so that we do not have to include the crt
  31. void * __cdecl
  32. ::operator new(size_t dwBytes)
  33. {
  34. void *p;
  35. p = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytes);
  36. return (p);
  37. }
  38. void __cdecl
  39. ::operator delete (void *p)
  40. {
  41. HeapFree(GetProcessHeap(), 0, p);
  42. }
  43. BOOL
  44. GetData(IN ULONG_PTR dwAddress, IN LPVOID ptr, IN ULONG size, IN PCSTR type )
  45. {
  46. BOOL b;
  47. ULONG BytesRead;
  48. ULONG count;
  49. if (fKD == 0)
  50. {
  51. return ReadProcessMemory(ProcessHandle, (LPVOID) dwAddress, ptr, size, 0);
  52. }
  53. while( size > 0 )
  54. {
  55. count = MIN( size, 3000 );
  56. b = ReadMemory((ULONG) dwAddress, ptr, count, &BytesRead );
  57. if (!b || BytesRead != count )
  58. {
  59. if (NULL == type)
  60. {
  61. type = "unspecified" ;
  62. }
  63. return FALSE;
  64. }
  65. dwAddress += count;
  66. size -= count;
  67. ptr = (LPVOID)((ULONG_PTR)ptr + count);
  68. }
  69. return TRUE;
  70. }
  71. char *Days[] =
  72. {
  73. "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  74. };
  75. char *Months[] =
  76. {
  77. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  78. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  79. };
  80. VOID
  81. FileTimeToString(
  82. FILETIME *FileTime,
  83. PCHAR Buffer
  84. )
  85. /*++
  86. Routine Description:
  87. Convert a FileTime (UTC time) to an ANSI date/time string in the
  88. local time zone.
  89. Arguments:
  90. Time - ptr to a FILETIME
  91. Str - a string of at least TIME_STRING_LENGTH bytes to receive the time.
  92. Return Value:
  93. None
  94. --*/
  95. {
  96. FILETIME LocalFileTime;
  97. SYSTEMTIME SystemTime;
  98. Buffer[0] = '\0';
  99. strcpy(Buffer, "Time???");
  100. if (FileTime->dwHighDateTime != 0 || FileTime->dwLowDateTime != 0)
  101. {
  102. if (!FileTimeToLocalFileTime(FileTime, &LocalFileTime) ||
  103. !FileTimeToSystemTime(&LocalFileTime, &SystemTime))
  104. {
  105. return;
  106. }
  107. sprintf(
  108. Buffer,
  109. "%s %s %2d, %4d %02d:%02d:%02d",
  110. Days[SystemTime.wDayOfWeek],
  111. Months[SystemTime.wMonth - 1],
  112. SystemTime.wDay,
  113. SystemTime.wYear,
  114. SystemTime.wHour,
  115. SystemTime.wMinute,
  116. SystemTime.wSecond);
  117. }
  118. return;
  119. }
  120. #define DMPGUID(_TEXT_,_Guid_) \
  121. { \
  122. dprintf((_TEXT_)); \
  123. dprintf("%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x\n", \
  124. (_Guid_).Data1, \
  125. (_Guid_).Data2, \
  126. (_Guid_).Data3, \
  127. (_Guid_).Data4[0], \
  128. (_Guid_).Data4[1], \
  129. (_Guid_).Data4[2], \
  130. (_Guid_).Data4[3], \
  131. (_Guid_).Data4[4], \
  132. (_Guid_).Data4[5], \
  133. (_Guid_).Data4[6], \
  134. (_Guid_).Data4[7]); \
  135. }
  136. #define DMPPGUID(_TEXT_,_pGuid_) \
  137. { \
  138. BOOL bDmpGuid; \
  139. BYTE bufDmpGuid[sizeof(GUID)]; \
  140. dprintf((_TEXT_)); \
  141. bDmpGuid = GetData((ULONG)(_pGuid_), &bufDmpGuid, sizeof(bufDmpGuid), NULL);\
  142. if ( !bDmpGuid ) { \
  143. dprintf("<Error reading memory>\n"); \
  144. } else { \
  145. dprintf("%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x\n", \
  146. ((GUID *)(bufDmpGuid))->Data1, \
  147. ((GUID *)(bufDmpGuid))->Data2, \
  148. ((GUID *)(bufDmpGuid))->Data3, \
  149. ((GUID *)(bufDmpGuid))->Data4[0], \
  150. ((GUID *)(bufDmpGuid))->Data4[1], \
  151. ((GUID *)(bufDmpGuid))->Data4[2], \
  152. ((GUID *)(bufDmpGuid))->Data4[3], \
  153. ((GUID *)(bufDmpGuid))->Data4[4], \
  154. ((GUID *)(bufDmpGuid))->Data4[5], \
  155. ((GUID *)(bufDmpGuid))->Data4[6], \
  156. ((GUID *)(bufDmpGuid))->Data4[7]); \
  157. \
  158. } \
  159. }
  160. #define DMPGNAME(_TEXT_,_pGname_) \
  161. { \
  162. BOOL bDmpGname; \
  163. BYTE bufDmpGname[sizeof(GNAME)];\
  164. BYTE DmpName[MAX_PATH * 2]; \
  165. UINT count = 0; \
  166. bDmpGname = GetData((ULONG)(_pGname_), &bufDmpGname, sizeof(bufDmpGname), NULL);\
  167. if ( !bDmpGname ) { \
  168. dprintf((_TEXT_)); \
  169. dprintf("<Error reading memory>\n"); \
  170. } else { \
  171. DMPPGUID((_TEXT_),((GNAME *)bufDmpGname)->Guid); \
  172. dprintf((_TEXT_)); \
  173. if (((GNAME *)bufDmpGname)->Name == NULL) { \
  174. dprintf("<null>\n"); \
  175. } else { \
  176. while (count < MAX_PATH * 2 && bDmpGname) { \
  177. bDmpGname = GetData((ULONG)(((GNAME *)bufDmpGname)->Name) + count, &DmpName[count], sizeof(BYTE), NULL);\
  178. count++; \
  179. } \
  180. \
  181. dprintf("%ws\n",(WCHAR *)DmpName); \
  182. } \
  183. } \
  184. }
  185. #define DMPQUAD(_TEXT_,_Fid_) \
  186. { \
  187. dprintf((_TEXT_)); \
  188. dprintf("%08x %08x\n",(ULONG)((_Fid_)>>32) ,(ULONG)(_Fid_)); \
  189. }
  190. #define DMPTIME(_TEXT_,_Time_) \
  191. { \
  192. CHAR TimeStr[TIME_STRING_LENGTH]; \
  193. FileTimeToString((FILETIME *)&(_Time_),TimeStr); \
  194. dprintf((_TEXT_)); \
  195. dprintf("%s\n",TimeStr); \
  196. }
  197. #define DMPSTRW(_TEXT_,_pStr_) \
  198. { \
  199. UINT count = 0; \
  200. BOOL bDmpStrW = TRUE; \
  201. BYTE DmpStr[MAX_PATH * 2]; \
  202. while (count < MAX_PATH * 2 && bDmpStrW) { \
  203. bDmpStrW = GetData((ULONG)(_pStr_) + count, &DmpStr[count], sizeof(BYTE), NULL);\
  204. count++; \
  205. } \
  206. dprintf((_TEXT_)); \
  207. dprintf("%ws\n",(WCHAR *)DmpStr); \
  208. }
  209. //
  210. // Common print functions for all the data structures.
  211. //
  212. VOID
  213. do_coe(
  214. PCHANGE_ORDER_ENTRY ChangeOrder
  215. )
  216. /*
  217. typedef struct _CHANGE_ORDER_ENTRY_ {
  218. GENERIC_HASH_ENTRY_HEADER HashEntryHeader; // Change Order hash Table support
  219. UNICODE_STRING UFileName; // Used in renames to make file name bigger
  220. ULONG EntryFlags; // misc state flags. See below.
  221. ULONG CoMorphGenCount; // for debugging.
  222. //
  223. // Change order process list management.
  224. //
  225. LIST_ENTRY ProcessList; // Link on the change order process list.
  226. ULONG TimeToRun; // Time to process the change order.
  227. ULONG EntryCreateTime; // Tick Count at entry create time.
  228. SINGLE_LIST_ENTRY DupCoList; // Duplicate change order list.
  229. //
  230. //
  231. ULONG DirNestingLevel; // Number levels file is down in tree.
  232. ULONGLONG FileReferenceNumber; // File's FID
  233. ULONGLONG ParentFileReferenceNumber; // File's parent FID
  234. ULONGLONG OriginalParentFid; // For rename processing
  235. ULONGLONG NewParentFid; // For rename processing
  236. ULONGLONG NameConflictHashValue; // Key value for NameConflict table cleanup.
  237. ULONG StreamLastMergeSeqNum; // Stream seq num of last Usn record merged with this CO.
  238. PREPLICA_THREAD_CTX RtCtx; // For DB access during CO processing.
  239. GUID *pParentGuid; // ptr to the File's parent Guid in CoCmd.
  240. //
  241. // The joinguid is a cxtion's session id and, in this case,
  242. // is used to retry change orders that were accepted by
  243. // the change order accept thread for a cxtion that has since
  244. // unjoined from its partner. The change orders for previous
  245. // sessions are retried because they are out-of-order wrt the
  246. // change orders for the current session id. In other words,
  247. // order is maintained per session by coordinating the partners
  248. // at join time.
  249. GUID JoinGuid; // Cxtion's session id
  250. // undefined if local co
  251. //
  252. // Remote and control change orders are associated with a cxtion.
  253. // If this field is non-null, then the field
  254. // ChangeOrderCount has been incremente for this change
  255. // order. The count should be decremented when the
  256. // change order is freed in ChgOrdIssueCleanup().
  257. //
  258. PCXTION Cxtion; // NULL if local co
  259. //
  260. // Issue cleanup flags -- As a change order is processed it acquires
  261. // various resources that must be released when it retires or goes thru
  262. // retry. The ISCU flag bits below are used to set these bits. Note:
  263. // Not all bits may be set here. Some may get set just before the CO goes
  264. // thru cleanup.
  265. //
  266. ULONG IssueCleanup;
  267. //
  268. // Needed to dampen basic info changes (e.g., resetting the archive bit)
  269. // Copied from the idtable entry when the change order is created and
  270. // used to update the change order when the change order is retired.
  271. //
  272. ULONG FileAttributes;
  273. LARGE_INTEGER FileCreateTime;
  274. LARGE_INTEGER FileWriteTime;
  275. //
  276. // Change order command parameters.
  277. // (must be last since it ends with FileName)
  278. //
  279. CHANGE_ORDER_COMMAND Cmd;
  280. } CHANGE_ORDER_ENTRY, *PCHANGE_ORDER_ENTRY;
  281. */
  282. {
  283. PWCHAR FileName = NULL;
  284. dprintf("Dumping CHANGE_ORDER_ENTRY.\n\n");
  285. dprintf("HashEntryHeader : Address( 0x%x )\n",ChangeOrder->HashEntryHeader);
  286. dprintf("FileNameLength : %d\n",ChangeOrder->UFileName.Length);
  287. FileName = new WCHAR((ChangeOrder->UFileName.Length)/2 + 1);
  288. GetData((ULONG)(ChangeOrder->UFileName.Buffer),(BYTE*)FileName,ChangeOrder->UFileName.Length,NULL);
  289. FileName[(ChangeOrder->UFileName.Length)/2] = L'\0';
  290. dprintf("FileName : Address( 0x%x )\n",ChangeOrder->UFileName.Buffer);
  291. dprintf("FileName : %ws\n",FileName);
  292. delete FileName;
  293. dprintf("EntryFlags : 0x%x\n",ChangeOrder->EntryFlags);
  294. dprintf("CoMorphGenCount : %d\n",ChangeOrder->CoMorphGenCount);
  295. dprintf("ProcessList : Address( 0x%x )\n",ChangeOrder->ProcessList);
  296. dprintf("TimeToRun : %d\n",ChangeOrder->TimeToRun);
  297. dprintf("EntryCreateTime : %d\n",ChangeOrder->EntryCreateTime);
  298. dprintf("DupCoList : Address( 0x%x )\n",ChangeOrder->DupCoList);
  299. dprintf("DirNestingLevel : %d\n",ChangeOrder->DirNestingLevel);
  300. DMPQUAD("FileReferenceNumber : ",ChangeOrder->FileReferenceNumber);
  301. DMPQUAD("ParentFileReferenceNumber : ",ChangeOrder->ParentFileReferenceNumber);
  302. DMPQUAD("OriginalParentFid : ",ChangeOrder->OriginalParentFid);
  303. DMPQUAD("NewParentFid : ",ChangeOrder->NewParentFid);
  304. DMPQUAD("NameConflictHashValue : ",ChangeOrder->NameConflictHashValue);
  305. dprintf("StreamLastMergeSeqNum : %d\n",ChangeOrder->StreamLastMergeSeqNum);
  306. dprintf("RtCtx : Address( 0x%x )\n",ChangeOrder->RtCtx);
  307. DMPPGUID("pParentGuid : ",ChangeOrder->pParentGuid);
  308. DMPGUID("JoinGuid : ",ChangeOrder->JoinGuid);
  309. dprintf("Cxtion : Address( 0x%x )\n",ChangeOrder->Cxtion);
  310. dprintf("IssueCleanup : 0x%x\n",ChangeOrder->IssueCleanup);
  311. dprintf("FileAttributes : 0x%x\n",ChangeOrder->FileAttributes);
  312. DMPTIME("FileCreateTime : ",ChangeOrder->FileCreateTime);
  313. DMPTIME("FileWriteTime : ",ChangeOrder->FileWriteTime);
  314. dprintf("Cmd : Address( 0x%x )\n",ChangeOrder->Cmd);
  315. }
  316. VOID
  317. do_coc(
  318. PCHANGE_ORDER_COMMAND Cmd
  319. )
  320. /*
  321. typedef struct _CHANGE_ORDER_RECORD_ {
  322. ULONG SequenceNumber; // Unique sequence number for change order.
  323. ULONG Flags; // Change order flags
  324. ULONG IFlags; // These flags can ONLY be updated with interlocked exchange.
  325. ULONG State; // State is sep DWORD to avoid locking.
  326. ULONG ContentCmd; // File content changes from UsnReason
  327. union {
  328. ULONG LocationCmd;
  329. CO_LOCATION_CMD Field; // File Location command
  330. } Lcmd;
  331. ULONG FileAttributes;
  332. ULONG FileVersionNumber; // The file version number, inc on each close.
  333. ULONG PartnerAckSeqNumber; // Save seq number for Partner Ack.
  334. ULONGLONG FileSize;
  335. ULONGLONG FileOffset; // The current committed progress for staging file.
  336. ULONGLONG FrsVsn; // Originator Volume sequence number
  337. bugbug("perf: FileUsn and JrnlUsn can probably be combined")
  338. USN FileUsn; // The USN of the file must match on the Fetch request.
  339. USN JrnlUsn; // USN of last journal record contributing to this CO.
  340. USN JrnlFirstUsn; // USN of first journal record contributing to this CO.
  341. struct _REPLICA *OriginalReplica; // Contains Replica ID when in DB
  342. struct _REPLICA *NewReplica; // Contains Replica ID when in DB
  343. GUID ChangeOrderGuid; // Guid that identifies the change order everywhere.
  344. GUID OriginatorGuid; // The GUID of the originating member
  345. GUID FileGuid; // The obj ID of the file
  346. GUID OldParentGuid; // The Obj ID of the file's original parent directory
  347. GUID NewParentGuid; // The Obj ID of the file's current parent directory
  348. GUID CxtionGuid; // The obj ID of remote CO connection.
  349. ULONGLONG Spare1Ull;
  350. ULONGLONG Spare2Ull;
  351. GUID Spare1Guid;
  352. GUID Spare2Guid;
  353. PWCHAR Spare1Wcs;
  354. PWCHAR Spare2Wcs;
  355. PVOID Spare1Bin;
  356. PVOID Spare2Bin;
  357. LARGE_INTEGER EventTime; // The USN Journal Entry Timestamp.
  358. USHORT FileNameLength;
  359. WCHAR FileName[MAX_PATH+1]; // The file name. (Must be Last)
  360. } CHANGE_ORDER_COMMAND, *PCHANGE_ORDER_COMMAND,
  361. */
  362. {
  363. PWCHAR FileName = NULL;
  364. dprintf("Dumping CHANGE_ORDER_COMMAND.\n\n");
  365. dprintf("SequenceNumber : %d\n",Cmd->SequenceNumber);
  366. dprintf("Flags : 0x%x\n",Cmd->Flags);
  367. dprintf("IFlags : 0x%x\n",Cmd->IFlags);
  368. dprintf("State : %d\n",Cmd->State);
  369. dprintf("ContentCmd : 0x%x\n",Cmd->ContentCmd);
  370. dprintf("LocationCmd : 0x%x\n",Cmd->Lcmd.LocationCmd);
  371. dprintf("FileAttributes : 0x%x\n",Cmd->FileAttributes);
  372. dprintf("FileVersionNumber : %d\n",Cmd->FileVersionNumber);
  373. dprintf("PartnerAckSeqNumber : %d\n",Cmd->PartnerAckSeqNumber);
  374. DMPQUAD("FileSize : ",Cmd->FileSize);
  375. DMPQUAD("FileOffset : ",Cmd->FileOffset);
  376. DMPQUAD("FrsVsn : ",Cmd->FrsVsn);
  377. DMPQUAD("FileUsn : ",Cmd->FileUsn);
  378. DMPQUAD("JrnlUsn : ",Cmd->JrnlUsn);
  379. DMPQUAD("JrnlFirstUsn : ",Cmd->JrnlFirstUsn);
  380. dprintf("OriginalReplicaNum : %d\n",Cmd->OriginalReplicaNum);
  381. dprintf("NewReplicaNum : %d\n",Cmd->NewReplicaNum);
  382. DMPGUID("ChangeOrderGuid : ",Cmd->ChangeOrderGuid);
  383. DMPGUID("OriginatorGuid : ",Cmd->OriginatorGuid);
  384. DMPGUID("FileGuid : ",Cmd->FileGuid);
  385. DMPGUID("OldParentGuid : ",Cmd->OldParentGuid);
  386. DMPGUID("NewParentGuid : ",Cmd->NewParentGuid);
  387. DMPGUID("CxtionGuid : ",Cmd->CxtionGuid);
  388. DMPTIME("EventTime : ",Cmd->EventTime);
  389. dprintf("FileNameLength : %d\n",Cmd->FileNameLength);
  390. dprintf("FileName : %ws\n",Cmd->FileName);
  391. }
  392. VOID
  393. do_cxt(
  394. PCXTION pCxtion
  395. )
  396. /*
  397. typedef struct _CXTION CXTION, *PCXTION;
  398. struct _CXTION {
  399. FRS_NODE_HEADER Header; // memory management
  400. ULONG State; // Incore state
  401. ULONG Flags; // misc flags
  402. BOOL Inbound; // TRUE if inbound cxtion *
  403. BOOL JrnlCxtion; // TRUE if this Cxtion struct is for the local NTFS Journal
  404. PGNAME Name; // Cxtion name/guid from the DS *
  405. PGNAME Partner; // Partner's name/guid from the DS *
  406. PWCHAR PartnerDnsName; // partner's DNS name from the DS *
  407. PWCHAR PartnerPrincName; // partner's server principle name *
  408. PWCHAR PartnerSid; // partner's sid (string) *
  409. PWCHAR PartSrvName; // Partner's server name
  410. ULONG PartnerAuthLevel; // Authentication level *
  411. PGEN_TABLE VVector; // partner's version vector
  412. PSCHEDULE Schedule; // schedule *
  413. ULONG TerminationCoSeqNum;// The Seq Num of most recent Termination CO inserted.
  414. PCOMMAND_SERVER VvJoinCs; // command server for vvjoins
  415. struct _COMMAND_PACKET *JoinCmd; // check join status; rejoin if needed
  416. // NULL == no delayed cmd outstanding
  417. ULONGLONG LastJoinTime; // The time of the last successful join on this cxtion.
  418. GUID JoinGuid; // Unique id for this join
  419. GUID ReplicaVersionGuid; // partner's originator guid
  420. DWORD CommQueueIndex; // Comm layer queue for sending pkts
  421. DWORD ChangeOrderCount; // remote/control change orders pending
  422. PGEN_TABLE CoeTable; // table of idle change orders
  423. struct _COMMAND_PACKET *CommTimeoutCmd; // Timeout (waitable timer) packet
  424. DWORD UnjoinTrigger; // DBG force unjoin in # remote cos
  425. DWORD UnjoinReset; // reset force unjoin trigger
  426. PFRS_QUEUE CoProcessQueue; // If non-null then Unidle the queue when
  427. // JOIN succeeds or fails.
  428. ULONG CommPkts; // Number of comm pkts
  429. ULONG Penalty; // Penalty in Milliseconds
  430. PCOMM_PACKET ActiveJoinCommPkt; // Don't flood Q w/many join pkts
  431. ULONG PartnerMajor; // From comm packet
  432. ULONG PartnerMinor; // From comm packet
  433. struct _OUT_LOG_PARTNER_ *OLCtx; // Outbound Log Context for this connection.
  434. struct _HASHTABLEDATA_REPLICACONN *PerfRepConnData; // PERFMON counter data structure
  435. };
  436. */
  437. {
  438. dprintf("Dumping CXTION.\n\n");
  439. dprintf("Header : Address ( 0x%x )\n",pCxtion->Header);
  440. dprintf("State : %d\n",pCxtion->State);
  441. dprintf("Flags : 0x%x\n",pCxtion->Flags);
  442. dprintf("Inbound : %d\n",pCxtion->Inbound);
  443. dprintf("JrnlCxtion : %d\n",pCxtion->JrnlCxtion);
  444. DMPGNAME("Name : ",pCxtion->Name);
  445. DMPGNAME("Partner : ",pCxtion->Partner);
  446. dprintf("PartnerDnsName : %ws\n",pCxtion->PartnerDnsName);
  447. dprintf("PartnerPrincName : %ws\n",pCxtion->PartnerPrincName);
  448. dprintf("PartnerSid : %ws\n",pCxtion->PartnerSid);
  449. dprintf("PartSrvName : %ws\n",pCxtion->PartSrvName);
  450. dprintf("PartnerAuthLevel : %d\n",pCxtion->PartnerAuthLevel);
  451. dprintf("VVector : Address ( 0x%x )\n",pCxtion->VVector);
  452. dprintf("Schedule : Address ( 0x%x )\n",pCxtion->Schedule);
  453. dprintf("TerminationCoSeqNum : %d\n",pCxtion->TerminationCoSeqNum);
  454. dprintf("VvJoinCs : Address ( 0x%x )\n",pCxtion->VvJoinCs);
  455. dprintf("JoinCmd : Address ( 0x%x )\n",pCxtion->JoinCmd);
  456. DMPTIME("LastJoinTime : ",pCxtion->LastJoinTime);
  457. DMPGUID("JoinGuid : ",pCxtion->JoinGuid);
  458. DMPGUID("ReplicaVersionGuid : ",pCxtion->ReplicaVersionGuid);
  459. dprintf("CommQueueIndex : %d\n",pCxtion->CommQueueIndex);
  460. dprintf("ChangeOrderCount : %d\n",pCxtion->ChangeOrderCount);
  461. dprintf("CoeTable : Address ( 0x%x )\n",pCxtion->CoeTable);
  462. dprintf("CommTimeoutCmd : Address ( 0x%x )\n",pCxtion->CommTimeoutCmd);
  463. dprintf("UnjoinTrigger : %d\n",pCxtion->UnjoinTrigger);
  464. dprintf("UnjoinReset : %d\n",pCxtion->UnjoinReset);
  465. dprintf("CoProcessQueue : Address ( 0x%x )\n",pCxtion->CoProcessQueue);
  466. dprintf("CommPkts : %d\n",pCxtion->CommPkts);
  467. dprintf("Penalty : %d\n",pCxtion->Penalty);
  468. dprintf("ActiveJoinCommPkt : Address ( 0x%x )\n",pCxtion->ActiveJoinCommPkt);
  469. dprintf("PartnerMajor : %d\n",pCxtion->PartnerMajor);
  470. dprintf("PartnerMinor : %d\n",pCxtion->PartnerMinor);
  471. dprintf("OLCtx : Address ( 0x%x )\n",pCxtion->OLCtx);
  472. dprintf("PerfRepConnData : Address ( 0x%x )\n",pCxtion->PerfRepConnData);
  473. }
  474. VOID
  475. do_olp(
  476. POUT_LOG_PARTNER pOlp
  477. )
  478. /*
  479. typedef struct _OUT_LOG_PARTNER_ {
  480. FRS_NODE_HEADER Header; // Memory alloc
  481. LIST_ENTRY List; // Link on the change order set list. (DONT MOVE)
  482. ULONG Flags; // misc state flags. see below.
  483. ULONG State; // Current state of this outbound partner.
  484. SINGLE_LIST_ENTRY SaveList; // The link for the DB save list.
  485. ULONG COLxRestart; // Restart point for Leading change order index.
  486. ULONG COLxVVJoinDone; // COLx where VVJoin Finished and was rolled back.
  487. ULONG COLx; // Leading change order index / sequence number.
  488. ULONG COTx; // Trailing change order index / sequence number.
  489. ULONG COTxLastSaved; // COTx value last saved in DB.
  490. ULONG COTxNormalModeSave;// Saved Normal Mode COTx while in VV Join Mode.
  491. ULONG COTslot; // Slot in Ack Vector corresponding to COTx.
  492. ULONG OutstandingCos; // The current number of change orders outstanding.
  493. ULONG OutstandingQuota; // The maximum number of COs outstanding.
  494. ULONG AckVector[ACK_VECTOR_LONGS]; // The partner ack vector.
  495. PCXTION Cxtion; // The partner connection. Has Guid and VVector.
  496. } OUT_LOG_PARTNER, *POUT_LOG_PARTNER;
  497. */
  498. {
  499. dprintf("Dumping OUT_LOG_PARTNER.\n\n");
  500. dprintf("Header : Address ( 0x%x )\n",pOlp->Header);
  501. dprintf("List : Address ( 0x%x )\n",pOlp->List);
  502. dprintf("Flags : 0x%x\n",pOlp->Flags);
  503. dprintf("State : %d\n",pOlp->State);
  504. dprintf("SaveList : Address ( 0x%x )\n",pOlp->SaveList);
  505. dprintf("COLxRestart : %d\n",pOlp->COLxRestart);
  506. dprintf("COLxVVJoinDone : %d\n",pOlp->COLxVVJoinDone);
  507. dprintf("COLx : %d\n",pOlp->COLx);
  508. dprintf("COTx : %d\n",pOlp->COTx);
  509. dprintf("COTxLastSaved : %d\n",pOlp->COTxLastSaved);
  510. dprintf("COTxNormalModeSave : %d\n",pOlp->COTxNormalModeSave);
  511. dprintf("COTslot : %d\n",pOlp->COTslot);
  512. dprintf("OutstandingCos : %d\n",pOlp->OutstandingCos);
  513. dprintf("OutstandingQuota : %d\n",pOlp->OutstandingQuota);
  514. }
  515. VOID
  516. do_rep(
  517. PREPLICA pReplica
  518. )
  519. /*
  520. typedef struct _REPLICA {
  521. FRS_NODE_HEADER Header; // memory management
  522. CRITICAL_SECTION ReplicaLock; // protects filter list (for now)
  523. ULONG ReferenceCount;
  524. ULONG CnfFlags; // From the config record
  525. ULONG ReplicaSetType; // Type of replica set
  526. BOOL Consistent; // replica is consistent
  527. BOOL IsOpen; // database table is open
  528. BOOL IsJournaling; // journal has been started
  529. BOOL IsAccepting; // accepting comm requests
  530. BOOL NeedsUpdate; // needs updating in the database
  531. BOOL IsSeeding; // Seeding thread is deployed
  532. BOOL IsSysvolReady; // SysvolReady is set to 1
  533. LIST_ENTRY ReplicaList; // Link all replicas together
  534. ULONG ServiceState; // stop, started, ...
  535. FRS_ERROR_CODE FStatus; // error
  536. PFRS_QUEUE Queue; // controlled by the command server
  537. PGNAME ReplicaName; // Set name/Server guid from the DS
  538. ULONG ReplicaNumber; // Internal id (name)
  539. PGNAME MemberName; // Member name/guid from the DS
  540. PGNAME SetName; // Set/guid name from the DS
  541. GUID *ReplicaRootGuid; // guid assigned to Root dir
  542. GUID ReplicaVersionGuid; // originator guid for version vector
  543. PSCHEDULE Schedule; // schedule
  544. PGEN_TABLE VVector; // Version vector
  545. PGEN_TABLE Cxtions; // in/outbound cxtions
  546. PWCHAR Root; // Root path
  547. PWCHAR Stage; // Staging path
  548. PWCHAR NewStage; // This maps to the current staging path in the
  549. // DS. NewStage will be the one written to
  550. // the config record but Stage will be used until
  551. // next reboot.
  552. PWCHAR Volume; // Volume??? bugbug
  553. ULONGLONG MembershipExpires;// membership tombstone
  554. ULONGLONG PreInstallFid; // For journal filtering.
  555. TABLE_CTX ConfigTable; // Db table context
  556. FRS_LIST ReplicaCtxListHead; // Links all open contexts on this replica set.
  557. PWCHAR FileFilterList; // Raw file filter
  558. PWCHAR DirFilterList; // Raw directory filter
  559. LIST_ENTRY FileNameFilterHead; // Head of file name filter list.
  560. LIST_ENTRY DirNameFilterHead; // Head of directory name filter list.
  561. PQHASH_TABLE NameConflictTable; // Sequence COs using the same file name.
  562. LONG InLogRetryCount; // Count of number CO needing a Retry.
  563. ULONG InLogSeqNumber; // The last sequence number used in Inlog
  564. //
  565. //
  566. // The inlog retry table tracks which retry change orders are currently
  567. // active so we don't reissue the same change order until current
  568. // invocation completes. This can happen when the system gets backed up
  569. // and the change order retry thread kicks off again to issue retry COs
  570. // before the last batch are able to finish. This state could be kept in
  571. // the Inlog record but then it means extra writes to the DB.
  572. // The sequence number is used to detect changes in the table when we don't
  573. // have the lock. It is per-replica because it uses the change order
  574. // sequence number of the inlog record and they aren't unique across
  575. // replicas.
  576. //
  577. PQHASH_TABLE ActiveInlogRetryTable;
  578. union {
  579. struct {
  580. ULONG AIRSequenceNum;
  581. ULONG AIRSequenceNumSample;
  582. };
  583. ULONGLONG QuadChunkA;
  584. };
  585. //
  586. // Status of sysvol seeding.
  587. // Returned for NtFrsApi_Rpc_PromotionStatusW().
  588. //
  589. DWORD NtFrsApi_ServiceState;
  590. DWORD NtFrsApi_ServiceWStatus;
  591. #ifndef NOVVJOINHACK
  592. DWORD NtFrsApi_HackCount; // temporary hack
  593. #endif NOVVJOINHACK
  594. PWCHAR NtFrsApi_ServiceDisplay;
  595. //
  596. // The Outbound log process state for this replica.
  597. //
  598. CRITICAL_SECTION OutLogLock; // protects the OutLog state
  599. LIST_ENTRY OutLogEligible; // Eligible outbound log partners
  600. LIST_ENTRY OutLogStandBy; // Partners ready to join eligible list
  601. LIST_ENTRY OutLogActive; // Active outbound log partners
  602. LIST_ENTRY OutLogInActive; // Inactive outbound log partners
  603. PQHASH_TABLE OutLogRecordLock; // Sync access to outlog records.
  604. ULONG OutLogSeqNumber; // The last sequence number used in Outlog
  605. ULONG OutLogJLx; // The Joint Leading Index
  606. ULONG OutLogJTx; // The Joint Trailing Index
  607. ULONG OutLogCOMax; // The index of the Max change order in the log.
  608. ULONG OutLogWorkState; // The output log current processing state.
  609. struct _COMMAND_PACKET *OutLogCmdPkt; // Cmd pkt to queue when idle and have work.
  610. PTABLE_CTX OutLogTableCtx; // Output Log Table context.
  611. ULONG OutLogCountVVJoins; // Count of number of VVJoins in progress.
  612. BOOL OutLogDoCleanup; // True means give log cleanup a run.
  613. //
  614. // The handle to the preinstall directory
  615. //
  616. HANDLE PreInstallHandle;
  617. //
  618. // The volume journal state for this replica.
  619. //
  620. GUID JrnlCxtionGuid; // Used as the Cxtion Guid for Local Cos
  621. USN InlogCommitUsn; // Our current USN Journal commit point.
  622. //USN JournalUsn; // The Journal USN for this replica.
  623. USN JrnlRecoveryStart; // Point to start recovery.
  624. USN JrnlRecoveryEnd; // Point where recovery is complete.
  625. LIST_ENTRY RecoveryRefreshList; // List of file refresh req change orders.
  626. LIST_ENTRY VolReplicaList; // Links all REPLICA structs on volume together.
  627. USN LastUsnRecordProcessed; // Current Journal subsystem read USN.
  628. LONG LocalCoQueueCount; // Count of number local COs in process queue
  629. struct _VOLUME_MONITOR_ENTRY *pVme; // Ref to the VME for this Replica.
  630. struct _HASHTABLEDATA_REPLICASET *PerfRepSetData; // PERFMON counter data structure
  631. } REPLICA, *PREPLICA;
  632. */
  633. {
  634. dprintf("Dumping REPLICA.\n\n");
  635. dprintf("Header : Address ( 0x%x )\n",pReplica->Header);
  636. dprintf("ReplicaLock : Address ( 0x%x )\n",pReplica->ReplicaLock);
  637. dprintf("ReferenceCount : %d\n",pReplica->ReferenceCount);
  638. dprintf("CnfFlags : 0x%x\n",pReplica->CnfFlags);
  639. dprintf("ReplicaSetType : %d\n",pReplica->ReplicaSetType);
  640. dprintf("Consistent : %d\n",pReplica->Consistent);
  641. dprintf("IsOpen : %d\n",pReplica->IsOpen);
  642. dprintf("IsJournaling : %d\n",pReplica->IsJournaling);
  643. dprintf("IsAccepting : %d\n",pReplica->IsAccepting);
  644. dprintf("NeedsUpdate : %d\n",pReplica->NeedsUpdate);
  645. dprintf("IsSeeding : %d\n",pReplica->IsSeeding);
  646. dprintf("IsSysvolReady : %d\n",pReplica->IsSysvolReady);
  647. dprintf("ReplicaList : Address ( 0x%x )\n",pReplica->ReplicaList);
  648. dprintf("ServiceState : %d\n",pReplica->ServiceState);
  649. dprintf("FStatus : %d\n",pReplica->FStatus);
  650. dprintf("Queue : Address ( 0x%x )\n",pReplica->Queue);
  651. DMPGNAME("ReplicaName : ",pReplica->ReplicaName);
  652. dprintf("ReplicaNumber : %d\n",pReplica->ReplicaNumber);
  653. DMPGNAME("MemberName : ",pReplica->MemberName);
  654. DMPGNAME("SetName : ",pReplica->SetName);
  655. DMPPGUID("ReplicaRootGuid : ",pReplica->ReplicaRootGuid);
  656. DMPGUID("ReplicaVersionGuid : ",pReplica->ReplicaVersionGuid);
  657. dprintf("Schedule : Address ( 0x%x )\n",pReplica->Schedule);
  658. dprintf("VVector : Address ( 0x%x )\n",pReplica->VVector);
  659. dprintf("Cxtions : Address ( 0x%x )\n",pReplica->Cxtions);
  660. DMPSTRW("Root : ",pReplica->Root);
  661. DMPSTRW("Stage : ",pReplica->Stage);
  662. DMPSTRW("NewStage : ",pReplica->NewStage);
  663. DMPSTRW("Volume : ",pReplica->Volume);
  664. DMPTIME("MembershipExpires : ",pReplica->MembershipExpires);
  665. DMPQUAD("PreInstallFid : ",pReplica->PreInstallFid);
  666. dprintf("ConfigTable : Address ( 0x%x )\n",pReplica->ConfigTable);
  667. dprintf("ReplicaCtxListHead : Address ( 0x%x )\n",pReplica->ReplicaCtxListHead);
  668. DMPSTRW("FileFilterList : ",pReplica->FileFilterList);
  669. DMPSTRW("DirFilterList : ",pReplica->DirFilterList);
  670. dprintf("FileNameFilterHead : Address ( 0x%x )\n",pReplica->FileNameFilterHead);
  671. dprintf("DirNameFilterHead : Address ( 0x%x )\n",pReplica->DirNameFilterHead);
  672. dprintf("NameConflictTable : Address ( 0x%x )\n",pReplica->NameConflictTable);
  673. dprintf("InLogRetryCount : %d\n",pReplica->InLogRetryCount);
  674. dprintf("InLogSeqNumber : %d\n",pReplica->InLogSeqNumber);
  675. dprintf("ActiveInlogRetryTable : Address ( 0x%x )\n",pReplica->ActiveInlogRetryTable);
  676. dprintf("NtFrsApi_ServiceState : %d\n",pReplica->NtFrsApi_ServiceState);
  677. dprintf("NtFrsApi_ServiceWStatus : %d\n",pReplica->NtFrsApi_ServiceWStatus);
  678. DMPSTRW("NtFrsApi_ServiceDisplay : ",pReplica->NtFrsApi_ServiceDisplay);
  679. dprintf("OutLogLock : Address ( 0x%x )\n",pReplica->OutLogLock);
  680. dprintf("OutLogEligible : Address ( 0x%x )\n",pReplica->OutLogEligible);
  681. dprintf("OutLogStandBy : Address ( 0x%x )\n",pReplica->OutLogStandBy);
  682. dprintf("OutLogActive : Address ( 0x%x )\n",pReplica->OutLogActive);
  683. dprintf("OutLogInActive : Address ( 0x%x )\n",pReplica->OutLogInActive);
  684. dprintf("OutLogRecordLock : Address ( 0x%x )\n",pReplica->OutLogRecordLock);
  685. dprintf("OutLogSeqNumber : %d\n",pReplica->OutLogSeqNumber);
  686. dprintf("OutLogJLx : %d\n",pReplica->OutLogJLx);
  687. dprintf("OutLogJTx : %d\n",pReplica->OutLogJTx);
  688. dprintf("OutLogCOMax : %d\n",pReplica->OutLogCOMax);
  689. dprintf("OutLogWorkState : %d\n",pReplica->OutLogWorkState);
  690. dprintf("OutLogCmdPkt : Address ( 0x%x )\n",pReplica->OutLogCmdPkt);
  691. dprintf("OutLogTableCtx : Address ( 0x%x )\n",pReplica->OutLogTableCtx);
  692. dprintf("OutLogCountVVJoins : %d\n",pReplica->OutLogCountVVJoins);
  693. dprintf("OutLogDoCleanup : %d\n",pReplica->OutLogDoCleanup);
  694. dprintf("PreInstallHandle : Address ( 0x%x )\n",pReplica->PreInstallHandle);
  695. DMPGUID("JrnlCxtionGuid : ",pReplica->JrnlCxtionGuid);
  696. DMPQUAD("InlogCommitUsn : ",pReplica->InlogCommitUsn);
  697. DMPQUAD("JrnlRecoveryStart : ",pReplica->JrnlRecoveryStart);
  698. DMPQUAD("JrnlRecoveryEnd : ",pReplica->JrnlRecoveryEnd);
  699. dprintf("RecoveryRefreshList : Address ( 0x%x )\n",pReplica->RecoveryRefreshList);
  700. dprintf("VolReplicaList : Address ( 0x%x )\n",pReplica->VolReplicaList);
  701. DMPQUAD("LastUsnRecordProcessed : ",pReplica->LastUsnRecordProcessed);
  702. dprintf("LocalCoQueueCount : %d\n",pReplica->LocalCoQueueCount);
  703. dprintf("pVme : Address ( 0x%x )\n",pReplica->pVme);
  704. dprintf("PerfRepSetData : Address ( 0x%x )\n",pReplica->PerfRepSetData);
  705. }
  706. VOID
  707. do_vme(
  708. PVOLUME_MONITOR_ENTRY pVme
  709. )
  710. /*
  711. typedef struct _VOLUME_MONITOR_ENTRY {
  712. FRS_NODE_HEADER Header;
  713. LIST_ENTRY ListEntry; // MUST FOLLOW HEADER
  714. //
  715. // This is the list head for all replica sets on the this volume. It links
  716. // the REPLICA structs together.
  717. //
  718. FRS_LIST ReplicaListHead; // List of Replica Sets on Vol.
  719. //
  720. // The following USNs are for managing the NTFS USN journal on the volume.
  721. //
  722. USN JrnlRecoveryEnd; // Point where recovery is complete.
  723. USN CurrentUsnRecord; // USN of record currently being processed.
  724. USN CurrentUsnRecordDone; // USN of most recent record done processing.
  725. USN LastUsnSavePoint; // USN of last vol wide save.
  726. USN MonitorMaxProgressUsn; // Farthest progress made in this journal.
  727. USN JrnlReadPoint; // The current active read point for journal.
  728. USN_JOURNAL_DATA UsnJournalData; // FSCTL_QUERY_USN_JOURNAL data at journal open.
  729. USN MonitorProgressUsn; // Start journal from here after pause.
  730. USN ReplayUsn; // Start journal here after replica startup request
  731. BOOL ReplayUsnValid; // above has valid data.
  732. //
  733. // The FrsVsn is a USN kept by FRS and exported by all replica sets on the
  734. // volume. It is unaffected by disk reformats and is saved in the config
  735. // record of each replica set. At startup we use the maximum value for all
  736. // replica sets on a given volume. The only time they might differ is when
  737. // service on a given replica set is not started.
  738. //
  739. ULONGLONG FrsVsn; // Private FRS volume seq num.
  740. CRITICAL_SECTION Lock; // To sync access to VME.
  741. CRITICAL_SECTION QuadWriteLock; // To sync updates to quadwords.
  742. OVERLAPPED CancelOverlap; // Overlap struct for cancel req
  743. ULONG WStatus; // Win32 status on error
  744. ULONG ActiveReplicas; // Num replica sets active on journal
  745. HANDLE Event; // Event handle for pause journal.
  746. HANDLE VolumeHandle; // The vol handle for journal.
  747. WCHAR DriveLetter[4]; // Drive letter for this volume.
  748. //
  749. // A change order table is kept on each volume to track the pending
  750. // change orders. Tracking it for each replica set would be nice but
  751. // that approach has a problem with renames that move files or dirs
  752. // across replica sets on the volume. If there are prior change orders
  753. // outstanding on a parent dir (MOVEOUT) in RS-A followed by a MOVEIN on
  754. // a child file X to RS-B we must be sure the MOVEOUT on the parent happens
  755. // before the MOVEIN on X. Similar problems arise with a MOVEOUT of file X
  756. // followed by a MOVEIN to a different R.S. on the same volume. We need to
  757. // locate the pending MOVEOUT change order on the volume or ensure it is
  758. // processed first. One list per volume solves these problems.
  759. //
  760. PGENERIC_HASH_TABLE ChangeOrderTable;// The Replica Change Order table.
  761. FRS_QUEUE ChangeOrderList; // Change order processing list head.
  762. LIST_ENTRY UpdateList; // Link for the Replica Update Process Queue.
  763. ULONG InitTime; // Time reference for the ChangeOrderList.
  764. //
  765. // THe Active Inbound Change Order table holds the change order structs
  766. // indexed by File ID. An entry in the table means that we have an
  767. // inbound (either local or remote) change order active on this file.
  768. //
  769. PGENERIC_HASH_TABLE ActiveInboundChangeOrderTable;
  770. //
  771. // The ActiveChildren hash table is used to record the parent FID of each
  772. // active change order. This is used to prevent a change order from starting
  773. // on the parent while a change order is active on one or more children.
  774. // For example if the child change order was a create and the parent change
  775. // order was an ACL change to prevent further creates, we must ensure the
  776. // child completes before starting the parent change order. Each entry has
  777. // a count of the number of active children and a flag that is set if the
  778. // change order process queue is blocked because of a pending change order
  779. // on the parent. When the count goes to zero the queue is unblocked.
  780. //
  781. PQHASH_TABLE ActiveChildren;
  782. //
  783. // The Parent Table is a simple hash table used to keep the parent File ID
  784. // for each file and dir in any Replica Set on the volume. It is used in
  785. // renames to find the old parent.
  786. //
  787. PQHASH_TABLE ParentFidTable;
  788. //
  789. // The FRS Write Filter table filters out journal entries caused
  790. // by file system write from the File Replication Service (Us) when we
  791. // install files in the replica tree.
  792. //
  793. PQHASH_TABLE FrsWriteFilter;
  794. //
  795. // The Recovery Conflict Table contains the FIDs of files that were in
  796. // the inbound log when we crashed. At the start of recovery the inbound
  797. // log for the given replica set is scanned and the FIDs are entered into
  798. // the table. During journal processing any USN records with a matching
  799. // FID are deemed to caused by FRS so we skip the record. (This is because
  800. // the FrsWriteFilter table was lost in the crash).
  801. PQHASH_TABLE RecoveryConflictTable;
  802. //
  803. // The name space table controls the merging of USN records into COs
  804. // that use the same file name. If a name usage conflict exists in the
  805. // USN record stream then we can't merge the USN record into a previous
  806. // change order on the same file.
  807. //
  808. PQHASH_TABLE NameSpaceTable;
  809. ULONG StreamSequenceNumberFetched;
  810. ULONG StreamSequenceNumberClean;
  811. ULONG StreamSequenceNumber;
  812. //
  813. // The Filter Table contains an entry for each direcctory that is within a
  814. // replica set on this volume. It is used to filter out Journal records for
  815. // files/dirs that are not in a Replica set. For those Journal records that
  816. // are in a replica set, a lookup on the parent FileId tells us which one.
  817. //
  818. PGENERIC_HASH_TABLE FilterTable; // THe directory filter table.
  819. BOOL StopIo; // True means StopIo requested.
  820. BOOL IoActive; // True means I/O active on volume.
  821. ULONG JournalState; // Current journal state.
  822. ULONG ReferenceCount; // Free all hash tables when it hits 0.
  823. LONG ActiveIoRequests;// Number of Journal reads currently outstanding.
  824. FILE_OBJECTID_BUFFER RootDirObjectId; // Object ID for volume
  825. FILE_FS_VOLUME_INFORMATION FSVolInfo; // NT volume info.
  826. CHAR FSVolLabel[MAXIMUM_VOLUME_LABEL_LENGTH];
  827. } VOLUME_MONITOR_ENTRY, *PVOLUME_MONITOR_ENTRY;
  828. */
  829. {
  830. dprintf("Dumping OUT_LOG_PARTNER.\n\n");
  831. dprintf("Header : Address ( 0x%x )\n",pVme->Header);
  832. dprintf("ListEntry : Address ( 0x%x )\n",pVme->ListEntry);
  833. dprintf("WStatus : 0x%x\n",pVme->WStatus);
  834. dprintf("ActiveReplicas : %d\n" ,pVme->ActiveReplicas);
  835. dprintf("Event Handle for pause : 0x%x\n",pVme->Event);
  836. dprintf("VolumeHandle : 0x%x\n",pVme->VolumeHandle);
  837. dprintf("DriveLetter : %ws\n" ,pVme->DriveLetter);
  838. dprintf("StopIo (bool) : 0x%x\n",pVme->StopIo);
  839. dprintf("IoActive (bool) : 0x%x\n",pVme->IoActive);
  840. dprintf("JournalState : 0x%x\n",pVme->JournalState);
  841. dprintf("ReferenceCount : %d\n" ,pVme->ReferenceCount);
  842. dprintf("ActiveIoRequests : %d\n" ,pVme->ActiveIoRequests);
  843. dprintf("FSVolLabel : %s\n" ,pVme->FSVolLabel);
  844. }
  845. //
  846. // Version info
  847. //
  848. #if DBG
  849. USHORT SavedMajorVersion = 0x0c;
  850. #else
  851. USHORT SavedMajorVersion;
  852. #endif
  853. EXT_API_VERSION ApiVersion = { 3, 5, EXT_API_VERSION_NUMBER, 0 };
  854. USHORT SavedMinorVersion = VER_PRODUCTBUILD;
  855. BOOL ChkTarget; // is debuggee a CHK build?
  856. VOID
  857. WinDbgExtensionDllInit(
  858. PWINDBG_EXTENSION_APIS lpExtensionApis,
  859. USHORT MajorVersion,
  860. USHORT MinorVersion
  861. )
  862. {
  863. fKD = 1;
  864. ExtensionApis = *lpExtensionApis ;
  865. SavedMajorVersion = MajorVersion;
  866. SavedMinorVersion = MinorVersion;
  867. ChkTarget = SavedMajorVersion == 0x0c ? TRUE : FALSE;
  868. }
  869. DECLARE_API( help )
  870. {
  871. INIT_DPRINTF();
  872. if (lpArgumentString[0] == '\0') {
  873. dprintf("\n");
  874. dprintf("FRS Debugger extensions help:\n\n");
  875. dprintf("%20s - CHANGE_ORDER_ENTRY\n","coe");
  876. dprintf("%20s - CHANGE_ORDER_COMMAND\n","coc");
  877. dprintf("%20s - CXTION\n","cxt");
  878. dprintf("%20s - OUT_LOG_PARTNER\n","olp");
  879. dprintf("%20s - REPLICA\n","rep");
  880. dprintf("%20s - VME\n","vme");
  881. dprintf("\n");
  882. }
  883. }
  884. DECLARE_API( version )
  885. {
  886. INIT_DPRINTF();
  887. if (fKD)
  888. {
  889. dprintf(
  890. "FRS Extension dll for Build %d debugging %s kernel for Build %d\n",
  891. VER_PRODUCTBUILD,
  892. SavedMajorVersion == 0x0c ? "Checked" : "Free",
  893. SavedMinorVersion
  894. );
  895. }
  896. else
  897. {
  898. dprintf(
  899. "FRS Extension dll for Build %d\n",
  900. VER_PRODUCTBUILD
  901. );
  902. }
  903. }
  904. DECLARE_API( coe )
  905. {
  906. ULONG_PTR dwAddr;
  907. INIT_DPRINTF();
  908. dwAddr = GetExpression(lpArgumentString);
  909. if ( !dwAddr ) {
  910. dprintf("Error: can't evaluate '%s'\n", lpArgumentString);
  911. return;
  912. }
  913. BOOL b;
  914. char block[sizeof(CHANGE_ORDER_ENTRY)];
  915. b = GetData(dwAddr, &block, sizeof(block), NULL);
  916. if ( !b ) {
  917. dprintf("can't read %p, error 0x%lx\n", dwAddr, GetLastError());
  918. return;
  919. }
  920. do_coe((CHANGE_ORDER_ENTRY *) block);
  921. }
  922. DECLARE_API( coc )
  923. {
  924. ULONG_PTR dwAddr;
  925. INIT_DPRINTF();
  926. dwAddr = GetExpression(lpArgumentString);
  927. if ( !dwAddr ) {
  928. dprintf("Error: can't evaluate '%s'\n", lpArgumentString);
  929. return;
  930. }
  931. BOOL b;
  932. char block[sizeof(CHANGE_ORDER_COMMAND)];
  933. b = GetData(dwAddr, &block, sizeof(block), NULL);
  934. if ( !b ) {
  935. dprintf("can't read %p, error 0x%lx\n", dwAddr, GetLastError());
  936. return;
  937. }
  938. do_coc((CHANGE_ORDER_COMMAND *) block);
  939. }
  940. DECLARE_API( cxt )
  941. {
  942. ULONG_PTR dwAddr;
  943. INIT_DPRINTF();
  944. dwAddr = GetExpression(lpArgumentString);
  945. if ( !dwAddr ) {
  946. dprintf("Error: can't evaluate '%s'\n", lpArgumentString);
  947. return;
  948. }
  949. BOOL b;
  950. char block[sizeof(CXTION)];
  951. b = GetData(dwAddr, &block, sizeof(block), NULL);
  952. if ( !b ) {
  953. dprintf("can't read %p, error 0x%lx\n", dwAddr, GetLastError());
  954. return;
  955. }
  956. do_cxt((CXTION *) block);
  957. }
  958. DECLARE_API( olp )
  959. {
  960. ULONG_PTR dwAddr;
  961. INIT_DPRINTF();
  962. dwAddr = GetExpression(lpArgumentString);
  963. if ( !dwAddr ) {
  964. dprintf("Error: can't evaluate '%s'\n", lpArgumentString);
  965. return;
  966. }
  967. BOOL b;
  968. char block[sizeof(OUT_LOG_PARTNER)];
  969. b = GetData(dwAddr, &block, sizeof(block), NULL);
  970. if ( !b ) {
  971. dprintf("can't read %p, error 0x%lx\n", dwAddr, GetLastError());
  972. return;
  973. }
  974. do_olp((OUT_LOG_PARTNER *) block);
  975. }
  976. DECLARE_API( vme )
  977. {
  978. ULONG_PTR dwAddr;
  979. INIT_DPRINTF();
  980. dwAddr = GetExpression(lpArgumentString);
  981. if ( !dwAddr ) {
  982. dprintf("Error: can't evaluate '%s'\n", lpArgumentString);
  983. return;
  984. }
  985. BOOL b;
  986. char block[sizeof(VOLUME_MONITOR_ENTRY)];
  987. b = GetData(dwAddr, &block, sizeof(block), NULL);
  988. if ( !b ) {
  989. dprintf("can't read %p, error 0x%lx\n", dwAddr, GetLastError());
  990. return;
  991. }
  992. do_vme((VOLUME_MONITOR_ENTRY *) block);
  993. }
  994. DECLARE_API( rep )
  995. {
  996. ULONG_PTR dwAddr;
  997. INIT_DPRINTF();
  998. dwAddr = GetExpression(lpArgumentString);
  999. if ( !dwAddr ) {
  1000. dprintf("Error: can't evaluate '%s'\n", lpArgumentString);
  1001. return;
  1002. }
  1003. BOOL b;
  1004. char block[sizeof(REPLICA)];
  1005. b = GetData(dwAddr, &block, sizeof(block), NULL);
  1006. if ( !b ) {
  1007. dprintf("can't read %p, error 0x%lx\n", dwAddr, GetLastError());
  1008. return;
  1009. }
  1010. do_rep((REPLICA *) block);
  1011. }
  1012. LPEXT_API_VERSION
  1013. ExtensionApiVersion(
  1014. VOID
  1015. )
  1016. {
  1017. return &ApiVersion;
  1018. }