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.

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