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.

451 lines
9.7 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1990 - 1999
  3. Module Name:
  4. util.c
  5. Abstract:
  6. This module provides all the utility functions for the Server side of
  7. the end-point mapper.
  8. Author:
  9. Bharat Shah
  10. Revision History:
  11. 06-03-97 gopalp Added code to cleanup stale EP Mapper entries.
  12. --*/
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include <sysinc.h>
  17. #include <rpc.h>
  18. #include <rpcndr.h>
  19. #include "epmp.h"
  20. #include "eptypes.h"
  21. #include "local.h"
  22. //
  23. // Link list manipulation rountines
  24. //
  25. #ifdef DBG
  26. void CountProcessContextList(EP_CLEANUP *pProcessContext, unsigned long nExpectedCount)
  27. {
  28. unsigned long nActualCount = 0;
  29. PIFOBJNode pNode = pProcessContext->EntryList;
  30. while (pNode && (pNode->OwnerOfList == pProcessContext))
  31. {
  32. pNode = pNode->Next;
  33. nActualCount ++;
  34. }
  35. if (nActualCount != nExpectedCount)
  36. {
  37. DbgPrint("Expected count was %d, while actual count was %d\n", nExpectedCount,
  38. nActualCount);
  39. }
  40. }
  41. #endif
  42. PIENTRY
  43. Link(
  44. PIENTRY *Head,
  45. PIENTRY Node
  46. )
  47. {
  48. if (Node == NULL)
  49. return (NULL);
  50. CheckInSem();
  51. Node->Next = *Head;
  52. return(*Head = Node);
  53. }
  54. VOID
  55. LinkAtEnd(
  56. PIFOBJNode *Head,
  57. PIFOBJNode Node
  58. )
  59. {
  60. register PIFOBJNode *ppNode;
  61. CheckInSem();
  62. for ( ppNode = Head; *ppNode; ppNode = &((*ppNode)->Next) );
  63. {
  64. ; // Empty body
  65. }
  66. *ppNode = Node;
  67. }
  68. PIENTRY
  69. UnLink(
  70. PIENTRY *Head,
  71. PIENTRY Node
  72. )
  73. {
  74. PIENTRY *ppNode;
  75. for (ppNode = Head; *ppNode && (*ppNode != Node);
  76. ppNode = &(*ppNode)->Next)
  77. {
  78. ; // Empty body
  79. }
  80. if (*ppNode)
  81. {
  82. *ppNode = Node->Next;
  83. return (Node);
  84. }
  85. return (0);
  86. }
  87. RPC_STATUS
  88. EnLinkOnIFOBJList(
  89. PEP_CLEANUP ProcessCtxt,
  90. PIFOBJNode NewNode
  91. )
  92. /*++
  93. Arguments:
  94. phContext - The context handle supplied by the process.
  95. NewNode - The node (EP entry) to be inserted into the EP Mapper database.
  96. Routine Description:
  97. This routine adds a new entry into the Endpoint Mapper database (which is
  98. maintained as a linked-list). It also updates the list of entries for the
  99. process identified by the context handle ProcessCtxt.
  100. Notes:
  101. a. This routine should always be called by holding a mutex.
  102. b. NewNode is already allocated by the caller.
  103. c. IFObjList may be created here.
  104. d. ProcessCtxt is assumed to be allocated sometime by the caler.
  105. Return Values:
  106. RPC_S_OK - Always.
  107. --*/
  108. {
  109. RPC_STATUS Status = RPC_S_OK;
  110. #ifdef DBG_DETAIL
  111. PIFOBJNode pTemp, pLast;
  112. #endif // DBG_DETAIL
  113. // Parameter validation.
  114. ASSERT(NewNode);
  115. ASSERT(ProcessCtxt);
  116. ASSERT(ProcessCtxt->MagicVal == CLEANUP_MAGIC_VALUE);
  117. ASSERT_PROCESS_CONTEXT_LIST_COUNT(ProcessCtxt, ProcessCtxt->cEntries);
  118. CheckInSem();
  119. //
  120. // First, insert NewNode into this Process's list of entries.
  121. //
  122. NewNode->Next = ProcessCtxt->EntryList;
  123. if (ProcessCtxt->EntryList != NULL)
  124. {
  125. ASSERT(ProcessCtxt->cEntries > 0);
  126. ASSERT(cTotalEpEntries > 0);
  127. ASSERT(IFObjList != NULL);
  128. NewNode->Prev = ProcessCtxt->EntryList->Prev;
  129. // Next node's Prev pointer
  130. ProcessCtxt->EntryList->Prev = NewNode;
  131. if (NewNode->Prev)
  132. {
  133. ASSERT(cTotalEpEntries > 1);
  134. // Previous node's Next pointer
  135. NewNode->Prev->Next = NewNode;
  136. }
  137. }
  138. else
  139. {
  140. ASSERT(ProcessCtxt->cEntries == 0);
  141. NewNode->Prev = NULL;
  142. }
  143. //
  144. // Now, adjust the Global EP Mapper entries list head, if necessary
  145. //
  146. if (ProcessCtxt->EntryList != NULL)
  147. {
  148. if (ProcessCtxt->EntryList == IFObjList)
  149. {
  150. IFObjList = NewNode;
  151. }
  152. }
  153. else
  154. {
  155. // First entry registered by this process
  156. if (IFObjList != NULL)
  157. {
  158. // Add the new ProcessCtxt at the head of IFObjList
  159. IFObjList->Prev = NewNode;
  160. NewNode->Next = IFObjList;
  161. }
  162. else
  163. {
  164. ASSERT(cTotalEpEntries == 0);
  165. }
  166. IFObjList = NewNode;
  167. }
  168. // Add new node at the head of Process list.
  169. ProcessCtxt->EntryList = NewNode;
  170. NewNode->OwnerOfList = ProcessCtxt;
  171. ProcessCtxt->cEntries++;
  172. cTotalEpEntries++;
  173. #ifdef DBG_DETAIL
  174. DbgPrint("RPCSS: cTotalEpEntries++ [%p] (%d)\n", ProcessCtxt, cTotalEpEntries);
  175. DbgPrint("RPCSS: Dump of IFOBJList\n");
  176. pTemp = IFObjList;
  177. pLast = IFObjList;
  178. while (pTemp)
  179. {
  180. DbgPrint("RPCSS: \t\t[%p]\n", pTemp);
  181. pLast = pTemp;
  182. pTemp = pTemp->Next;
  183. }
  184. DbgPrint("RPCSS: --------------------\n");
  185. while (pLast)
  186. {
  187. DbgPrint("RPCSS: \t\t\t[%p]\n", pLast);
  188. pLast = pLast->Prev;
  189. }
  190. #endif // DBG_DETAIL
  191. ASSERT_PROCESS_CONTEXT_LIST_COUNT(ProcessCtxt, ProcessCtxt->cEntries);
  192. return (Status);
  193. }
  194. RPC_STATUS
  195. UnLinkFromIFOBJList(
  196. PEP_CLEANUP ProcessCtxt,
  197. PIFOBJNode DeleteMe
  198. )
  199. /*++
  200. Arguments:
  201. phContext - The context handle supplied by the process.
  202. DeleteMe - The node (EP entry) to be deleted from the EP Mapper database.
  203. Routine Description:
  204. This routine removes an existing entry from the Endpoint Mapper database
  205. (which is maintained as a linked-list). It also updates the list of entries
  206. for the process identified by the context handle ProcessCtxt.
  207. Notes:
  208. a. This routine should always be called by holding a mutex.
  209. b. DeleteMe node has to be freed by the caller.
  210. c. IFOBJlist may become empty (NULLed out) here.
  211. d. ProcessCtxt may become empty here and if so, it should be freed
  212. by the caller.
  213. Return Values:
  214. RPC_S_OK - If everyhing went well.
  215. RPC_S_ACCESS_DENIED - If something went wrong.
  216. --*/
  217. {
  218. RPC_STATUS Status = RPC_S_OK;
  219. #ifdef DBG_DETAIL
  220. PIFOBJNode pTemp, pLast;
  221. #endif // DBG_DETAIL
  222. // Parameter validation.
  223. ASSERT(DeleteMe);
  224. ASSERT(ProcessCtxt);
  225. ASSERT(ProcessCtxt->MagicVal == CLEANUP_MAGIC_VALUE);
  226. CheckInSem();
  227. //
  228. // The context has been created already for this process. So, there
  229. // should be one or more entries registered by this process.
  230. //
  231. ASSERT(IFObjList);
  232. ASSERT(cTotalEpEntries > 0);
  233. ASSERT(ProcessCtxt->EntryList);
  234. ASSERT(ProcessCtxt->cEntries > 0);
  235. ASSERT(ProcessCtxt->EntryList->OwnerOfList == ProcessCtxt);
  236. ASSERT_PROCESS_CONTEXT_LIST_COUNT(ProcessCtxt, ProcessCtxt->cEntries);
  237. // Trying to unregister someone else's entry?
  238. if (DeleteMe->OwnerOfList != ProcessCtxt)
  239. {
  240. ASSERT("Returning RPC_S_ACCESS_DENIED" &&
  241. (DeleteMe->OwnerOfList != ProcessCtxt));
  242. return (RPC_S_ACCESS_DENIED);
  243. }
  244. //
  245. // First, remove DeleteMe from this Process's List.
  246. //
  247. // See if it the first element of the process list.
  248. if (DeleteMe == ProcessCtxt->EntryList)
  249. {
  250. if (DeleteMe->Next)
  251. {
  252. // if we are nibbling the next segment, zero out the EntryList
  253. if (DeleteMe->Next->OwnerOfList != ProcessCtxt)
  254. {
  255. ProcessCtxt->EntryList = NULL;
  256. }
  257. else
  258. ProcessCtxt->EntryList = DeleteMe->Next;
  259. }
  260. else
  261. {
  262. ProcessCtxt->EntryList = NULL;
  263. }
  264. }
  265. ASSERT( ((ProcessCtxt->EntryList != NULL) && (ProcessCtxt->cEntries > 1))
  266. || (ProcessCtxt->cEntries == 1) );
  267. // Remove it.
  268. if (DeleteMe->Next != NULL)
  269. {
  270. // Next node's Prev pointer
  271. DeleteMe->Next->Prev = DeleteMe->Prev;
  272. }
  273. if (DeleteMe->Prev != NULL)
  274. {
  275. // Previous node's Next pointer
  276. DeleteMe->Prev->Next = DeleteMe->Next;
  277. }
  278. else
  279. {
  280. ASSERT(IFObjList == DeleteMe);
  281. }
  282. //
  283. // Next, adjust the Global EP Mapper entries list head, if necessary
  284. //
  285. if (IFObjList == DeleteMe)
  286. {
  287. // Can become NULL here.
  288. IFObjList = DeleteMe->Next;
  289. }
  290. // Remove node from all lists.
  291. DeleteMe->Prev = NULL;
  292. DeleteMe->Next = NULL;
  293. DeleteMe->OwnerOfList = NULL;
  294. ProcessCtxt->cEntries--;
  295. cTotalEpEntries--;
  296. #ifdef DBG_DETAIL
  297. DbgPrint("RPCSS: cTotalEpEntries-- [%p] (%d)\n", ProcessCtxt, cTotalEpEntries);
  298. DbgPrint("RPCSS: Dump of IFOBJList\n");
  299. pTemp = IFObjList;
  300. pLast = IFObjList;
  301. while (pTemp)
  302. {
  303. DbgPrint("RPCSS: \t\t[%p]\n", pTemp);
  304. pLast = pTemp;
  305. pTemp = pTemp->Next;
  306. }
  307. DbgPrint("RPCSS: --------------------\n");
  308. while (pLast)
  309. {
  310. DbgPrint("RPCSS: \t\t\t[%p]\n", pLast);
  311. pLast = pLast->Prev;
  312. }
  313. #endif // DBG_DETAIL
  314. ASSERT_PROCESS_CONTEXT_LIST_COUNT(ProcessCtxt, ProcessCtxt->cEntries);
  315. return (Status);
  316. }
  317. //
  318. // HACK Alert.
  319. //
  320. // Midl 1.00.xx didn't support full pointers. So, clients from NT 3.1
  321. // machines will use unique pointers. This function detects and fixes
  322. // the buffer if an older client contacts our new server.
  323. // This HACK can be removed when supporting NT 3.1 era machines is no
  324. // longer required.
  325. void
  326. FixupForUniquePointerClients(
  327. PRPC_MESSAGE pRpcMessage
  328. )
  329. {
  330. unsigned long *pBuffer = (unsigned long *)pRpcMessage->Buffer;
  331. // Check the obj uuid parameter.
  332. if (pBuffer[0] != 0)
  333. {
  334. // If it is not zero, it should be 1.
  335. pBuffer[0] = 1;
  336. // check the map_tower, which moves over 1 + 4 longs for the obj uuid
  337. if (pBuffer[5] != 0)
  338. pBuffer[5] = 2;
  339. }
  340. else
  341. {
  342. // Null obj uuid, check the map_tower.
  343. if (pBuffer[1] != 0)
  344. pBuffer[1] = 1;
  345. }
  346. }