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.

489 lines
11 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. PIFOBJNode
  88. GetLastIFOBJNode (
  89. void
  90. )
  91. /*++
  92. Routine Description:
  93. Returns the address of the last PIFOBJNode
  94. Arguments:
  95. Return Value:
  96. See description.
  97. Notes:
  98. The IFObjList list MUST not be empty when this
  99. function is called. It will AV if the list is
  100. empty. Caller must verify that the list is not
  101. empty before calling this function.
  102. --*/
  103. {
  104. PIFOBJNode CurrentNode = IFObjList;
  105. while (CurrentNode->Next != NULL)
  106. {
  107. CurrentNode = CurrentNode->Next;
  108. }
  109. return CurrentNode;
  110. }
  111. RPC_STATUS
  112. EnLinkOnIFOBJList(
  113. PEP_CLEANUP ProcessCtxt,
  114. PIFOBJNode NewNode
  115. )
  116. /*++
  117. Arguments:
  118. phContext - The context handle supplied by the process.
  119. NewNode - The node (EP entry) to be inserted into the EP Mapper database.
  120. Routine Description:
  121. This routine adds a new entry into the Endpoint Mapper database (which is
  122. maintained as a linked-list). It also updates the list of entries for the
  123. process identified by the context handle ProcessCtxt.
  124. Notes:
  125. a. This routine should always be called by holding a mutex.
  126. b. NewNode is already allocated by the caller.
  127. c. IFObjList may be created here.
  128. d. ProcessCtxt is assumed to be allocated sometime by the caler.
  129. Return Values:
  130. RPC_S_OK - Always.
  131. --*/
  132. {
  133. RPC_STATUS Status = RPC_S_OK;
  134. IFOBJNode *LastNode;
  135. #ifdef DBG_DETAIL
  136. PIFOBJNode pTemp, pLast;
  137. #endif // DBG_DETAIL
  138. // Parameter validation.
  139. ASSERT(NewNode);
  140. ASSERT(ProcessCtxt);
  141. ASSERT(ProcessCtxt->MagicVal == CLEANUP_MAGIC_VALUE);
  142. ASSERT_PROCESS_CONTEXT_LIST_COUNT(ProcessCtxt, ProcessCtxt->cEntries);
  143. CheckInSem();
  144. //
  145. // First, insert NewNode into this Process's list of entries.
  146. //
  147. NewNode->Next = ProcessCtxt->EntryList;
  148. if (ProcessCtxt->EntryList != NULL)
  149. {
  150. ASSERT(ProcessCtxt->cEntries > 0);
  151. ASSERT(cTotalEpEntries > 0);
  152. ASSERT(IFObjList != NULL);
  153. NewNode->Prev = ProcessCtxt->EntryList->Prev;
  154. // Next node's Prev pointer
  155. ProcessCtxt->EntryList->Prev = NewNode;
  156. if (NewNode->Prev)
  157. {
  158. ASSERT(cTotalEpEntries > 1);
  159. // Previous node's Next pointer
  160. NewNode->Prev->Next = NewNode;
  161. }
  162. }
  163. else
  164. {
  165. ASSERT(ProcessCtxt->cEntries == 0);
  166. NewNode->Prev = NULL;
  167. }
  168. //
  169. // Now, adjust the Global EP Mapper entries list head, if necessary
  170. //
  171. if (ProcessCtxt->EntryList != NULL)
  172. {
  173. if (ProcessCtxt->EntryList == IFObjList)
  174. {
  175. IFObjList = NewNode;
  176. }
  177. }
  178. else
  179. {
  180. // First entry registered by this process
  181. if (IFObjList != NULL)
  182. {
  183. LastNode = GetLastIFOBJNode();
  184. ASSERT(LastNode != NULL);
  185. ASSERT(LastNode->Next == NULL);
  186. // Add the new ProcessCtxt at the tail of IFObjList
  187. LastNode->Next = NewNode;
  188. NewNode->Prev = LastNode;
  189. // should already have been set to NULL
  190. ASSERT(NewNode->Next == NULL);
  191. }
  192. else
  193. {
  194. ASSERT(cTotalEpEntries == 0);
  195. IFObjList = NewNode;
  196. }
  197. }
  198. // Add new node at the head of Process list.
  199. ProcessCtxt->EntryList = NewNode;
  200. NewNode->OwnerOfList = ProcessCtxt;
  201. ProcessCtxt->cEntries++;
  202. cTotalEpEntries++;
  203. #ifdef DBG_DETAIL
  204. DbgPrint("RPCSS: cTotalEpEntries++ [%p] (%d)\n", ProcessCtxt, cTotalEpEntries);
  205. DbgPrint("RPCSS: Dump of IFOBJList\n");
  206. pTemp = IFObjList;
  207. pLast = IFObjList;
  208. while (pTemp)
  209. {
  210. DbgPrint("RPCSS: \t\t[%p]\n", pTemp);
  211. pLast = pTemp;
  212. pTemp = pTemp->Next;
  213. }
  214. DbgPrint("RPCSS: --------------------\n");
  215. while (pLast)
  216. {
  217. DbgPrint("RPCSS: \t\t\t[%p]\n", pLast);
  218. pLast = pLast->Prev;
  219. }
  220. #endif // DBG_DETAIL
  221. ASSERT_PROCESS_CONTEXT_LIST_COUNT(ProcessCtxt, ProcessCtxt->cEntries);
  222. return (Status);
  223. }
  224. RPC_STATUS
  225. UnLinkFromIFOBJList(
  226. PEP_CLEANUP ProcessCtxt,
  227. PIFOBJNode DeleteMe
  228. )
  229. /*++
  230. Arguments:
  231. phContext - The context handle supplied by the process.
  232. DeleteMe - The node (EP entry) to be deleted from the EP Mapper database.
  233. Routine Description:
  234. This routine removes an existing entry from the Endpoint Mapper database
  235. (which is maintained as a linked-list). It also updates the list of entries
  236. for the process identified by the context handle ProcessCtxt.
  237. Notes:
  238. a. This routine should always be called by holding a mutex.
  239. b. DeleteMe node has to be freed by the caller.
  240. c. IFOBJlist may become empty (NULLed out) here.
  241. d. ProcessCtxt may become empty here and if so, it should be freed
  242. by the caller.
  243. Return Values:
  244. RPC_S_OK - If everyhing went well.
  245. RPC_S_ACCESS_DENIED - If something went wrong.
  246. --*/
  247. {
  248. RPC_STATUS Status = RPC_S_OK;
  249. #ifdef DBG_DETAIL
  250. PIFOBJNode pTemp, pLast;
  251. #endif // DBG_DETAIL
  252. // Parameter validation.
  253. ASSERT(DeleteMe);
  254. ASSERT(ProcessCtxt);
  255. ASSERT(ProcessCtxt->MagicVal == CLEANUP_MAGIC_VALUE);
  256. CheckInSem();
  257. //
  258. // The context has been created already for this process. So, there
  259. // should be one or more entries registered by this process.
  260. //
  261. ASSERT(IFObjList);
  262. ASSERT(cTotalEpEntries > 0);
  263. ASSERT(ProcessCtxt->EntryList);
  264. ASSERT(ProcessCtxt->cEntries > 0);
  265. ASSERT(ProcessCtxt->EntryList->OwnerOfList == ProcessCtxt);
  266. ASSERT_PROCESS_CONTEXT_LIST_COUNT(ProcessCtxt, ProcessCtxt->cEntries);
  267. // Trying to unregister someone else's entry?
  268. if (DeleteMe->OwnerOfList != ProcessCtxt)
  269. {
  270. ASSERT("Returning RPC_S_ACCESS_DENIED" &&
  271. (DeleteMe->OwnerOfList != ProcessCtxt));
  272. return (RPC_S_ACCESS_DENIED);
  273. }
  274. //
  275. // First, remove DeleteMe from this Process's List.
  276. //
  277. // See if it the first element of the process list.
  278. if (DeleteMe == ProcessCtxt->EntryList)
  279. {
  280. if (DeleteMe->Next)
  281. {
  282. // if we are nibbling the next segment, zero out the EntryList
  283. if (DeleteMe->Next->OwnerOfList != ProcessCtxt)
  284. {
  285. ProcessCtxt->EntryList = NULL;
  286. }
  287. else
  288. ProcessCtxt->EntryList = DeleteMe->Next;
  289. }
  290. else
  291. {
  292. ProcessCtxt->EntryList = NULL;
  293. }
  294. }
  295. ASSERT( ((ProcessCtxt->EntryList != NULL) && (ProcessCtxt->cEntries > 1))
  296. || (ProcessCtxt->cEntries == 1) );
  297. // Remove it.
  298. if (DeleteMe->Next != NULL)
  299. {
  300. // Next node's Prev pointer
  301. DeleteMe->Next->Prev = DeleteMe->Prev;
  302. }
  303. if (DeleteMe->Prev != NULL)
  304. {
  305. // Previous node's Next pointer
  306. DeleteMe->Prev->Next = DeleteMe->Next;
  307. }
  308. else
  309. {
  310. ASSERT(IFObjList == DeleteMe);
  311. }
  312. //
  313. // Next, adjust the Global EP Mapper entries list head, if necessary
  314. //
  315. if (IFObjList == DeleteMe)
  316. {
  317. // Can become NULL here.
  318. IFObjList = DeleteMe->Next;
  319. }
  320. // Remove node from all lists.
  321. DeleteMe->Prev = NULL;
  322. DeleteMe->Next = NULL;
  323. DeleteMe->OwnerOfList = NULL;
  324. ProcessCtxt->cEntries--;
  325. cTotalEpEntries--;
  326. #ifdef DBG_DETAIL
  327. DbgPrint("RPCSS: cTotalEpEntries-- [%p] (%d)\n", ProcessCtxt, cTotalEpEntries);
  328. DbgPrint("RPCSS: Dump of IFOBJList\n");
  329. pTemp = IFObjList;
  330. pLast = IFObjList;
  331. while (pTemp)
  332. {
  333. DbgPrint("RPCSS: \t\t[%p]\n", pTemp);
  334. pLast = pTemp;
  335. pTemp = pTemp->Next;
  336. }
  337. DbgPrint("RPCSS: --------------------\n");
  338. while (pLast)
  339. {
  340. DbgPrint("RPCSS: \t\t\t[%p]\n", pLast);
  341. pLast = pLast->Prev;
  342. }
  343. #endif // DBG_DETAIL
  344. ASSERT_PROCESS_CONTEXT_LIST_COUNT(ProcessCtxt, ProcessCtxt->cEntries);
  345. return (Status);
  346. }
  347. //
  348. // HACK Alert.
  349. //
  350. // Midl 1.00.xx didn't support full pointers. So, clients from NT 3.1
  351. // machines will use unique pointers. This function detects and fixes
  352. // the buffer if an older client contacts our new server.
  353. // This HACK can be removed when supporting NT 3.1 era machines is no
  354. // longer required.
  355. void
  356. FixupForUniquePointerClients(
  357. PRPC_MESSAGE pRpcMessage
  358. )
  359. {
  360. unsigned long *pBuffer = (unsigned long *)pRpcMessage->Buffer;
  361. // Check the obj uuid parameter.
  362. if (pBuffer[0] != 0)
  363. {
  364. // If it is not zero, it should be 1.
  365. pBuffer[0] = 1;
  366. // check the map_tower, which moves over 1 + 4 longs for the obj uuid
  367. if (pBuffer[5] != 0)
  368. pBuffer[5] = 2;
  369. }
  370. else
  371. {
  372. // Null obj uuid, check the map_tower.
  373. if (pBuffer[1] != 0)
  374. pBuffer[1] = 1;
  375. }
  376. }