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.

612 lines
19 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. CellUtil.cxx
  5. Abstract:
  6. Utility functions for manipulating cells
  7. Author:
  8. Kamen Moutafov (kamenm) Dec 99 - Feb 2000
  9. Revision History:
  10. --*/
  11. #include <precomp.hxx>
  12. #include <DbgLib.hxx>
  13. DebugCellUnion *GetCellByIndex(IN OpenedDbgSection *pSection, IN DWORD CellIndex)
  14. {
  15. DWORD LocalPageSize = GetPageSize();
  16. DebugCellGeneric *LastCellForSection;
  17. DebugCellGeneric *CurrentCell;
  18. ASSERT(pSection != NULL);
  19. ASSERT(pSection->SectionCopy != NULL);
  20. #ifdef _WIN64
  21. if (CellIndex <= 1)
  22. return NULL;
  23. #else
  24. if (CellIndex == 0)
  25. return NULL;
  26. #endif
  27. LastCellForSection = GetLastCellForSection(pSection, LocalPageSize);
  28. CurrentCell = GetCellForSection(pSection, CellIndex);
  29. ASSERT(CurrentCell <= LastCellForSection);
  30. return (DebugCellUnion *) CurrentCell;
  31. }
  32. DebugCellUnion *GetCellByDebugCellID(IN CellEnumerationHandle CellEnumHandle, IN DebugCellID CellID)
  33. {
  34. SectionsSnapshot *Snapshot;
  35. OpenedDbgSection *CurrentSection;
  36. DebugCellUnion *Cell = NULL;
  37. Snapshot = (SectionsSnapshot *)CellEnumHandle;
  38. ASSERT(Snapshot != NULL);
  39. CurrentSection = Snapshot->FirstOpenedSection;
  40. while (TRUE)
  41. {
  42. if (CurrentSection->SectionID == CellID.SectionID)
  43. {
  44. Cell = GetCellByIndex(CurrentSection, CellID.CellID);
  45. break;
  46. }
  47. if (CurrentSection->SectionsList.Flink == NULL)
  48. break;
  49. CurrentSection = CONTAINING_RECORD(CurrentSection->SectionsList.Flink, OpenedDbgSection, SectionsList);
  50. }
  51. return Cell;
  52. }
  53. RPC_STATUS GetCellByDebugCellID(IN DWORD ProcessID, IN DebugCellID CellID, OUT DebugCellUnion *Container)
  54. {
  55. RPC_STATUS Status;
  56. CellEnumerationHandle CellEnumHandle;
  57. DebugCellUnion *Cell;
  58. ASSERT(Container != NULL);
  59. Status = OpenRPCServerDebugInfo(ProcessID, &CellEnumHandle);
  60. if (Status != RPC_S_OK)
  61. {
  62. return Status;
  63. }
  64. Cell = GetCellByDebugCellID(CellEnumHandle, CellID);
  65. if (Cell)
  66. {
  67. memcpy(Container, Cell, sizeof(DebugCellUnion));
  68. }
  69. else
  70. Status = ERROR_FILE_NOT_FOUND;
  71. CloseRPCServerDebugInfo(&CellEnumHandle);
  72. return Status;
  73. }
  74. /////////////////////////////////////////////////////
  75. typedef struct tagRPCDebugCallInfoEnumState
  76. {
  77. DWORD CallID;
  78. DWORD IfStart;
  79. int ProcNum;
  80. DWORD ProcessID;
  81. union
  82. {
  83. // if ProcessID != 0, cellEnum is used (i.e. we have process wide enumeration
  84. // otherwise, systemWideEnum is used - we have system wide enumeration
  85. RPCSystemWideCellEnumerationHandle systemWideEnum;
  86. CellEnumerationHandle cellEnum;
  87. };
  88. } RPCDebugCallInfoEnumState;
  89. RPC_STATUS OpenRPCDebugCallInfoEnumeration(IN DWORD CallID OPTIONAL, IN DWORD IfStart OPTIONAL,
  90. IN int ProcNum OPTIONAL,
  91. IN DWORD ProcessID OPTIONAL,
  92. OUT CallInfoEnumerationHandle *pHandle)
  93. {
  94. RPCDebugCallInfoEnumState *pCallEnumeration;
  95. RPC_STATUS Status;
  96. *pHandle = NULL;
  97. pCallEnumeration = new RPCDebugCallInfoEnumState;
  98. if (pCallEnumeration == NULL)
  99. return RPC_S_OUT_OF_MEMORY;
  100. pCallEnumeration->CallID = CallID;
  101. pCallEnumeration->IfStart = IfStart;
  102. pCallEnumeration->ProcessID = ProcessID;
  103. pCallEnumeration->ProcNum = ProcNum;
  104. if (ProcessID != 0)
  105. {
  106. Status = OpenRPCServerDebugInfo(ProcessID, &pCallEnumeration->cellEnum);
  107. if (Status == ERROR_FILE_NOT_FOUND)
  108. {
  109. delete pCallEnumeration;
  110. return RPC_S_DBG_NOT_AN_RPC_SERVER;
  111. }
  112. else if (Status != RPC_S_OK)
  113. {
  114. delete pCallEnumeration;
  115. return Status;
  116. }
  117. }
  118. else
  119. {
  120. Status = OpenRPCSystemWideCellEnumeration(&pCallEnumeration->systemWideEnum);
  121. if (Status != RPC_S_OK)
  122. return Status;
  123. }
  124. *pHandle = (CallInfoEnumerationHandle) pCallEnumeration;
  125. return RPC_S_OK;
  126. }
  127. RPC_STATUS GetNextRPCDebugCallInfo(IN CallInfoEnumerationHandle handle, OUT DebugCallInfo **NextCall,
  128. OUT DebugCellID *CellID, OUT DWORD *ServerPID)
  129. {
  130. RPCDebugCallInfoEnumState *pCallEnumeration = (RPCDebugCallInfoEnumState *)handle;
  131. RPC_STATUS Status;
  132. DebugCallInfo *CallInfo;
  133. DebugCellUnion *NextCell;
  134. ASSERT(pCallEnumeration != NULL);
  135. ASSERT(NextCall != NULL);
  136. ASSERT(ServerPID != NULL);
  137. // loop until we find something or run out of cells/servers
  138. while (TRUE)
  139. {
  140. if (pCallEnumeration->ProcessID != 0)
  141. {
  142. *ServerPID = pCallEnumeration->ProcessID;
  143. NextCell = GetNextDebugCellInfo(pCallEnumeration->cellEnum, CellID);
  144. if (NextCell == NULL)
  145. return RPC_S_DBG_ENUMERATION_DONE;
  146. }
  147. else
  148. {
  149. Status = GetNextRPCSystemWideCell(pCallEnumeration->systemWideEnum, &NextCell, CellID, ServerPID);
  150. if (Status == RPC_S_INVALID_BOUND)
  151. return RPC_S_DBG_ENUMERATION_DONE;
  152. if (Status != RPC_S_OK)
  153. return Status;
  154. }
  155. // NextCell must be non-NULL here, or we have a bug
  156. ASSERT(NextCell != NULL);
  157. if (NextCell->callInfo.Type != dctCallInfo)
  158. continue;
  159. CallInfo = &NextCell->callInfo;
  160. if ((pCallEnumeration->CallID != 0) && (CallInfo->CallID != pCallEnumeration->CallID))
  161. continue;
  162. if ((pCallEnumeration->IfStart != 0) && (CallInfo->InterfaceUUIDStart != pCallEnumeration->IfStart))
  163. continue;
  164. if (((USHORT)pCallEnumeration->ProcNum != (USHORT)RPCDBG_NO_PROCNUM_SPECIFIED)
  165. && (CallInfo->ProcNum != pCallEnumeration->ProcNum))
  166. continue;
  167. // if we have survived all checks until now, we have found it - return it
  168. *NextCall = CallInfo;
  169. return RPC_S_OK;
  170. }
  171. }
  172. void FinishRPCDebugCallInfoEnumeration(IN OUT CallInfoEnumerationHandle *pHandle)
  173. {
  174. RPCDebugCallInfoEnumState *pCallEnumeration;
  175. ASSERT(pHandle != NULL);
  176. pCallEnumeration = (RPCDebugCallInfoEnumState *)*pHandle;
  177. ASSERT(pCallEnumeration != NULL);
  178. if (pCallEnumeration->ProcessID != 0)
  179. {
  180. CloseRPCServerDebugInfo(&pCallEnumeration->cellEnum);
  181. }
  182. else
  183. {
  184. FinishRPCSystemWideCellEnumeration(&pCallEnumeration->systemWideEnum);
  185. }
  186. }
  187. RPC_STATUS ResetRPCDebugCallInfoEnumeration(IN CallInfoEnumerationHandle handle)
  188. {
  189. RPCDebugCallInfoEnumState *pCallEnumeration = (RPCDebugCallInfoEnumState *)handle;
  190. ASSERT(pCallEnumeration != NULL);
  191. if (pCallEnumeration->ProcessID != 0)
  192. {
  193. ResetRPCServerDebugInfo(pCallEnumeration->cellEnum);
  194. return RPC_S_OK;
  195. }
  196. else
  197. {
  198. return ResetRPCSystemWideCellEnumeration(pCallEnumeration->systemWideEnum);
  199. }
  200. }
  201. ////////////////////////////////////
  202. typedef struct tagRPCDebugEndpointInfoEnumState
  203. {
  204. char *Endpoint;
  205. RPCSystemWideCellEnumerationHandle systemWideEnum;
  206. } RPCDebugEndpointInfoEnumState;
  207. RPC_STATUS OpenRPCDebugEndpointInfoEnumeration(IN char *Endpoint OPTIONAL,
  208. OUT EndpointInfoEnumerationHandle *pHandle)
  209. {
  210. RPCDebugEndpointInfoEnumState *pEndpointEnumeration;
  211. RPC_STATUS Status;
  212. int EndpointLength;
  213. *pHandle = NULL;
  214. pEndpointEnumeration = new RPCDebugEndpointInfoEnumState;
  215. if (pEndpointEnumeration == NULL)
  216. return RPC_S_OUT_OF_MEMORY;
  217. if (ARGUMENT_PRESENT(Endpoint))
  218. {
  219. EndpointLength = strlen(Endpoint);
  220. pEndpointEnumeration->Endpoint = new char [EndpointLength + 1];
  221. if (pEndpointEnumeration->Endpoint == NULL)
  222. {
  223. delete pEndpointEnumeration;
  224. return RPC_S_OUT_OF_MEMORY;
  225. }
  226. memcpy(pEndpointEnumeration->Endpoint, Endpoint, EndpointLength + 1);
  227. }
  228. else
  229. {
  230. pEndpointEnumeration->Endpoint = NULL;
  231. }
  232. Status = OpenRPCSystemWideCellEnumeration(&pEndpointEnumeration->systemWideEnum);
  233. if (Status != RPC_S_OK)
  234. return Status;
  235. *pHandle = (EndpointInfoEnumerationHandle) pEndpointEnumeration;
  236. return RPC_S_OK;
  237. }
  238. RPC_STATUS GetNextRPCDebugEndpointInfo(IN CallInfoEnumerationHandle handle, OUT DebugEndpointInfo **NextEndpoint,
  239. OUT DebugCellID *CellID, OUT DWORD *ServerPID)
  240. {
  241. RPCDebugEndpointInfoEnumState *pEndpointEnumeration = (RPCDebugEndpointInfoEnumState *)handle;
  242. RPC_STATUS Status;
  243. DebugEndpointInfo *EndpointInfo;
  244. DebugCellUnion *NextCell;
  245. ASSERT(pEndpointEnumeration != NULL);
  246. ASSERT(NextEndpoint != NULL);
  247. ASSERT(ServerPID != NULL);
  248. // loop until we find something or run out of cells/servers
  249. while (TRUE)
  250. {
  251. Status = GetNextRPCSystemWideCell(pEndpointEnumeration->systemWideEnum, &NextCell, CellID, ServerPID);
  252. if (Status == RPC_S_INVALID_BOUND)
  253. return RPC_S_DBG_ENUMERATION_DONE;
  254. if (Status != RPC_S_OK)
  255. return Status;
  256. // NextCell must be non-NULL here, or we have a bug
  257. ASSERT(NextCell != NULL);
  258. if (NextCell->callInfo.Type != dctEndpointInfo)
  259. continue;
  260. EndpointInfo = &NextCell->endpointInfo;
  261. if (pEndpointEnumeration->Endpoint != NULL)
  262. {
  263. if (strncmp(EndpointInfo->EndpointName, pEndpointEnumeration->Endpoint, sizeof(EndpointInfo->EndpointName)) != 0)
  264. continue;
  265. }
  266. // if we have survived all checks until now, we have found it - return it
  267. *NextEndpoint = EndpointInfo;
  268. return RPC_S_OK;
  269. }
  270. }
  271. void FinishRPCDebugEndpointInfoEnumeration(IN OUT EndpointInfoEnumerationHandle *pHandle)
  272. {
  273. RPCDebugEndpointInfoEnumState *pEndpointEnumeration;
  274. ASSERT(pHandle != NULL);
  275. pEndpointEnumeration = (RPCDebugEndpointInfoEnumState *)*pHandle;
  276. ASSERT(pEndpointEnumeration != NULL);
  277. FinishRPCSystemWideCellEnumeration(&pEndpointEnumeration->systemWideEnum);
  278. }
  279. RPC_STATUS ResetRPCDebugEndpointInfoEnumeration(IN EndpointInfoEnumerationHandle handle)
  280. {
  281. RPCDebugEndpointInfoEnumState *pEndpointEnumeration = (RPCDebugEndpointInfoEnumState *)handle;
  282. ASSERT(pEndpointEnumeration != NULL);
  283. return ResetRPCSystemWideCellEnumeration(pEndpointEnumeration->systemWideEnum);
  284. }
  285. ////////////////////////////////////////////////
  286. typedef struct tagRPCDebugThreadInfoEnumState
  287. {
  288. DWORD ProcessID;
  289. DWORD ThreadID;
  290. CellEnumerationHandle cellEnum;
  291. } RPCDebugThreadInfoEnumState;
  292. RPC_STATUS OpenRPCDebugThreadInfoEnumeration(IN DWORD ProcessID,
  293. IN DWORD ThreadID OPTIONAL,
  294. OUT ThreadInfoEnumerationHandle *pHandle)
  295. {
  296. RPCDebugThreadInfoEnumState *pThreadEnumeration;
  297. RPC_STATUS Status;
  298. ASSERT(ProcessID != 0);
  299. *pHandle = NULL;
  300. pThreadEnumeration = new RPCDebugThreadInfoEnumState;
  301. if (pThreadEnumeration == NULL)
  302. return RPC_S_OUT_OF_MEMORY;
  303. pThreadEnumeration->ProcessID = ProcessID;
  304. pThreadEnumeration->ThreadID = ThreadID;
  305. Status = OpenRPCServerDebugInfo(ProcessID, &pThreadEnumeration->cellEnum);
  306. if (Status == ERROR_FILE_NOT_FOUND)
  307. {
  308. delete pThreadEnumeration;
  309. return RPC_S_DBG_NOT_AN_RPC_SERVER;
  310. }
  311. else if (Status != RPC_S_OK)
  312. {
  313. delete pThreadEnumeration;
  314. return Status;
  315. }
  316. *pHandle = (ThreadInfoEnumerationHandle) pThreadEnumeration;
  317. return RPC_S_OK;
  318. }
  319. RPC_STATUS GetNextRPCDebugThreadInfo(IN ThreadInfoEnumerationHandle handle, OUT DebugThreadInfo **NextThread,
  320. OUT DebugCellID *CellID, OUT DWORD *ServerPID)
  321. {
  322. RPCDebugThreadInfoEnumState *pThreadEnumeration = (RPCDebugThreadInfoEnumState *)handle;
  323. RPC_STATUS Status;
  324. DebugThreadInfo *ThreadInfo;
  325. DebugCellUnion *NextCell;
  326. ASSERT(pThreadEnumeration != NULL);
  327. ASSERT(NextThread != NULL);
  328. ASSERT(ServerPID != NULL);
  329. // loop until we find something or run out of cells/servers
  330. while (TRUE)
  331. {
  332. *ServerPID = pThreadEnumeration->ProcessID;
  333. NextCell = GetNextDebugCellInfo(pThreadEnumeration->cellEnum, CellID);
  334. if (NextCell == NULL)
  335. return RPC_S_DBG_ENUMERATION_DONE;
  336. if (NextCell->callInfo.Type != dctThreadInfo)
  337. continue;
  338. ThreadInfo = &NextCell->threadInfo;
  339. if ((pThreadEnumeration->ThreadID != 0) && (ThreadInfo->TID != pThreadEnumeration->ThreadID))
  340. continue;
  341. // if we have survived all checks until now, we have found it - return it
  342. *NextThread = ThreadInfo;
  343. return RPC_S_OK;
  344. }
  345. }
  346. void FinishRPCDebugThreadInfoEnumeration(IN OUT ThreadInfoEnumerationHandle *pHandle)
  347. {
  348. RPCDebugThreadInfoEnumState *pThreadEnumeration;
  349. ASSERT(pHandle != NULL);
  350. pThreadEnumeration = (RPCDebugThreadInfoEnumState *)*pHandle;
  351. ASSERT(pThreadEnumeration != NULL);
  352. CloseRPCServerDebugInfo(&pThreadEnumeration->cellEnum);
  353. }
  354. RPC_STATUS ResetRPCDebugThreadInfoEnumeration(IN ThreadInfoEnumerationHandle handle)
  355. {
  356. RPCDebugThreadInfoEnumState *pThreadEnumeration = (RPCDebugThreadInfoEnumState *)handle;
  357. ASSERT(pThreadEnumeration != NULL);
  358. ResetRPCServerDebugInfo(pThreadEnumeration->cellEnum);
  359. return RPC_S_OK;
  360. }
  361. /////////////////////////////////////////////////////
  362. typedef struct tagRPCDebugClientCallInfoEnumState
  363. {
  364. DWORD CallID;
  365. DWORD IfStart;
  366. int ProcNum;
  367. DWORD ProcessID;
  368. union
  369. {
  370. // if ProcessID != 0, cellEnum is used (i.e. we have process wide enumeration
  371. // otherwise, systemWideEnum is used - we have system wide enumeration
  372. RPCSystemWideCellEnumerationHandle systemWideEnum;
  373. CellEnumerationHandle cellEnum;
  374. };
  375. } RPCDebugClientCallInfoEnumState;
  376. RPC_STATUS OpenRPCDebugClientCallInfoEnumeration(IN DWORD CallID OPTIONAL, IN DWORD IfStart OPTIONAL,
  377. IN int ProcNum OPTIONAL,
  378. IN DWORD ProcessID OPTIONAL,
  379. OUT ClientCallInfoEnumerationHandle *pHandle)
  380. {
  381. RPCDebugClientCallInfoEnumState *pCallEnumeration;
  382. RPC_STATUS Status;
  383. *pHandle = NULL;
  384. pCallEnumeration = new RPCDebugClientCallInfoEnumState;
  385. if (pCallEnumeration == NULL)
  386. return RPC_S_OUT_OF_MEMORY;
  387. pCallEnumeration->CallID = CallID;
  388. pCallEnumeration->IfStart = IfStart;
  389. pCallEnumeration->ProcessID = ProcessID;
  390. pCallEnumeration->ProcNum = ProcNum;
  391. if (ProcessID != 0)
  392. {
  393. Status = OpenRPCServerDebugInfo(ProcessID, &pCallEnumeration->cellEnum);
  394. if (Status == ERROR_FILE_NOT_FOUND)
  395. {
  396. delete pCallEnumeration;
  397. return RPC_S_DBG_NOT_AN_RPC_SERVER;
  398. }
  399. else if (Status != RPC_S_OK)
  400. {
  401. delete pCallEnumeration;
  402. return Status;
  403. }
  404. }
  405. else
  406. {
  407. Status = OpenRPCSystemWideCellEnumeration(&pCallEnumeration->systemWideEnum);
  408. if (Status != RPC_S_OK)
  409. return Status;
  410. }
  411. *pHandle = (ClientCallInfoEnumerationHandle) pCallEnumeration;
  412. return RPC_S_OK;
  413. }
  414. RPC_STATUS GetNextRPCDebugClientCallInfo(IN ClientCallInfoEnumerationHandle handle,
  415. OUT DebugClientCallInfo **NextCall,
  416. OUT DebugCallTargetInfo **NextCallTarget,
  417. OUT DebugCellID *CellID, OUT DWORD *ServerPID)
  418. {
  419. RPCDebugClientCallInfoEnumState *pCallEnumeration = (RPCDebugClientCallInfoEnumState *)handle;
  420. RPC_STATUS Status;
  421. DebugClientCallInfo *CallInfo;
  422. DebugCallTargetInfo *CallTargetInfo;
  423. DebugCellUnion *NextCell;
  424. ASSERT(pCallEnumeration != NULL);
  425. ASSERT(NextCall != NULL);
  426. ASSERT(ServerPID != NULL);
  427. // loop until we find something or run out of cells/servers
  428. while (TRUE)
  429. {
  430. if (pCallEnumeration->ProcessID != 0)
  431. {
  432. *ServerPID = pCallEnumeration->ProcessID;
  433. NextCell = GetNextDebugCellInfo(pCallEnumeration->cellEnum, CellID);
  434. if (NextCell == NULL)
  435. return RPC_S_DBG_ENUMERATION_DONE;
  436. }
  437. else
  438. {
  439. Status = GetNextRPCSystemWideCell(pCallEnumeration->systemWideEnum, &NextCell, CellID, ServerPID);
  440. if (Status == RPC_S_INVALID_BOUND)
  441. return RPC_S_DBG_ENUMERATION_DONE;
  442. if (Status != RPC_S_OK)
  443. return Status;
  444. }
  445. // NextCell must be non-NULL here, or we have a bug
  446. ASSERT(NextCell != NULL);
  447. if (NextCell->callInfo.Type != dctClientCallInfo)
  448. continue;
  449. CallInfo = &NextCell->clientCallInfo;
  450. if ((pCallEnumeration->CallID != 0) && (CallInfo->CallID != pCallEnumeration->CallID))
  451. continue;
  452. if ((pCallEnumeration->IfStart != 0) && (CallInfo->IfStart != pCallEnumeration->IfStart))
  453. continue;
  454. if (((USHORT)pCallEnumeration->ProcNum != (USHORT)RPCDBG_NO_PROCNUM_SPECIFIED)
  455. && (CallInfo->ProcNum != pCallEnumeration->ProcNum))
  456. continue;
  457. if (pCallEnumeration->ProcessID != 0)
  458. {
  459. CallTargetInfo = (DebugCallTargetInfo *) GetCellByDebugCellID(pCallEnumeration->cellEnum,
  460. NextCell->clientCallInfo.CallTargetID);
  461. }
  462. else
  463. {
  464. CallTargetInfo = (DebugCallTargetInfo *) GetRPCSystemWideCellFromCellID(pCallEnumeration->systemWideEnum,
  465. NextCell->clientCallInfo.CallTargetID);
  466. }
  467. // if we have survived all checks until now, we have found it - return it
  468. *NextCall = CallInfo;
  469. *NextCallTarget = CallTargetInfo;
  470. return RPC_S_OK;
  471. }
  472. }
  473. void FinishRPCDebugClientCallInfoEnumeration(IN OUT ClientCallInfoEnumerationHandle *pHandle)
  474. {
  475. RPCDebugClientCallInfoEnumState *pCallEnumeration;
  476. ASSERT(pHandle != NULL);
  477. pCallEnumeration = (RPCDebugClientCallInfoEnumState *)*pHandle;
  478. ASSERT(pCallEnumeration != NULL);
  479. if (pCallEnumeration->ProcessID != 0)
  480. {
  481. CloseRPCServerDebugInfo(&pCallEnumeration->cellEnum);
  482. }
  483. else
  484. {
  485. FinishRPCSystemWideCellEnumeration(&pCallEnumeration->systemWideEnum);
  486. }
  487. }
  488. RPC_STATUS ResetRPCDebugClientCallInfoEnumeration(IN CallInfoEnumerationHandle handle)
  489. {
  490. RPCDebugClientCallInfoEnumState *pCallEnumeration = (RPCDebugClientCallInfoEnumState *)handle;
  491. ASSERT(pCallEnumeration != NULL);
  492. if (pCallEnumeration->ProcessID != 0)
  493. {
  494. ResetRPCServerDebugInfo(pCallEnumeration->cellEnum);
  495. return RPC_S_OK;
  496. }
  497. else
  498. {
  499. return ResetRPCSystemWideCellEnumeration(pCallEnumeration->systemWideEnum);
  500. }
  501. }