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.

274 lines
8.7 KiB

  1. /*****************************Module*Header*******************************\
  2. * Module Name: local.c *
  3. * *
  4. * Support routines for client side objects. *
  5. * *
  6. * Created: 30-May-1991 21:55:57 *
  7. * Author: Charles Whitmer [chuckwh] *
  8. * *
  9. * Copyright (c) 1991,1993 Microsoft Corporation *
  10. \**************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include <ntcsrdll.h>
  14. LHE *pLocalTable; // Points to handle table.
  15. ULONG iFreeLhe = INVALID_INDEX; // Identifies a free handle index.
  16. ULONG cLheCommitted = 0; // Count of LHEs with committed RAM.
  17. CRITICAL_SECTION semLocal; // Semaphore for handle allocation.
  18. //XXX Useless but needed by csrgdi.h
  19. #if DBG
  20. ULONG gcHits = 0;
  21. ULONG gcBatch = 0;
  22. ULONG gcCache = 0;
  23. ULONG gcUser = 0;
  24. #endif
  25. /******************************Private*Routine*****************************\
  26. * bMakeMoreHandles () *
  27. * *
  28. * Commits more RAM to the local handle table and links the new free *
  29. * handles together. Returns TRUE on success, FALSE on error. *
  30. * *
  31. * History: *
  32. * Sat 01-Jun-1991 17:06:45 -by- Charles Whitmer [chuckwh] *
  33. * Wrote it. *
  34. \**************************************************************************/
  35. BOOL bMakeMoreHandles()
  36. {
  37. UINT ii;
  38. // Commit more RAM for the handle table.
  39. if (
  40. (cLheCommitted >= MAX_HANDLES) ||
  41. (VirtualAlloc(
  42. (LPVOID) &pLocalTable[cLheCommitted],
  43. COMMIT_COUNT * sizeof(LHE),
  44. MEM_COMMIT,
  45. PAGE_READWRITE
  46. ) == (LPVOID) NULL)
  47. )
  48. {
  49. WARNING("bMakeMoreHandles(): failed to commit more memory\n");
  50. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  51. return(FALSE);
  52. }
  53. // Initialize the new handles.
  54. ii = iFreeLhe = cLheCommitted;
  55. cLheCommitted += COMMIT_COUNT;
  56. for (; ii<cLheCommitted; ii++)
  57. {
  58. pLocalTable[ii].metalink = ii+1;
  59. pLocalTable[ii].iUniq = 1;
  60. pLocalTable[ii].iType = LO_NULL;
  61. }
  62. pLocalTable[ii-1].metalink = INVALID_INDEX;
  63. return(TRUE);
  64. }
  65. /******************************Public*Routine******************************\
  66. * iAllocHandle (iType,hgre,pv) *
  67. * *
  68. * Allocates a handle from the local handle table, initializes fields in *
  69. * the handle entry. Returns the handle index or INVALID_INDEX on error. *
  70. * *
  71. * History: *
  72. * Sat 01-Jun-1991 17:08:54 -by- Charles Whitmer [chuckwh] *
  73. * Wrote it. *
  74. \**************************************************************************/
  75. ULONG iAllocHandle(ULONG iType,ULONG hgre,PVOID pv)
  76. {
  77. ULONG ii = INVALID_INDEX;
  78. PLHE plhe;
  79. // Get critical for handle allocation.
  80. ENTERCRITICALSECTION(&semLocal);
  81. // Make sure a handle is available.
  82. if (iFreeLhe != INVALID_INDEX || bMakeMoreHandles())
  83. {
  84. ii = iFreeLhe;
  85. plhe = pLocalTable + ii;
  86. iFreeLhe = plhe->metalink;
  87. plhe->hgre = hgre;
  88. plhe->cRef = 0;
  89. plhe->iType = (BYTE) iType;
  90. plhe->pv = pv;
  91. plhe->metalink = 0;
  92. plhe->tidOwner = 0;
  93. plhe->cLock = 0;
  94. }
  95. // Leave the critical section.
  96. LEAVECRITICALSECTION(&semLocal);
  97. return(ii);
  98. }
  99. /******************************Public*Routine******************************\
  100. * vFreeHandle (h) *
  101. * *
  102. * Frees up a local handle. The handle is added to the free list. This *
  103. * may be called with either an index or handle. The iUniq count is *
  104. * updated so the next user of this handle slot will have a different *
  105. * handle. *
  106. * *
  107. * Note for client side implementation: *
  108. * Caller should have handle locked before calling this. *
  109. * *
  110. * History: *
  111. * Sat 01-Jun-1991 17:11:23 -by- Charles Whitmer [chuckwh] *
  112. * Wrote it. *
  113. \**************************************************************************/
  114. VOID vFreeHandle(ULONG_PTR h)
  115. {
  116. // Extract the index from the handle.
  117. UINT ii = MASKINDEX(h);
  118. // Get critical for handle deallocation.
  119. ENTERCRITICALSECTION(&semLocal);
  120. // Caller should lock handle before freeing.
  121. ASSERTOPENGL(pLocalTable[ii].cLock == 1,
  122. "vFreeHandle(): cLock != 1\n");
  123. ASSERTOPENGL(pLocalTable[ii].tidOwner == GetCurrentThreadId(),
  124. "vFreeHandle(): thread not owner\n");
  125. // Add the handle to the free list.
  126. pLocalTable[ii].metalink = iFreeLhe;
  127. iFreeLhe = ii;
  128. // Increment the iUniq count.
  129. pLocalTable[ii].iUniq++;
  130. if (pLocalTable[ii].iUniq == 0)
  131. pLocalTable[ii].iUniq = 1;
  132. pLocalTable[ii].iType = LO_NULL;
  133. // Leave the critical section.
  134. LEAVECRITICALSECTION(&semLocal);
  135. }
  136. /******************************Public*Routine******************************\
  137. * cLockHandle (h)
  138. *
  139. * Lock handle for access by a thread. If another thread possesses the lock,
  140. * this will fail.
  141. *
  142. * Returns:
  143. * Lock count. Returns -1 if failure.
  144. *
  145. * History:
  146. * 31-Jan-1995 -by- Gilman Wong [gilmanw]
  147. * Wrote it.
  148. \**************************************************************************/
  149. LONG cLockHandle(ULONG_PTR h)
  150. {
  151. LONG lRet = -1;
  152. // Extract the index from the handle.
  153. UINT ii = MASKINDEX(h);
  154. PLHE plhe = pLocalTable + ii;
  155. // Get critical for handle locking.
  156. ENTERCRITICALSECTION(&semLocal);
  157. if ((ii >= cLheCommitted) ||
  158. (!MATCHUNIQ(plhe,h)) ||
  159. ((plhe->iType != LO_RC))
  160. )
  161. {
  162. DBGLEVEL1(LEVEL_ERROR, "cLockHandle: invalid handle 0x%lx\n", h);
  163. SetLastError(ERROR_INVALID_HANDLE);
  164. goto cLockHandle_exit;
  165. }
  166. // If not currently locked or if current owning thread is the same,
  167. // do the lock.
  168. if ( (pLocalTable[ii].cLock == 0) ||
  169. (pLocalTable[ii].tidOwner == GetCurrentThreadId()) )
  170. {
  171. pLocalTable[ii].cLock++;
  172. pLocalTable[ii].tidOwner = GetCurrentThreadId();
  173. lRet = (LONG) pLocalTable[ii].cLock;
  174. }
  175. else
  176. {
  177. WARNING("cLockHandle(): current thread not owner\n");
  178. SetLastError(ERROR_BUSY);
  179. }
  180. // Leave the critical section.
  181. cLockHandle_exit:
  182. LEAVECRITICALSECTION(&semLocal);
  183. return lRet;
  184. }
  185. /******************************Public*Routine******************************\
  186. * vUnlockHandle (h)
  187. *
  188. * Removes a lock from the handle. Must be owned by current thread.
  189. *
  190. * Note:
  191. * Caller should possess the lock before this is called. This implies
  192. * that cLockHandle must be called and its return code must be heeded.
  193. *
  194. * History:
  195. * 31-Jan-1995 -by- Gilman Wong [gilmanw]
  196. * Wrote it.
  197. \**************************************************************************/
  198. VOID vUnlockHandle(ULONG_PTR h)
  199. {
  200. // Extract the index from the handle.
  201. UINT ii = MASKINDEX(h);
  202. // Get critical for handle deallocation.
  203. ENTERCRITICALSECTION(&semLocal);
  204. // If not currently locked or if current owning thread is the same,
  205. // do the lock.
  206. ASSERTOPENGL(pLocalTable[ii].cLock > 0,
  207. "vUnlockHandle(): not locked\n");
  208. ASSERTOPENGL(pLocalTable[ii].tidOwner == GetCurrentThreadId(),
  209. "vUnlockHandle(): thread not owner\n");
  210. if ( (pLocalTable[ii].cLock > 0) &&
  211. (pLocalTable[ii].tidOwner == GetCurrentThreadId()) )
  212. {
  213. pLocalTable[ii].cLock--;
  214. }
  215. // Leave the critical section.
  216. LEAVECRITICALSECTION(&semLocal);
  217. }