Source code of Windows XP (NT5)
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.

1198 lines
36 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. RpcDbg.cxx
  5. Abstract:
  6. RPC Extended Debugging Utility
  7. Author:
  8. Kamen Moutafov (kamenm) 11-30-99
  9. Revision History:
  10. --*/
  11. #include <sysinc.h>
  12. #include <CellDef.hxx>
  13. // Usage
  14. const char *USAGE = "-s <server> -p <protseq> -C <CallID> -I <IfStart>\n"
  15. "-N <ProcNum> -P <ProcessID> -L <CellID1.CellID2>\n"
  16. "-E <EndpointName> -T <ThreadID> -r <radix> -c -l -e -t -a\n"
  17. "Exactly one of -c, -l, -e, -t, or -a have to be specified.\n"
  18. "The valid combinations are:\n"
  19. "-c [-C <CallID>] [-I <IfStart>] [-N <ProcNum>] [-P <ProcessID>]\n"
  20. "-l -P <ProcessID> -L <CellID1.CellID2>\n"
  21. "-e -E <EndpointName>\n"
  22. "-t -P <ProcessID> [-T <ThreadID>]\n"
  23. "-a [-C <CallID>] [-I <IfStart>] [-N <ProcNum>] [-P <ProcessID>]\n"
  24. "-s, -p and -r are independent to the other options. -r affects"
  25. "only options after it on the command line. Default is 16 (hex)";
  26. // Error stuff
  27. #define CHECK_RET(status, string) if (status)\
  28. { printf("%s failed -- %lu (0x%08X)\n", string,\
  29. (unsigned long)status, (unsigned long)status);\
  30. return (status); }
  31. DWORD CallID = 0;
  32. DWORD IfStart = 0;
  33. DWORD ProcNum = RPCDBG_NO_PROCNUM_SPECIFIED;
  34. DWORD ProcessID = 0;
  35. DebugCellID CellID = {0, 0};
  36. char *EndpointName = NULL;
  37. DWORD ThreadID = 0;
  38. char *Protseq = "ncacn_np";
  39. char *NetworkAddr = NULL;
  40. int radix = 16;
  41. char *BindingEndpoint = 0;
  42. enum tagChosenDebugAction
  43. {
  44. cdaInvalid,
  45. cdaCallInfo,
  46. cdaDebugCellInfo,
  47. cdaEndpointInfo,
  48. cdaThreadInfo,
  49. cdaClientCallInfo
  50. } ChosenDebugAction;
  51. int Action = cdaInvalid;
  52. BOOL CheckForCellID(void)
  53. {
  54. if ((CellID.SectionID != 0) || (CellID.CellID != 0))
  55. {
  56. printf("A cell ID cannot be specified for this action\n");
  57. return TRUE;
  58. }
  59. else
  60. return FALSE;
  61. }
  62. BOOL CheckForEndpointName(void)
  63. {
  64. if (EndpointName)
  65. {
  66. printf("An endpoint name cannot be specified for this action\n");
  67. return TRUE;
  68. }
  69. else
  70. return FALSE;
  71. }
  72. BOOL CheckForThreadID(void)
  73. {
  74. if (ThreadID)
  75. {
  76. printf("A thread ID cannot be specified for this action\n");
  77. return TRUE;
  78. }
  79. else
  80. return FALSE;
  81. }
  82. BOOL CheckForCallID(void)
  83. {
  84. if (CallID)
  85. {
  86. printf("A call ID cannot be specified for this action\n");
  87. return TRUE;
  88. }
  89. else
  90. return FALSE;
  91. }
  92. BOOL CheckForIfStart(void)
  93. {
  94. if (IfStart)
  95. {
  96. printf("An interface UUID start cannot be specified for this action\n");
  97. return TRUE;
  98. }
  99. else
  100. return FALSE;
  101. }
  102. BOOL CheckForProcNum(void)
  103. {
  104. if (ProcNum != RPCDBG_NO_PROCNUM_SPECIFIED)
  105. {
  106. printf("A procedure number cannot be specified for this action\n");
  107. return TRUE;
  108. }
  109. else
  110. return FALSE;
  111. }
  112. BOOL CheckForProcessID(void)
  113. {
  114. if (ProcessID)
  115. {
  116. printf("A process ID cannot be specified for this action\n");
  117. return TRUE;
  118. }
  119. else
  120. return FALSE;
  121. }
  122. void __cdecl DumpToConsole(PCSTR lpFormat, ...)
  123. {
  124. va_list arglist;
  125. va_start(arglist, lpFormat);
  126. vfprintf(stdout, lpFormat, arglist);
  127. va_end(arglist);
  128. }
  129. void __RPC_FAR * __RPC_API MIDL_user_allocate(size_t Size)
  130. {
  131. void PAPI * pvBuf;
  132. pvBuf = new char [Size];
  133. return(pvBuf);
  134. }
  135. void __RPC_API MIDL_user_free (void __RPC_FAR *Buf)
  136. {
  137. delete (Buf);
  138. }
  139. const char *ValidProtocolSequences[] = {"ncacn_np", "ncacn_ip_tcp"};
  140. const char *ValidEnpoints[] = {"epmapper", "135"};
  141. #define ARRAY_SIZE_OF(a) (sizeof(a) / sizeof(a[0]))
  142. void ParseArgv(int argc, char **argv)
  143. {
  144. int fMissingParm = 0;
  145. char *Name = *argv;
  146. char option;
  147. char *TempString;
  148. char *Delimiter;
  149. char *Ignored;
  150. BOOL fInvalidArg;
  151. int i;
  152. argc--;
  153. argv++;
  154. while(argc)
  155. {
  156. if (**argv != '/' &&
  157. **argv != '-')
  158. {
  159. printf("Invalid switch: %s\n", *argv);
  160. argc--;
  161. argv++;
  162. }
  163. else
  164. {
  165. option = argv[0][1];
  166. argc--;
  167. argv++;
  168. // Most switches require a second command line arg.
  169. if (argc < 1)
  170. fMissingParm = 1;
  171. switch(option)
  172. {
  173. case 'C':
  174. CallID = strtoul(*argv, &Ignored, radix);
  175. argc--;
  176. argv++;
  177. break;
  178. case 'p':
  179. Protseq = *argv;
  180. for (i = 0; i < ARRAY_SIZE_OF(ValidProtocolSequences); i ++)
  181. {
  182. if (_strcmpi(Protseq, ValidProtocolSequences[i]) == 0)
  183. {
  184. break;
  185. }
  186. }
  187. if (i < ARRAY_SIZE_OF(ValidProtocolSequences))
  188. {
  189. BindingEndpoint = (char *) ValidEnpoints[i];
  190. argc--;
  191. argv++;
  192. break;
  193. }
  194. else
  195. {
  196. printf("Invalid protocol sequence: %s\n", Protseq);
  197. printf("Usage: %s: %s\n", Name, USAGE);
  198. exit(2);
  199. }
  200. case 's':
  201. NetworkAddr = *argv;
  202. argc--;
  203. argv++;
  204. break;
  205. case 'I':
  206. IfStart = strtoul(*argv, &Ignored, radix);
  207. argc--;
  208. argv++;
  209. break;
  210. case 'N':
  211. ProcNum = strtoul(*argv, &Ignored, radix);
  212. argc--;
  213. argv++;
  214. break;
  215. case 'L':
  216. TempString = *argv;
  217. Delimiter = strchr(TempString, '.');
  218. if (Delimiter == NULL)
  219. {
  220. printf("Usage: %s: %s\n", Name, USAGE);
  221. exit(2);
  222. }
  223. *Delimiter = 0;
  224. Delimiter ++;
  225. CellID.SectionID = (unsigned short)strtoul(TempString, &Ignored, radix);
  226. CellID.CellID = (unsigned short)strtoul(Delimiter, &Ignored, radix);
  227. argc--;
  228. argv++;
  229. break;
  230. case 'E':
  231. EndpointName = *argv;
  232. argc--;
  233. argv++;
  234. break;
  235. case 'T':
  236. ThreadID = strtoul(*argv, &Ignored, radix);
  237. argc--;
  238. argv++;
  239. break;
  240. case 'P':
  241. ProcessID = strtoul(*argv, &Ignored, radix);
  242. argc--;
  243. argv++;
  244. break;
  245. case 'c':
  246. if (Action != cdaInvalid)
  247. {
  248. printf("The action to be performed can be specified only once on the command line\n");
  249. printf("Usage: %s: %s\n", Name, USAGE);
  250. exit(2);
  251. }
  252. Action = cdaCallInfo;
  253. fMissingParm = 0;
  254. break;
  255. case 'l':
  256. if (Action != cdaInvalid)
  257. {
  258. printf("The action to be performed can be specified only once on the command line\n");
  259. printf("Usage: %s: %s\n", Name, USAGE);
  260. exit(2);
  261. }
  262. Action = cdaDebugCellInfo;
  263. fMissingParm = 0;
  264. break;
  265. case 'e':
  266. if (Action != cdaInvalid)
  267. {
  268. printf("The action to be performed can be specified only once on the command line\n");
  269. printf("Usage: %s: %s\n", Name, USAGE);
  270. exit(2);
  271. }
  272. Action = cdaEndpointInfo;
  273. fMissingParm = 0;
  274. break;
  275. case 't':
  276. if (Action != cdaInvalid)
  277. {
  278. printf("The action to be performed can be specified only once on the command line\n");
  279. printf("Usage: %s: %s\n", Name, USAGE);
  280. exit(2);
  281. }
  282. Action = cdaThreadInfo;
  283. fMissingParm = 0;
  284. break;
  285. case 'a':
  286. if (Action != cdaInvalid)
  287. {
  288. printf("The action to be performed can be specified only once on the command line\n");
  289. printf("Usage: %s: %s\n", Name, USAGE);
  290. exit(2);
  291. }
  292. Action = cdaClientCallInfo;
  293. fMissingParm = 0;
  294. break;
  295. case 'r':
  296. radix = atoi(*argv);
  297. fMissingParm = 0;
  298. break;
  299. default:
  300. fMissingParm = 0;
  301. printf("Usage: %s: %s\n", Name, USAGE);
  302. exit(2);
  303. break;
  304. }
  305. if (fMissingParm)
  306. {
  307. printf("Invalid switch %s, missing required parameter\n", *argv);
  308. exit(2);
  309. }
  310. }
  311. } // while argc
  312. // verify that the options are consistent
  313. fInvalidArg = FALSE;
  314. switch (Action)
  315. {
  316. case cdaInvalid:
  317. printf("The action to be performed should be specified exactly once on the command line\n");
  318. printf("Usage: %s: %s\n", Name, USAGE);
  319. exit(2);
  320. case cdaCallInfo:
  321. case cdaClientCallInfo:
  322. fInvalidArg = CheckForCellID();
  323. fInvalidArg |= CheckForEndpointName();
  324. fInvalidArg |= CheckForThreadID();
  325. if (fInvalidArg)
  326. {
  327. printf("Usage: %s: %s\n", Name, USAGE);
  328. exit(2);
  329. }
  330. break;
  331. case cdaDebugCellInfo:
  332. if ((CellID.SectionID == 0) && (CellID.CellID == 0))
  333. {
  334. printf("A cell ID must be specified for this action\n");
  335. fInvalidArg = TRUE;
  336. }
  337. if (ProcessID == 0)
  338. {
  339. printf("A process ID must be specified for this action\n");
  340. fInvalidArg = TRUE;
  341. }
  342. fInvalidArg |= CheckForEndpointName();
  343. fInvalidArg |= CheckForThreadID();
  344. fInvalidArg |= CheckForCallID();
  345. fInvalidArg |= CheckForIfStart();
  346. fInvalidArg |= CheckForProcNum();
  347. if (fInvalidArg)
  348. {
  349. printf("Usage: %s: %s\n", Name, USAGE);
  350. exit(2);
  351. }
  352. break;
  353. case cdaEndpointInfo:
  354. fInvalidArg |= CheckForCellID();
  355. fInvalidArg |= CheckForThreadID();
  356. fInvalidArg |= CheckForCallID();
  357. fInvalidArg |= CheckForIfStart();
  358. fInvalidArg |= CheckForProcNum();
  359. fInvalidArg |= CheckForProcessID();
  360. if (fInvalidArg)
  361. {
  362. printf("Usage: %s: %s\n", Name, USAGE);
  363. exit(2);
  364. }
  365. break;
  366. case cdaThreadInfo:
  367. if (ProcessID == 0)
  368. {
  369. printf("A process ID must be specified for this action\n");
  370. fInvalidArg = TRUE;
  371. }
  372. fInvalidArg |= CheckForCellID();
  373. fInvalidArg |= CheckForCallID();
  374. fInvalidArg |= CheckForIfStart();
  375. fInvalidArg |= CheckForProcNum();
  376. if (fInvalidArg)
  377. {
  378. printf("Usage: %s: %s\n", Name, USAGE);
  379. exit(2);
  380. }
  381. break;
  382. default:
  383. printf("Internal error. Chosen action is %d\n", Action);
  384. exit(2);
  385. }
  386. }
  387. /*
  388. RPC_STATUS DoRpcBindingSetAuthInfo(handle_t Binding)
  389. {
  390. if (AuthnLevel != RPC_C_AUTHN_LEVEL_NONE)
  391. return RpcBindingSetAuthInfo(Binding,
  392. NULL,
  393. AuthnLevel,
  394. ulSecurityPackage,
  395. NULL,
  396. RPC_C_AUTHZ_NONE);
  397. else
  398. return(RPC_S_OK);
  399. }
  400. unsigned long Worker(unsigned long l)
  401. {
  402. unsigned long status;
  403. unsigned long Test;
  404. unsigned long ClientId;
  405. unsigned long InSize, OutSize;
  406. unsigned long Time, Calls;
  407. char __RPC_FAR *pBuffer;
  408. char __RPC_FAR *stringBinding;
  409. handle_t binding;
  410. RPC_STATUS RpcErr;
  411. int Retries;
  412. pBuffer = MIDL_user_allocate(128*1024L);
  413. if (pBuffer == 0)
  414. {
  415. PrintToConsole("Out of memory!");
  416. return 1;
  417. }
  418. status =
  419. RpcStringBindingComposeA(0,
  420. Protseq,
  421. NetworkAddr,
  422. Endpoint,
  423. 0,
  424. &stringBinding);
  425. CHECK_RET(status, "RpcStringBindingCompose");
  426. status =
  427. RpcBindingFromStringBindingA(stringBinding, &binding);
  428. CHECK_RET(status, "RpcBindingFromStringBinding");
  429. status =
  430. DoRpcBindingSetAuthInfo(binding);
  431. CHECK_RET(status, "RpcBindingSetAuthInfo");
  432. RpcStringFreeA(&stringBinding);
  433. Retries = 15;
  434. do
  435. {
  436. status = BeginTest(binding, &ClientId, &Test, &InSize, &OutSize);
  437. if (status == PERF_TOO_MANY_CLIENTS)
  438. {
  439. PrintToConsole("Too many clients, I'm exiting\n");
  440. goto Cleanup ;
  441. }
  442. Retries --;
  443. if ((status == RPC_S_SERVER_UNAVAILABLE) && (Retries > 0))
  444. {
  445. PrintToConsole("Server too busy - retrying ...\n");
  446. }
  447. }
  448. while ((status == RPC_S_SERVER_UNAVAILABLE) && (Retries > 0));
  449. CHECK_RET(status, "ClientConnect");
  450. if (InSize > IN_ADJUSTMENT)
  451. {
  452. InSize -= IN_ADJUSTMENT;
  453. }
  454. else
  455. {
  456. InSize = 0;
  457. }
  458. if (OutSize > OUT_ADJUSTMENT)
  459. {
  460. OutSize -= OUT_ADJUSTMENT;
  461. }
  462. else
  463. {
  464. OutSize = 0;
  465. }
  466. gInSize = InSize;
  467. gOutSize = OutSize;
  468. PrintToConsole("Client %ld connected\n", ClientId);
  469. Retries = 15;
  470. do
  471. {
  472. RpcTryExcept
  473. {
  474. RpcErr = RPC_S_OK;
  475. Time = GetTickCount();
  476. Calls = ( (TestTable[Test])(binding, ClientId, pBuffer) );
  477. Time = GetTickCount() - Time;
  478. Dump("Completed %d calls in %d ms\n"
  479. "%d T/S or %3d.%03d ms/T\n\n",
  480. Calls,
  481. Time,
  482. (Calls * 1000) / Time,
  483. Time / Calls,
  484. ((Time % Calls) * 1000) / Calls
  485. );
  486. }
  487. RpcExcept(1)
  488. {
  489. RpcErr = (unsigned long)RpcExceptionCode();
  490. PrintToConsole("\nException %lu (0x%08lX)\n",
  491. RpcErr, RpcErr);
  492. }
  493. RpcEndExcept
  494. Retries --;
  495. if ((RpcErr == RPC_S_SERVER_UNAVAILABLE) && (Retries > 0))
  496. {
  497. PrintToConsole("Server too busy - retrying ...\n");
  498. }
  499. }
  500. while ((RpcErr == RPC_S_SERVER_UNAVAILABLE) && (Retries > 0));
  501. Cleanup:
  502. RpcBindingFree(&binding);
  503. return status;
  504. }
  505. */
  506. ////////////////////////////////////////////////////////////////////
  507. /// Local representation to wire representation translation routines
  508. ////////////////////////////////////////////////////////////////////
  509. BOOL TranslateRemoteCallInfoToLocalCallInfo(IN RemoteDebugCallInfo *RemoteCallInfo,
  510. OUT DebugCallInfo *LocalDebugInfo)
  511. {
  512. LocalDebugInfo->Type = RemoteCallInfo->Type;
  513. LocalDebugInfo->Status = RemoteCallInfo->Status;
  514. LocalDebugInfo->ProcNum = RemoteCallInfo->ProcNum;
  515. LocalDebugInfo->InterfaceUUIDStart = RemoteCallInfo->InterfaceUUIDStart;
  516. LocalDebugInfo->ServicingTID = RemoteCallInfo->ServicingTID;
  517. LocalDebugInfo->CallFlags = RemoteCallInfo->CallFlags;
  518. LocalDebugInfo->CallID = RemoteCallInfo->CallID;
  519. LocalDebugInfo->LastUpdateTime = RemoteCallInfo->LastUpdateTime;
  520. if (RemoteCallInfo->ConnectionType == crtLrpcConnection)
  521. {
  522. ASSERT(LocalDebugInfo->CallFlags & DBGCELL_LRPC_CALL);
  523. LocalDebugInfo->Connection = RemoteCallInfo->connInfo.Connection;
  524. }
  525. else if (RemoteCallInfo->ConnectionType == crtOsfConnection)
  526. {
  527. LocalDebugInfo->PID = RemoteCallInfo->connInfo.Caller.PID;
  528. LocalDebugInfo->TID = RemoteCallInfo->connInfo.Caller.TID;
  529. }
  530. else
  531. {
  532. PrintToConsole("Invalid type for call info connection type: %d\n",
  533. RemoteCallInfo->ConnectionType);
  534. return FALSE;
  535. }
  536. return TRUE;
  537. }
  538. void TranslateRemoteEndpointInfoToLocalEndpointInfo(IN RemoteDebugEndpointInfo *RemoteEndpointInfo,
  539. OUT DebugEndpointInfo *LocalDebugInfo)
  540. {
  541. LocalDebugInfo->Type = RemoteEndpointInfo->Type;
  542. LocalDebugInfo->ProtseqType = RemoteEndpointInfo->ProtseqType;
  543. LocalDebugInfo->Status = RemoteEndpointInfo->Status;
  544. if (RemoteEndpointInfo->EndpointName)
  545. {
  546. memcpy(LocalDebugInfo->EndpointName,
  547. RemoteEndpointInfo->EndpointName,
  548. DebugEndpointNameLength);
  549. MIDL_user_free(RemoteEndpointInfo->EndpointName);
  550. RemoteEndpointInfo->EndpointName = 0;
  551. }
  552. else
  553. LocalDebugInfo->EndpointName[0] = 0;
  554. }
  555. void TranslateRemoteThreadInfoToLocalThreadInfo(IN RemoteDebugThreadInfo *RemoteThreadInfo,
  556. OUT DebugThreadInfo *LocalDebugInfo)
  557. {
  558. LocalDebugInfo->Type = RemoteThreadInfo->Type;
  559. LocalDebugInfo->Status = RemoteThreadInfo->Status;
  560. LocalDebugInfo->LastUpdateTime = RemoteThreadInfo->LastUpdateTime;
  561. LocalDebugInfo->TID = RemoteThreadInfo->TID;
  562. LocalDebugInfo->Endpoint = RemoteThreadInfo->Endpoint;
  563. }
  564. void TranslateRemoteClientCallInfoToLocalClientCallInfo(IN RemoteDebugClientCallInfo *RemoteClientCallInfo,
  565. OUT DebugClientCallInfo *LocalDebugInfo)
  566. {
  567. LocalDebugInfo->Type = RemoteClientCallInfo->Type;
  568. LocalDebugInfo->ProcNum = RemoteClientCallInfo->ProcNum;
  569. LocalDebugInfo->ServicingThread = RemoteClientCallInfo->ServicingThread;
  570. LocalDebugInfo->IfStart = RemoteClientCallInfo->IfStart;
  571. LocalDebugInfo->CallID = RemoteClientCallInfo->CallID;
  572. LocalDebugInfo->CallTargetID = RemoteClientCallInfo->CallTargetID;
  573. if (RemoteClientCallInfo->Endpoint)
  574. {
  575. memcpy(LocalDebugInfo->Endpoint,
  576. RemoteClientCallInfo->Endpoint,
  577. ClientCallEndpointLength);
  578. MIDL_user_free(RemoteClientCallInfo->Endpoint);
  579. RemoteClientCallInfo->Endpoint = 0;
  580. }
  581. else
  582. LocalDebugInfo->Endpoint[0] = 0;
  583. }
  584. void TranslateRemoteConnectionInfoToLocalConnectionInfo(IN RemoteDebugConnectionInfo *RemoteConnectionInfo,
  585. OUT DebugConnectionInfo *LocalDebugInfo)
  586. {
  587. LocalDebugInfo->Type = RemoteConnectionInfo->Type;
  588. LocalDebugInfo->Flags = RemoteConnectionInfo->Flags;
  589. LocalDebugInfo->LastTransmitFragmentSize =
  590. RemoteConnectionInfo->LastTransmitFragmentSize;
  591. LocalDebugInfo->Endpoint = RemoteConnectionInfo->Endpoint;
  592. LocalDebugInfo->ConnectionID[0] = ULongToPtr(RemoteConnectionInfo->ConnectionID[0]);
  593. LocalDebugInfo->ConnectionID[1] = ULongToPtr(RemoteConnectionInfo->ConnectionID[1]);
  594. LocalDebugInfo->LastSendTime = RemoteConnectionInfo->LastSendTime;
  595. LocalDebugInfo->LastReceiveTime = RemoteConnectionInfo->LastReceiveTime;
  596. }
  597. void TranslateRemoteCallTargetInfoToLocalCallTargetInfo(IN RemoteDebugCallTargetInfo *RemoteCallTargetInfo,
  598. OUT DebugCallTargetInfo *LocalDebugInfo)
  599. {
  600. LocalDebugInfo->Type = RemoteCallTargetInfo->Type;
  601. LocalDebugInfo->ProtocolSequence = RemoteCallTargetInfo->ProtocolSequence;
  602. LocalDebugInfo->LastUpdateTime = RemoteCallTargetInfo->LastUpdateTime;
  603. if (RemoteCallTargetInfo->TargetServer)
  604. {
  605. memcpy(LocalDebugInfo->TargetServer, RemoteCallTargetInfo->TargetServer,
  606. TargetServerNameLength);
  607. MIDL_user_free(RemoteCallTargetInfo->TargetServer);
  608. RemoteCallTargetInfo->TargetServer = 0;
  609. }
  610. }
  611. BOOL TranslateRemoteDebugCellInfoToLocalDebugCellInfo(RemoteDebugCellUnion *RemoteCellInfo,
  612. DebugCellUnion *Container)
  613. {
  614. switch (RemoteCellInfo->UnionType)
  615. {
  616. case dctCallInfo:
  617. return TranslateRemoteCallInfoToLocalCallInfo(&RemoteCellInfo->debugInfo.callInfo,
  618. &Container->callInfo);
  619. break;
  620. case dctThreadInfo:
  621. TranslateRemoteThreadInfoToLocalThreadInfo(&RemoteCellInfo->debugInfo.threadInfo,
  622. &Container->threadInfo);
  623. break;
  624. case dctEndpointInfo:
  625. TranslateRemoteEndpointInfoToLocalEndpointInfo(&RemoteCellInfo->debugInfo.endpointInfo,
  626. &Container->endpointInfo);
  627. break;
  628. case dctClientCallInfo:
  629. TranslateRemoteClientCallInfoToLocalClientCallInfo(&RemoteCellInfo->debugInfo.clientCallInfo,
  630. &Container->clientCallInfo);
  631. break;
  632. case dctConnectionInfo:
  633. TranslateRemoteConnectionInfoToLocalConnectionInfo(&RemoteCellInfo->debugInfo.connectionInfo,
  634. &Container->connectionInfo);
  635. break;
  636. case dctCallTargetInfo:
  637. TranslateRemoteCallTargetInfoToLocalCallTargetInfo(&RemoteCellInfo->debugInfo.callTargetInfo,
  638. &Container->callTargetInfo);
  639. break;
  640. default:
  641. PrintToConsole("Invalid debug cell type: %d\n", RemoteCellInfo->UnionType);
  642. return FALSE;
  643. }
  644. return TRUE;
  645. }
  646. //////////////////////////////////////////////////////////////////////////////
  647. /// Helper routines for enumerating remote information
  648. //////////////////////////////////////////////////////////////////////////////
  649. void GetAndPrintRemoteCallInfo(IN handle_t Binding)
  650. {
  651. RemoteDebugCallInfo *RemoteCallInfo;
  652. DebugCellID CellID;
  653. DbgCallEnumHandle rh;
  654. DebugCallInfo LocalCallInfo;
  655. RPC_STATUS Status;
  656. RemoteCallInfo = NULL;
  657. DumpToConsole("Getting remote call info ...\n");
  658. RpcTryExcept
  659. {
  660. Status = RemoteOpenRPCDebugCallInfoEnumeration(Binding, &rh, CallID, IfStart, ProcNum, ProcessID);
  661. }
  662. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  663. {
  664. Status = RpcExceptionCode();
  665. }
  666. RpcEndExcept
  667. if (Status != RPC_S_OK)
  668. {
  669. DumpToConsole("RemoteOpenRPCDebugCallInfoEnumeration failed: %d\n", Status);
  670. return;
  671. }
  672. PrintCallInfoHeader(DumpToConsole);
  673. do
  674. {
  675. RemoteCallInfo = NULL;
  676. RpcTryExcept
  677. {
  678. Status = RemoteGetNextRPCDebugCallInfo(rh, &RemoteCallInfo, &CellID, &ProcessID);
  679. }
  680. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  681. {
  682. Status = RpcExceptionCode();
  683. }
  684. RpcEndExcept
  685. if (Status == RPC_S_OK)
  686. {
  687. TranslateRemoteCallInfoToLocalCallInfo(RemoteCallInfo, &LocalCallInfo);
  688. MIDL_user_free(RemoteCallInfo);
  689. PrintCallInfoBody(ProcessID, CellID, &LocalCallInfo, DumpToConsole);
  690. }
  691. }
  692. while (Status == RPC_S_OK);
  693. if (Status != RPC_S_DBG_ENUMERATION_DONE)
  694. {
  695. DumpToConsole("Enumeration aborted with error %d\n", Status);
  696. }
  697. RpcTryExcept
  698. {
  699. RemoteFinishRPCDebugCallInfoEnumeration(&rh);
  700. }
  701. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  702. {
  703. Status = RpcExceptionCode();
  704. }
  705. RpcEndExcept
  706. }
  707. void GetAndPrintRemoteEndpointInfo(IN handle_t Binding)
  708. {
  709. DWORD CurrentPID;
  710. RPC_STATUS Status;
  711. DebugEndpointInfo EndpointInfo;
  712. RemoteDebugEndpointInfo *RemoteEndpointInfo;
  713. DbgEndpointEnumHandle rh;
  714. DebugCellID CellID;
  715. DumpToConsole("Getting remote endpoint info ...\n");
  716. RpcTryExcept
  717. {
  718. Status = RemoteOpenRPCDebugEndpointInfoEnumeration(Binding, &rh,
  719. (EndpointName != NULL) ? (strlen(EndpointName) + 1) : 0,
  720. (unsigned char *) EndpointName);
  721. }
  722. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  723. {
  724. Status = RpcExceptionCode();
  725. }
  726. RpcEndExcept
  727. if (Status != RPC_S_OK)
  728. {
  729. DumpToConsole("RemoteOpenRPCDebugEndpointInfoEnumeration failed: %d\n", Status);
  730. return;
  731. }
  732. PrintEndpointInfoHeader(DumpToConsole);
  733. do
  734. {
  735. RemoteEndpointInfo = NULL;
  736. RpcTryExcept
  737. {
  738. Status = RemoteGetNextRPCDebugEndpointInfo(rh, &RemoteEndpointInfo, &CellID, &CurrentPID);
  739. }
  740. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  741. {
  742. Status = RpcExceptionCode();
  743. }
  744. RpcEndExcept
  745. if (Status == RPC_S_OK)
  746. {
  747. TranslateRemoteEndpointInfoToLocalEndpointInfo(RemoteEndpointInfo, &EndpointInfo);
  748. MIDL_user_free(RemoteEndpointInfo);
  749. PrintEndpointInfoBody(CurrentPID, CellID, &EndpointInfo, DumpToConsole);
  750. }
  751. }
  752. while (Status == RPC_S_OK);
  753. if (Status != RPC_S_DBG_ENUMERATION_DONE)
  754. {
  755. DumpToConsole("Enumeration aborted with error %d\n", Status);
  756. }
  757. RpcTryExcept
  758. {
  759. RemoteFinishRPCDebugEndpointInfoEnumeration(&rh);
  760. }
  761. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  762. {
  763. Status = RpcExceptionCode();
  764. }
  765. RpcEndExcept
  766. }
  767. void GetAndPrintRemoteThreadInfo(IN handle_t Binding)
  768. {
  769. RPC_STATUS Status;
  770. DbgThreadEnumHandle rh;
  771. RemoteDebugThreadInfo *RemoteThreadInfo;
  772. DebugThreadInfo LocalThreadInfo;
  773. DebugCellID CellID;
  774. DWORD CurrentPID;
  775. DumpToConsole("Getting remote thread info ...\n");
  776. RpcTryExcept
  777. {
  778. Status = RemoteOpenRPCDebugThreadInfoEnumeration(Binding, &rh, ProcessID, ThreadID);
  779. }
  780. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  781. {
  782. Status = RpcExceptionCode();
  783. }
  784. RpcEndExcept
  785. if (Status != RPC_S_OK)
  786. {
  787. DumpToConsole("RemoteOpenRPCDebugThreadInfoEnumeration failed: %d\n", Status);
  788. return;
  789. }
  790. PrintThreadInfoHeader(DumpToConsole);
  791. do
  792. {
  793. RemoteThreadInfo = NULL;
  794. RpcTryExcept
  795. {
  796. Status = RemoteGetNextRPCDebugThreadInfo(rh, &RemoteThreadInfo, &CellID, &CurrentPID);
  797. }
  798. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  799. {
  800. Status = RpcExceptionCode();
  801. }
  802. RpcEndExcept
  803. if (Status == RPC_S_OK)
  804. {
  805. TranslateRemoteThreadInfoToLocalThreadInfo(RemoteThreadInfo, &LocalThreadInfo);
  806. MIDL_user_free(RemoteThreadInfo);
  807. PrintThreadInfoBody(CurrentPID, CellID, &LocalThreadInfo, DumpToConsole);
  808. }
  809. }
  810. while (Status == RPC_S_OK);
  811. if (Status != RPC_S_DBG_ENUMERATION_DONE)
  812. {
  813. DumpToConsole("Enumeration aborted with error %d\n", Status);
  814. }
  815. RpcTryExcept
  816. {
  817. RemoteFinishRPCDebugThreadInfoEnumeration(&rh);
  818. }
  819. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  820. {
  821. Status = RpcExceptionCode();
  822. }
  823. RpcEndExcept
  824. }
  825. void GetAndPrintRemoteClientCallInfo(IN handle_t Binding)
  826. {
  827. DWORD CurrentPID;
  828. DebugCellID CellID;
  829. DebugClientCallInfo LocalClientCall;
  830. DebugCallTargetInfo LocalCallTarget;
  831. RemoteDebugClientCallInfo *RemoteClientCallInfo;
  832. RemoteDebugCallTargetInfo *RemoteCallTargetInfo;
  833. RPC_STATUS Status;
  834. DbgClientCallEnumHandle rh;
  835. DumpToConsole("Getting remote call info ...\n");
  836. RpcTryExcept
  837. {
  838. Status = RemoteOpenRPCDebugClientCallInfoEnumeration(Binding, &rh, CallID, IfStart, ProcNum, ProcessID);
  839. }
  840. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  841. {
  842. Status = RpcExceptionCode();
  843. }
  844. RpcEndExcept
  845. if (Status != RPC_S_OK)
  846. {
  847. DumpToConsole("RemoteOpenRPCDebugClientCallInfoEnumeration failed: %d\n", Status);
  848. return;
  849. }
  850. PrintClientCallInfoHeader(DumpToConsole);
  851. do
  852. {
  853. RemoteClientCallInfo = NULL;
  854. RemoteCallTargetInfo = NULL;
  855. RpcTryExcept
  856. {
  857. Status = RemoteGetNextRPCDebugClientCallInfo(rh, &RemoteClientCallInfo, &RemoteCallTargetInfo,
  858. &CellID, &CurrentPID);
  859. }
  860. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  861. {
  862. Status = RpcExceptionCode();
  863. }
  864. RpcEndExcept
  865. if (Status == RPC_S_OK)
  866. {
  867. if ((RemoteCallTargetInfo != NULL) && (RemoteCallTargetInfo->Type != dctCallTargetInfo))
  868. {
  869. DumpToConsole("Inconsistent information detected - skipping ...\n");
  870. MIDL_user_free(RemoteClientCallInfo);
  871. MIDL_user_free(RemoteCallTargetInfo);
  872. continue;
  873. }
  874. TranslateRemoteClientCallInfoToLocalClientCallInfo(RemoteClientCallInfo, &LocalClientCall);
  875. MIDL_user_free(RemoteClientCallInfo);
  876. TranslateRemoteCallTargetInfoToLocalCallTargetInfo(RemoteCallTargetInfo, &LocalCallTarget);
  877. MIDL_user_free(RemoteCallTargetInfo);
  878. PrintClientCallInfoBody(CurrentPID, CellID, &LocalClientCall, &LocalCallTarget,
  879. DumpToConsole);
  880. }
  881. }
  882. while (Status == RPC_S_OK);
  883. if (Status != RPC_S_DBG_ENUMERATION_DONE)
  884. {
  885. DumpToConsole("Enumeration aborted with error %d\n", Status);
  886. }
  887. RpcTryExcept
  888. {
  889. RemoteFinishRPCDebugClientCallInfoEnumeration(&rh);
  890. }
  891. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  892. {
  893. Status = RpcExceptionCode();
  894. }
  895. RpcEndExcept
  896. }
  897. int __cdecl
  898. main (int argc, char **argv)
  899. {
  900. unsigned long Status, i;
  901. unsigned char *StringBinding;
  902. handle_t Binding;
  903. RemoteDebugCellUnion *RemoteDebugCell;
  904. DebugCellUnion Container;
  905. DebugCellUnion EndpointContainer;
  906. DebugCellUnion *EndpointContainerPointer;
  907. BOOL fResult;
  908. ParseArgv(argc, argv);
  909. // by now, we must have all valid arguments. Depending on local/remote
  910. // case and on action chosen, we actually do the work
  911. if (NetworkAddr == NULL)
  912. {
  913. // in local case, just do the work
  914. switch (Action)
  915. {
  916. case cdaCallInfo:
  917. GetAndPrintCallInfo(CallID, IfStart, ProcNum, ProcessID, DumpToConsole);
  918. break;
  919. case cdaClientCallInfo:
  920. GetAndPrintClientCallInfo(CallID, IfStart, ProcNum, ProcessID, DumpToConsole);
  921. break;
  922. case cdaDebugCellInfo:
  923. GetAndPrintDbgCellInfo(ProcessID, CellID, DumpToConsole);
  924. break;
  925. case cdaEndpointInfo:
  926. GetAndPrintEndpointInfo(EndpointName, DumpToConsole);
  927. break;
  928. case cdaThreadInfo:
  929. GetAndPrintThreadInfo(ProcessID, ThreadID, DumpToConsole);
  930. break;
  931. }
  932. }
  933. else
  934. {
  935. Status = RpcStringBindingComposeA(0, (unsigned char *)Protseq,
  936. (unsigned char *)NetworkAddr, (unsigned char *)BindingEndpoint, 0, &StringBinding);
  937. CHECK_RET(Status, "RpcStringBindingCompose");
  938. Status = RpcBindingFromStringBindingA(StringBinding, &Binding);
  939. CHECK_RET(Status, "RpcBindingFromStringBinding");
  940. RpcStringFreeA(&StringBinding);
  941. Status = RpcBindingSetAuthInfo(Binding, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_GSS_NEGOTIATE,
  942. NULL, RPC_C_AUTHZ_NONE);
  943. CHECK_RET(Status, "RpcBindingSetAuthInfo");
  944. // in remote case, call the remote RPCSS
  945. switch (Action)
  946. {
  947. case cdaCallInfo:
  948. GetAndPrintRemoteCallInfo(Binding);
  949. break;
  950. case cdaClientCallInfo:
  951. GetAndPrintRemoteClientCallInfo(Binding);
  952. break;
  953. case cdaDebugCellInfo:
  954. RemoteDebugCell = NULL;
  955. DumpToConsole("Getting remote cell info ...\n");
  956. RpcTryExcept
  957. {
  958. Status = RemoteGetCellByDebugCellID(Binding, ProcessID, CellID, &RemoteDebugCell);
  959. }
  960. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  961. {
  962. Status = RpcExceptionCode();
  963. }
  964. RpcEndExcept
  965. if (Status != RPC_S_OK)
  966. {
  967. DumpToConsole("Remote call failed with error %d\n", Status);
  968. break;
  969. }
  970. // get back the idl representation into a DbgCell representation
  971. fResult = TranslateRemoteDebugCellInfoToLocalDebugCellInfo(RemoteDebugCell, &Container);
  972. MIDL_user_free(RemoteDebugCell);
  973. // if FALSE is returned, error info should have already been printed out
  974. if (!fResult)
  975. break;
  976. if (Container.genericCell.Type == dctConnectionInfo)
  977. {
  978. RemoteDebugCell = NULL;
  979. DumpToConsole("Getting remote endpoint info for connection ...\n");
  980. RpcTryExcept
  981. {
  982. Status = RemoteGetCellByDebugCellID(Binding, ProcessID,
  983. Container.connectionInfo.Endpoint, &RemoteDebugCell);
  984. }
  985. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  986. {
  987. Status = RpcExceptionCode();
  988. }
  989. RpcEndExcept
  990. if (Status != RPC_S_OK)
  991. {
  992. DumpToConsole("Remote call failed with error %d\n", Status);
  993. break;
  994. }
  995. fResult = TranslateRemoteDebugCellInfoToLocalDebugCellInfo(RemoteDebugCell,
  996. &EndpointContainer);
  997. MIDL_user_free(RemoteDebugCell);
  998. if (!fResult)
  999. break;
  1000. EndpointContainerPointer = &EndpointContainer;
  1001. }
  1002. else
  1003. EndpointContainerPointer = NULL;
  1004. PrintDbgCellInfo(&Container, EndpointContainerPointer, DumpToConsole);
  1005. break;
  1006. case cdaEndpointInfo:
  1007. GetAndPrintRemoteEndpointInfo(Binding);
  1008. break;
  1009. case cdaThreadInfo:
  1010. GetAndPrintRemoteThreadInfo(Binding);
  1011. break;
  1012. }
  1013. RpcBindingFree(&Binding);
  1014. }
  1015. /*
  1016. PrintToConsole("Authentication Level is: %s\n", AuthnLevelStr);
  1017. if (Options[0] < 0)
  1018. Options[0] = 1;
  1019. pClientThreads = MIDL_user_allocate(sizeof(HANDLE) * Options[0]);
  1020. for(i = 0; i < (unsigned long)Options[0]; i++)
  1021. {
  1022. pClientThreads[i] = CreateThread(0,
  1023. 0,
  1024. (LPTHREAD_START_ROUTINE)Worker,
  1025. 0,
  1026. 0,
  1027. &status);
  1028. if (pClientThreads[i] == 0)
  1029. ApiError("CreateThread", GetLastError());
  1030. }
  1031. status = WaitForMultipleObjects(Options[0],
  1032. pClientThreads,
  1033. TRUE, // Wait for all client threads
  1034. INFINITE);
  1035. if (status == WAIT_FAILED)
  1036. {
  1037. ApiError("WaitForMultipleObjects", GetLastError());
  1038. }
  1039. */
  1040. return(0);
  1041. }