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.

651 lines
25 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. DbgPrint.cxx
  5. Abstract:
  6. Functions for printing debug information
  7. Author:
  8. Kamen Moutafov (kamenm) Dec 99 - Feb 2000
  9. Revision History:
  10. --*/
  11. #include <precomp.hxx>
  12. #include <wincrypt.h>
  13. #include <rpctrans.hxx>
  14. void PrintTimeInSeconds(RPC_CHAR *HeaderString, DWORD TimeInMilliseconds,
  15. PRPCDEBUG_OUTPUT_ROUTINE PrintRoutine)
  16. {
  17. PrintRoutine("%S (in seconds since boot):%d.%d (0x%X.%X)\n", HeaderString,
  18. TimeInMilliseconds / 1000, TimeInMilliseconds % 1000,
  19. TimeInMilliseconds / 1000, TimeInMilliseconds % 1000);
  20. }
  21. void PrintDebugCellID(RPC_CHAR *HeaderString, DebugCellID CellID,
  22. PRPCDEBUG_OUTPUT_ROUTINE PrintRoutine)
  23. {
  24. PrintRoutine("%S: 0x%X.%X\n", HeaderString, CellID.SectionID, CellID.CellID);
  25. }
  26. const RPC_CHAR *CallStatusStrings[] = {L"Allocated", L"Active", L"Dispatched"};
  27. #define UnknownValueLiteral (L"Unknown/Invalid")
  28. const RPC_CHAR *UnknownValue = UnknownValueLiteral;
  29. const RPC_CHAR *ConnectionAuthLevelStrings[] = {L"Default", L"None", L"Connect", L"Call", L"Packet",
  30. L"Packet Integrity", L"Packet Privacy", UnknownValueLiteral, UnknownValueLiteral};
  31. const RPC_CHAR *ConnectionAuthServiceStrings[] = {L"None", L"NTLM", L"Kerberos/Snego", L"Other"};
  32. const RPC_CHAR *ProtocolSequenceStrings[] = {L"TCP", L"UDP", L"LRPC", UnknownValueLiteral, UnknownValueLiteral,
  33. L"SPX", UnknownValueLiteral, L"IPX", L"NMP", UnknownValueLiteral, UnknownValueLiteral, L"NB",
  34. UnknownValueLiteral, UnknownValueLiteral, UnknownValueLiteral, L"DSP", L"DDP", UnknownValueLiteral,
  35. UnknownValueLiteral, L"SPP", UnknownValueLiteral, UnknownValueLiteral,
  36. L"MQ", UnknownValueLiteral, L"HTTP"};
  37. const int FirstProtocolSequenceTowerID = TCP_TOWER_ID;
  38. const int LastProtocolSequenceTowerID = HTTP_TOWER_ID;
  39. RPC_CHAR *GetProtocolSequenceString(int ProtocolSequenceID)
  40. {
  41. RPC_CHAR *CurrentString;
  42. if ((ProtocolSequenceID < FirstProtocolSequenceTowerID)
  43. || (ProtocolSequenceID > LastProtocolSequenceTowerID))
  44. {
  45. CurrentString = (RPC_CHAR *) UnknownValue;
  46. }
  47. else
  48. {
  49. CurrentString = (RPC_CHAR *) ProtocolSequenceStrings[
  50. ProtocolSequenceID - FirstProtocolSequenceTowerID];
  51. }
  52. ASSERT(CurrentString != NULL);
  53. return CurrentString;
  54. }
  55. void PrintCallInfoHeader(PRPCDEBUG_OUTPUT_ROUTINE PrintRoutine)
  56. {
  57. PrintRoutine("PID CELL ID ST PNO IFSTART THRDCELL CALLFLAG CALLID LASTTIME CONN/CLN\n");
  58. PrintRoutine("----------------------------------------------------------------------------\n");
  59. }
  60. void PrintCallInfoBody(IN DWORD ProcessID, IN DebugCellID CellID,
  61. IN DebugCallInfo *CallInfo, PRPCDEBUG_OUTPUT_ROUTINE PrintRoutine)
  62. {
  63. PrintRoutine("%04x %04x.%04x %02x %03x %08lx %04x.%04x %08lx %08lx %08lx ",
  64. ProcessID, CellID.SectionID, CellID.CellID, CallInfo->Status,
  65. CallInfo->ProcNum, CallInfo->InterfaceUUIDStart,
  66. CallInfo->ServicingTID.SectionID, CallInfo->ServicingTID.CellID,
  67. CallInfo->CallFlags, CallInfo->CallID, CallInfo->LastUpdateTime);
  68. if (CallInfo->CallFlags & DBGCELL_LRPC_CALL)
  69. {
  70. PrintRoutine("%04x.%04x\n", (DWORD)CallInfo->PID, (DWORD)CallInfo->TID);
  71. }
  72. else
  73. {
  74. PrintRoutine("%04x.%04x\n", (DWORD)CallInfo->Connection.SectionID,
  75. (DWORD)CallInfo->Connection.CellID);
  76. }
  77. }
  78. void GetAndPrintCallInfo(IN DWORD CallID OPTIONAL, IN DWORD IfStart OPTIONAL,
  79. IN int ProcNum OPTIONAL, IN DWORD ProcessID OPTIONAL,
  80. PRPCDEBUG_OUTPUT_ROUTINE PrintRoutine)
  81. {
  82. CallInfoEnumerationHandle h;
  83. RPC_STATUS Status;
  84. DebugCallInfo *NextCall;
  85. DebugCellID CellID;
  86. DWORD CurrentPID;
  87. PrintRoutine("Searching for call info ...\n");
  88. Status = OpenRPCDebugCallInfoEnumeration(CallID, IfStart, ProcNum, ProcessID, &h);
  89. if (Status != RPC_S_OK)
  90. {
  91. PrintRoutine("OpenRPCDebugCallInfoEnumeration failed: %d\n", Status);
  92. return;
  93. }
  94. PrintCallInfoHeader(PrintRoutine);
  95. do
  96. {
  97. Status = GetNextRPCDebugCallInfo(h, &NextCall, &CellID, &CurrentPID);
  98. if (Status == RPC_S_OK)
  99. {
  100. PrintCallInfoBody(CurrentPID, CellID, NextCall, PrintRoutine);
  101. /*
  102. // print the information we obtained
  103. PrintRoutine("%04x %04x.%04x %02x %03x %08lx %04x.%04x %08lx %08lx %08lx ",
  104. CurrentPID, CellID.SectionID, CellID.CellID, NextCall->Status,
  105. NextCall->ProcNum, NextCall->InterfaceUUIDStart,
  106. NextCall->ServicingTID.SectionID, NextCall->ServicingTID.CellID,
  107. NextCall->CallFlags, NextCall->CallID, NextCall->LastUpdateTime);
  108. if (NextCall->CallFlags & DBGCELL_LRPC_CALL)
  109. {
  110. PrintRoutine("%04x.%04x\n", (DWORD)NextCall->PID, (DWORD)NextCall->TID);
  111. }
  112. else
  113. {
  114. PrintRoutine("%04x.%04x\n", (DWORD)NextCall->Connection.SectionID,
  115. (DWORD)NextCall->Connection.CellID);
  116. }
  117. */
  118. }
  119. }
  120. while (Status == RPC_S_OK);
  121. if (Status != RPC_S_DBG_ENUMERATION_DONE)
  122. {
  123. PrintRoutine("Enumeration aborted with error %d\n", Status);
  124. }
  125. FinishRPCDebugCallInfoEnumeration(&h);
  126. }
  127. void PrintDbgCellInfo(IN DebugCellUnion *Container, IN DebugCellUnion *EndpointContainer OPTIONAL,
  128. PRPCDEBUG_OUTPUT_ROUTINE PrintRoutine)
  129. {
  130. RPC_CHAR *CurrentString;
  131. DWORD LocalFlags;
  132. BOOL fFirstTime;
  133. char EndpointString[DebugEndpointNameLength + 1];
  134. int ConnectionAuthLevel;
  135. int ConnectionAuthService;
  136. HANDLE LocalIPAddress;
  137. HANDLE LocalIPAddress2;
  138. int i;
  139. HANDLE LocalIPAddressElement;
  140. HANDLE LocalSessionID;
  141. switch(Container->genericCell.Type)
  142. {
  143. case dctFree:
  144. PrintRoutine("Free cell\n");
  145. break;
  146. case dctCallInfo:
  147. PrintRoutine("Call\n");
  148. if ((Container->callInfo.Status < CallStatusFirst)
  149. || (Container->callInfo.Status > CallStatusLast))
  150. {
  151. CurrentString = (RPC_CHAR *)UnknownValue;
  152. }
  153. else
  154. {
  155. CurrentString = (RPC_CHAR *)CallStatusStrings[Container->callInfo.Status];
  156. }
  157. PrintRoutine("Status: %S\n", CurrentString);
  158. PrintRoutine("Procedure Number: %d\n", Container->callInfo.ProcNum);
  159. PrintRoutine("Interface UUID start (first DWORD only): %X\n", Container->callInfo.InterfaceUUIDStart);
  160. PrintRoutine("Call ID: 0x%x (%d)\n", Container->callInfo.CallID, Container->callInfo.CallID);
  161. PrintDebugCellID(L"Servicing thread identifier", Container->callInfo.ServicingTID, PrintRoutine);
  162. PrintRoutine("Call Flags:");
  163. LocalFlags = Container->callInfo.CallFlags;
  164. fFirstTime = TRUE;
  165. if (LocalFlags & DBGCELL_CACHED_CALL)
  166. {
  167. PrintRoutine(" cached");
  168. fFirstTime = FALSE;
  169. }
  170. if (LocalFlags & DBGCELL_ASYNC_CALL)
  171. {
  172. if (fFirstTime == FALSE)
  173. {
  174. PrintRoutine(", ");
  175. }
  176. PrintRoutine("async");
  177. fFirstTime = FALSE;
  178. }
  179. if (LocalFlags & DBGCELL_PIPE_CALL)
  180. {
  181. if (fFirstTime == FALSE)
  182. {
  183. PrintRoutine(", ");
  184. }
  185. PrintRoutine("pipe");
  186. fFirstTime = FALSE;
  187. }
  188. if (LocalFlags & DBGCELL_LRPC_CALL)
  189. {
  190. if (fFirstTime == FALSE)
  191. {
  192. PrintRoutine(", ");
  193. }
  194. PrintRoutine("LRPC");
  195. fFirstTime = FALSE;
  196. }
  197. if (fFirstTime == TRUE)
  198. {
  199. PrintRoutine("none");
  200. }
  201. PrintRoutine("\n");
  202. PrintTimeInSeconds(L"Last update time", Container->callInfo.LastUpdateTime, PrintRoutine);
  203. if (LocalFlags & DBGCELL_LRPC_CALL)
  204. {
  205. PrintRoutine("Caller (PID/TID) is: %x.%x (%d.%d)\n", Container->callInfo.PID,
  206. Container->callInfo.TID, Container->callInfo.PID, Container->callInfo.TID);
  207. }
  208. else
  209. PrintDebugCellID(L"Owning connection identifier", Container->callInfo.Connection, PrintRoutine);
  210. break;
  211. case dctThreadInfo:
  212. PrintRoutine("Thread\n");
  213. PrintRoutine("Status: ");
  214. switch (Container->threadInfo.Status)
  215. {
  216. case dtsProcessing:
  217. PrintRoutine("Processing\n");
  218. break;
  219. case dtsDispatched:
  220. PrintRoutine("Dispatched\n");
  221. break;
  222. case dtsAllocated:
  223. PrintRoutine("Allocated\n");
  224. break;
  225. case dtsIdle:
  226. PrintRoutine("Idle\n");
  227. break;
  228. default:
  229. PrintRoutine("Unknown (%d)\n", Container->threadInfo.Status);
  230. }
  231. PrintRoutine("Thread ID: 0x%X (%d)\n", Container->threadInfo.TID, Container->threadInfo.TID);
  232. if ((Container->threadInfo.Endpoint.CellID == 0) && (Container->threadInfo.Endpoint.SectionID == 0))
  233. {
  234. PrintRoutine("Thread is an IO completion thread\n");
  235. }
  236. else
  237. {
  238. PrintDebugCellID(L"Associated Endpoint:", Container->threadInfo.Endpoint, PrintRoutine);
  239. }
  240. PrintTimeInSeconds(L"Last update time", Container->threadInfo.LastUpdateTime, PrintRoutine);
  241. break;
  242. case dctEndpointInfo:
  243. PrintRoutine("Endpoint\n");
  244. PrintRoutine("Status: ");
  245. switch (Container->endpointInfo.Status)
  246. {
  247. case desAllocated:
  248. PrintRoutine("Allocated\n");
  249. break;
  250. case desActive:
  251. PrintRoutine("Active\n");
  252. break;
  253. case desInactive:
  254. PrintRoutine("Inactive\n");
  255. break;
  256. default:
  257. PrintRoutine("Unknown (%d)\n", Container->endpointInfo.Status);
  258. }
  259. CurrentString = GetProtocolSequenceString(Container->endpointInfo.ProtseqType);
  260. PrintRoutine("Protocol Sequence: %S\n", CurrentString);
  261. memcpy(EndpointString, Container->endpointInfo.EndpointName,
  262. sizeof(Container->endpointInfo.EndpointName));
  263. EndpointString[DebugEndpointNameLength] = 0;
  264. PrintRoutine("Endpoint name: %s\n", EndpointString);
  265. break;
  266. case dctClientCallInfo:
  267. PrintRoutine("Client call info\n");
  268. PrintRoutine("Procedure number: %d\n", Container->clientCallInfo.ProcNum);
  269. PrintRoutine("Interface UUID start (first DWORD only): %X\n", Container->clientCallInfo.IfStart);
  270. PrintRoutine("Call ID: 0x%x (%d)\n", Container->clientCallInfo.CallID,
  271. Container->clientCallInfo.CallID);
  272. PrintDebugCellID(L"Calling thread identifier", Container->clientCallInfo.ServicingThread,
  273. PrintRoutine);
  274. PrintDebugCellID(L"Call target identifier", Container->clientCallInfo.CallTargetID, PrintRoutine);
  275. ASSERT(sizeof(Container->clientCallInfo.Endpoint) < sizeof(EndpointString));
  276. memcpy(EndpointString, Container->clientCallInfo.Endpoint, sizeof(Container->clientCallInfo.Endpoint));
  277. EndpointString[ClientCallEndpointLength] = 0;
  278. PrintRoutine("Call target endpoint: %s\n", EndpointString);
  279. break;
  280. case dctCallTargetInfo:
  281. PrintRoutine("Call target info\n");
  282. CurrentString = GetProtocolSequenceString(Container->callTargetInfo.ProtocolSequence);
  283. PrintRoutine("Protocol Sequence: %S\n", CurrentString);
  284. PrintTimeInSeconds(L"Last update time", Container->callTargetInfo.LastUpdateTime, PrintRoutine);
  285. ASSERT(sizeof(Container->callTargetInfo.TargetServer) < sizeof(EndpointString));
  286. memcpy(EndpointString, Container->callTargetInfo.TargetServer,
  287. sizeof(Container->callTargetInfo.TargetServer));
  288. EndpointString[sizeof(Container->callTargetInfo.TargetServer)] = 0;
  289. PrintRoutine("Target server is: %s\n", EndpointString);
  290. break;
  291. case dctConnectionInfo:
  292. PrintRoutine("Connection\n");
  293. LocalFlags = Container->connectionInfo.Flags;
  294. fFirstTime = TRUE;
  295. PrintRoutine("Connection flags: ");
  296. if (LocalFlags & 1)
  297. {
  298. PrintRoutine("Exclusive\n");
  299. }
  300. else
  301. {
  302. PrintRoutine("None\n");
  303. }
  304. ConnectionAuthLevel =
  305. (Container->connectionInfo.Flags & ConnectionAuthLevelMask) >> ConnectionAuthLevelShift;
  306. ConnectionAuthService =
  307. (Container->connectionInfo.Flags & ConnectionAuthServiceMask) >> ConnectionAuthServiceShift;
  308. PrintRoutine("Authentication Level: %S\n", ConnectionAuthLevelStrings[ConnectionAuthLevel]);
  309. PrintRoutine("Authentication Service: %S\n", ConnectionAuthServiceStrings[ConnectionAuthService]);
  310. PrintRoutine("Last Transmit Fragment Size: %d (0x%X)\n",
  311. Container->connectionInfo.LastTransmitFragmentSize);
  312. PrintDebugCellID(L"Endpoint for the connection", Container->connectionInfo.Endpoint, PrintRoutine);
  313. PrintTimeInSeconds(L"Last send time", Container->connectionInfo.LastSendTime, PrintRoutine);
  314. PrintTimeInSeconds(L"Last receive time", Container->connectionInfo.LastReceiveTime, PrintRoutine);
  315. PrintRoutine("Getting endpoint info ...\n");
  316. switch(EndpointContainer->endpointInfo.ProtseqType)
  317. {
  318. case TCP_TOWER_ID:
  319. case UDP_TOWER_ID:
  320. case HTTP_TOWER_ID:
  321. // IP address of some sort
  322. PrintRoutine("Caller is");
  323. LocalIPAddress = Container->connectionInfo.ConnectionID[1];
  324. LocalIPAddress2 = Container->connectionInfo.ConnectionID[0];
  325. if (LocalIPAddress2 == 0)
  326. {
  327. PrintRoutine("(IPv4): ");
  328. for (i = 0; i < 4; i ++)
  329. {
  330. LocalIPAddressElement = (HANDLE)((ULONGLONG)LocalIPAddress & 0xFF);
  331. LocalIPAddress = (HANDLE)((ULONGLONG)LocalIPAddress >> 8);
  332. PrintRoutine("%d", HandleToUlong(LocalIPAddressElement));
  333. if (i < 3)
  334. {
  335. PrintRoutine(".");
  336. }
  337. else
  338. {
  339. PrintRoutine("\n");
  340. }
  341. }
  342. }
  343. else
  344. {
  345. PrintRoutine("(IPv6 - last two DWORDS): ");
  346. PrintRoutine("%d::%d\n", HandleToUlong(LocalIPAddress2), HandleToULong(LocalIPAddress));
  347. }
  348. break;
  349. case NMP_TOWER_ID:
  350. LocalSessionID = Container->connectionInfo.ConnectionID[0];
  351. if (LocalSessionID)
  352. {
  353. PrintRoutine("Cannot determine caller for remote named pipes\n");
  354. }
  355. else
  356. {
  357. LocalSessionID = Container->connectionInfo.ConnectionID[1];
  358. PrintRoutine("Process object for caller is 0x%X\n", LocalSessionID);
  359. }
  360. break;
  361. default:
  362. CurrentString = GetProtocolSequenceString(EndpointContainer->endpointInfo.ProtseqType);
  363. PrintRoutine("Cannot determine caller for this type of protocol sequence %S (%d)\n",
  364. CurrentString, EndpointContainer->endpointInfo.ProtseqType);
  365. }
  366. break;
  367. case dctUsedGeneric:
  368. break;
  369. default:
  370. PrintRoutine("Invalid cell type: %d\n", Container->genericCell.Type);
  371. }
  372. }
  373. void GetAndPrintDbgCellInfo(DWORD ProcessID, DebugCellID CellID,
  374. PRPCDEBUG_OUTPUT_ROUTINE PrintRoutine)
  375. {
  376. DebugCellUnion Container;
  377. DebugCellUnion EndpointContainer;
  378. RPC_STATUS Status;
  379. PrintRoutine("Getting cell info ...\n");
  380. Status = GetCellByDebugCellID(ProcessID, CellID, &Container);
  381. if (Status != RPC_S_OK)
  382. {
  383. PrintRoutine("Getting cell info failed with error %d\n", Status);
  384. return;
  385. }
  386. if (Container.genericCell.Type == dctConnectionInfo)
  387. {
  388. Status = GetCellByDebugCellID(ProcessID, Container.connectionInfo.Endpoint, &EndpointContainer);
  389. if (Status != RPC_S_OK)
  390. {
  391. PrintRoutine("Getting endpoint info failed with error %d\n", Status);
  392. return;
  393. }
  394. }
  395. PrintDbgCellInfo(&Container, &EndpointContainer, PrintRoutine);
  396. }
  397. void PrintEndpointInfoHeader(PRPCDEBUG_OUTPUT_ROUTINE PrintRoutine)
  398. {
  399. PrintRoutine("PID CELL ID ST PROTSEQ ENDPOINT \n");
  400. PrintRoutine("-------------------------------------------------------------\n");
  401. }
  402. void PrintEndpointInfoBody(IN DWORD ProcessID, IN DebugCellID CellID,
  403. IN DebugEndpointInfo *EndpointInfo, PRPCDEBUG_OUTPUT_ROUTINE PrintRoutine)
  404. {
  405. RPC_CHAR *ProtseqName;
  406. char CurrentEndpoint[DebugEndpointNameLength + 1];
  407. ProtseqName = GetProtocolSequenceString(EndpointInfo->ProtseqType);
  408. CurrentEndpoint[DebugEndpointNameLength] = 0;
  409. memcpy(CurrentEndpoint, EndpointInfo->EndpointName, DebugEndpointNameLength);
  410. // print the information we obtained
  411. PrintRoutine("%04x %04x.%04x %02x %14S %s\n",
  412. ProcessID, CellID.SectionID, CellID.CellID, EndpointInfo->Status,
  413. ProtseqName, CurrentEndpoint);
  414. }
  415. void GetAndPrintEndpointInfo(IN char *Endpoint OPTIONAL, PRPCDEBUG_OUTPUT_ROUTINE PrintRoutine)
  416. {
  417. DWORD CurrentPID;
  418. RPC_STATUS Status;
  419. DebugEndpointInfo *NextEndpoint;
  420. EndpointInfoEnumerationHandle h;
  421. DebugCellID CellID;
  422. PrintRoutine("Searching for endpoint info ...\n");
  423. Status = OpenRPCDebugEndpointInfoEnumeration(Endpoint, &h);
  424. if (Status != RPC_S_OK)
  425. {
  426. PrintRoutine("OpenRPCDebugEndpointInfoEnumeration failed: %d\n", Status);
  427. return;
  428. }
  429. PrintEndpointInfoHeader(PrintRoutine);
  430. do
  431. {
  432. Status = GetNextRPCDebugEndpointInfo(h, &NextEndpoint, &CellID, &CurrentPID);
  433. if (Status == RPC_S_OK)
  434. {
  435. PrintEndpointInfoBody(CurrentPID, CellID, NextEndpoint, PrintRoutine);
  436. }
  437. }
  438. while (Status == RPC_S_OK);
  439. if (Status != RPC_S_DBG_ENUMERATION_DONE)
  440. {
  441. PrintRoutine("Enumeration aborted with error %d\n", Status);
  442. }
  443. FinishRPCDebugEndpointInfoEnumeration(&h);
  444. }
  445. void PrintThreadInfoHeader(PRPCDEBUG_OUTPUT_ROUTINE PrintRoutine)
  446. {
  447. PrintRoutine("PID CELL ID ST TID ENDPOINT LASTTIME\n");
  448. PrintRoutine("---------------------------------------------\n");
  449. }
  450. void PrintThreadInfoBody(IN DWORD ProcessID, IN DebugCellID CellID,
  451. IN DebugThreadInfo *ThreadInfo, PRPCDEBUG_OUTPUT_ROUTINE PrintRoutine)
  452. {
  453. // print the information we obtained
  454. PrintRoutine("%04x %04x.%04x %02x %08x %04x.%04x %08x\n",
  455. ProcessID, CellID.SectionID, CellID.CellID, ThreadInfo->Status,
  456. ThreadInfo->TID, ThreadInfo->Endpoint.SectionID,
  457. ThreadInfo->Endpoint.CellID, ThreadInfo->LastUpdateTime);
  458. }
  459. void GetAndPrintThreadInfo(DWORD ProcessID, DWORD ThreadID OPTIONAL, PRPCDEBUG_OUTPUT_ROUTINE PrintRoutine)
  460. {
  461. DebugThreadInfo *NextThread;
  462. RPC_STATUS Status;
  463. ThreadInfoEnumerationHandle h;
  464. DebugCellID CellID;
  465. DWORD CurrentPID;
  466. PrintRoutine("Searching for thread info ...\n");
  467. Status = OpenRPCDebugThreadInfoEnumeration(ProcessID, ThreadID, &h);
  468. if (Status != RPC_S_OK)
  469. {
  470. PrintRoutine("OpenRPCDebugThreadInfoEnumeration failed: %d\n", Status);
  471. return;
  472. }
  473. PrintThreadInfoHeader(PrintRoutine);
  474. do
  475. {
  476. Status = GetNextRPCDebugThreadInfo(h, &NextThread, &CellID, &CurrentPID);
  477. if (Status == RPC_S_OK)
  478. {
  479. PrintThreadInfoBody(CurrentPID, CellID, NextThread, PrintRoutine);
  480. }
  481. }
  482. while (Status == RPC_S_OK);
  483. if (Status != RPC_S_DBG_ENUMERATION_DONE)
  484. {
  485. PrintRoutine("Enumeration aborted with error %d\n", Status);
  486. }
  487. FinishRPCDebugThreadInfoEnumeration(&h);
  488. }
  489. void PrintClientCallInfoHeader(PRPCDEBUG_OUTPUT_ROUTINE PrintRoutine)
  490. {
  491. PrintRoutine("PID CELL ID PNO IFSTART TIDNUMBER CALLID LASTTIME PS CLTNUMBER ENDPOINT\n");
  492. PrintRoutine("------------------------------------------------------------------------------\n");
  493. }
  494. void PrintClientCallInfoBody(IN DWORD ProcessID, IN DebugCellID CellID,
  495. IN DebugClientCallInfo *ClientCallInfo,
  496. IN DebugCallTargetInfo *CallTargetInfo,
  497. PRPCDEBUG_OUTPUT_ROUTINE PrintRoutine)
  498. {
  499. char TempString[DebugEndpointNameLength + 1];
  500. ASSERT(sizeof(TempString) > sizeof(CallTargetInfo->TargetServer));
  501. ASSERT(sizeof(TempString) > sizeof(ClientCallInfo->Endpoint));
  502. memcpy(TempString, ClientCallInfo->Endpoint, sizeof(ClientCallInfo->Endpoint));
  503. TempString[sizeof(ClientCallInfo->Endpoint)] = 0;
  504. // print the information we obtained
  505. PrintRoutine("%04x %04x.%04x %04x %08lx %04x.%04x %08lx %08lx %02x %04x.%04x %s\n",
  506. ProcessID, CellID.SectionID, CellID.CellID, ClientCallInfo->ProcNum,
  507. ClientCallInfo->IfStart, ClientCallInfo->ServicingThread.SectionID,
  508. ClientCallInfo->ServicingThread.CellID, ClientCallInfo->CallID,
  509. CallTargetInfo->LastUpdateTime, CallTargetInfo->ProtocolSequence,
  510. ClientCallInfo->CallTargetID.SectionID, ClientCallInfo->CallTargetID.CellID,
  511. TempString);
  512. }
  513. void GetAndPrintClientCallInfo(IN DWORD CallID OPTIONAL, IN DWORD IfStart OPTIONAL,
  514. IN int ProcNum OPTIONAL, IN DWORD ProcessID OPTIONAL,
  515. PRPCDEBUG_OUTPUT_ROUTINE PrintRoutine)
  516. {
  517. DWORD CurrentPID;
  518. DebugCellID CellID;
  519. DebugClientCallInfo *NextClientCall;
  520. DebugCallTargetInfo *NextCallTarget;
  521. RPC_STATUS Status;
  522. CallInfoEnumerationHandle h;
  523. PrintRoutine("Searching for call info ...\n");
  524. Status = OpenRPCDebugClientCallInfoEnumeration(CallID, IfStart, ProcNum, ProcessID, &h);
  525. if (Status != RPC_S_OK)
  526. {
  527. PrintRoutine("OpenRPCDebugClientCallInfoEnumeration failed: %d\n", Status);
  528. return;
  529. }
  530. PrintClientCallInfoHeader(PrintRoutine);
  531. do
  532. {
  533. Status = GetNextRPCDebugClientCallInfo(h, &NextClientCall, &NextCallTarget, &CellID, &CurrentPID);
  534. if (Status == RPC_S_OK)
  535. {
  536. if ((NextCallTarget != NULL) && (NextCallTarget->Type != dctCallTargetInfo))
  537. {
  538. PrintRoutine("Inconsistent information detected - skipping ...\n");
  539. continue;
  540. }
  541. PrintClientCallInfoBody(CurrentPID, CellID, NextClientCall, NextCallTarget,
  542. PrintRoutine);
  543. }
  544. }
  545. while (Status == RPC_S_OK);
  546. if (Status != RPC_S_DBG_ENUMERATION_DONE)
  547. {
  548. PrintRoutine("Enumeration aborted with error %d\n", Status);
  549. }
  550. FinishRPCDebugClientCallInfoEnumeration(&h);
  551. }