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.

390 lines
8.9 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: Handles.cpp
  6. * Content: Handle manager
  7. *
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 08/19/99 mjn Created
  12. * 03/23/00 mjn Revised to ensure 64-bit compliance
  13. * 03/24/00 mjn Added H_Enum
  14. * 07/09/00 rmt Added signature bytes
  15. * 08/05/00 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles.
  16. * 08/31/00 rmt Whistler Prefix Bug 171826
  17. *
  18. ***************************************************************************/
  19. #include "dnlobbyi.h"
  20. #define INC_SERIAL_COUNT(a) if (++((a)->dwSerial) == 0) ((a)->dwSerial)++
  21. #define INDEX_MASK 0x000fffff
  22. #define SERIAL_MASK 0xfff00000
  23. #define SERIAL_SHIFT 20
  24. #define GET_INDEX(h) (h & INDEX_MASK)
  25. #define GET_SERIAL(h) ((h & SERIAL_MASK) >> SERIAL_SHIFT)
  26. #define MAKE_HANDLE(i,s) ((i & INDEX_MASK) | ((s << SERIAL_SHIFT) & SERIAL_MASK))
  27. #define VERIFY_HANDLE(p,h) (((h & INDEX_MASK) < (p)->dwNumHandles) && ((p)->HandleArray[(h & INDEX_MASK)].dwSerial) && ((h & SERIAL_MASK) == ((p)->HandleArray[(h & INDEX_MASK)].dwSerial << SERIAL_SHIFT)))
  28. #undef DPF_MODNAME
  29. #define DPF_MODNAME "H_Grow"
  30. HRESULT H_Grow(HANDLESTRUCT *const phs,
  31. const DWORD dwIncSize)
  32. {
  33. HRESULT hResultCode = S_OK;
  34. DWORD dw;
  35. DPFX(DPFPREP, 9,"Parameters: phs [0x%p], dwIncSize [%ld]",phs,dwIncSize);
  36. if (dwIncSize == 0)
  37. {
  38. DPFERR("Must grow handles by at least 1");
  39. return(E_INVALIDARG);
  40. }
  41. // Grab CS
  42. DNEnterCriticalSection(&phs->dncs);
  43. if (phs->HandleArray == NULL || phs->dwNumHandles == 0)
  44. {
  45. if ((phs->HandleArray = static_cast<HANDLEELEMENT*>(DNMalloc((dwIncSize + phs->dwNumHandles) * sizeof(HANDLEELEMENT)))) == NULL)
  46. {
  47. DPFERR("Could not create handle array");
  48. hResultCode = E_OUTOFMEMORY;
  49. goto EXIT_H_Grow;
  50. }
  51. }
  52. else
  53. {
  54. if ((phs->HandleArray = static_cast<HANDLEELEMENT*>(DNRealloc(phs->HandleArray,(dwIncSize + phs->dwNumHandles) * sizeof(HANDLEELEMENT)))) == NULL)
  55. {
  56. DPFERR("Could not grow handle array");
  57. hResultCode = E_OUTOFMEMORY;
  58. goto EXIT_H_Grow;
  59. }
  60. }
  61. // Update Handle Structure
  62. phs->dwFirstFreeHandle = phs->dwNumHandles;
  63. phs->dwLastFreeHandle = phs->dwNumHandles + dwIncSize - 1;
  64. phs->dwNumFreeHandles = dwIncSize;
  65. phs->dwNumHandles += dwIncSize;
  66. // Setup free Handle Elements
  67. for (dw = 0 ; dw < dwIncSize - 1 ; dw++)
  68. {
  69. phs->HandleArray[phs->dwFirstFreeHandle + dw].dwSerial = 0;
  70. phs->HandleArray[phs->dwFirstFreeHandle + dw].Entry.dwIndex = phs->dwFirstFreeHandle + dw + 1;
  71. }
  72. phs->HandleArray[phs->dwFirstFreeHandle + dw].dwSerial = 0;
  73. phs->HandleArray[phs->dwFirstFreeHandle + dw].Entry.pvData = NULL;
  74. EXIT_H_Grow:
  75. // Release CS
  76. DNLeaveCriticalSection(&phs->dncs);
  77. DPFX(DPFPREP, 9,"Returning: [0x%lx]",hResultCode);
  78. return(hResultCode);
  79. }
  80. #undef DPF_MODNAME
  81. #define DPF_MODNAME "H_Initialize"
  82. HRESULT H_Initialize(HANDLESTRUCT *const phs,
  83. const DWORD dwInitialNum)
  84. {
  85. HRESULT hResultCode = S_OK;
  86. DPFX(DPFPREP, 9,"Parameters: phs [0x%p], dwInitialNum [%ld]",phs,dwInitialNum);
  87. if (dwInitialNum == 0)
  88. {
  89. DPFERR("Must initialize handles with at least 1");
  90. return(E_INVALIDARG);
  91. }
  92. if (!DNInitializeCriticalSection(&phs->dncs))
  93. {
  94. DPFERR("DNInitializeCriticalSection() failed");
  95. return(E_OUTOFMEMORY);
  96. }
  97. // Lock
  98. DNEnterCriticalSection(&phs->dncs);
  99. phs->dwSignature = DPLSIGNATURE_HANDLESTRUCT;
  100. phs->HandleArray = NULL;
  101. phs->dwNumHandles = 0;
  102. phs->dwNumFreeHandles = 0;
  103. phs->dwFirstFreeHandle = 0;
  104. phs->dwLastFreeHandle = 0;
  105. phs->dwSerial = 1;
  106. if ((hResultCode = H_Grow(phs,dwInitialNum)) != S_OK)
  107. {
  108. DPFERR("H_Grow() failed");
  109. goto EXIT_H_Initialize;
  110. }
  111. EXIT_H_Initialize:
  112. // Unlock
  113. DNLeaveCriticalSection(&phs->dncs);
  114. DPFX(DPFPREP, 9,"Returning: [0x%lx]",hResultCode);
  115. return(hResultCode);
  116. }
  117. #undef DPF_MODNAME
  118. #define DPF_MODNAME "H_Terminate"
  119. void H_Terminate(HANDLESTRUCT *const phs)
  120. {
  121. DPFX(DPFPREP, 9,"Parameters: phs [0x%p]",phs);
  122. if (phs->HandleArray != NULL)
  123. DNFree(phs->HandleArray);
  124. phs->dwNumHandles = 0;
  125. phs->dwSignature = DPLSIGNATURE_HANDLESTRUCT_FREE;
  126. DNDeleteCriticalSection(&phs->dncs);
  127. DPFX(DPFPREP, 9,"Returning");
  128. }
  129. #undef DPF_MODNAME
  130. #define DPF_MODNAME "H_Create"
  131. HRESULT H_Create(HANDLESTRUCT *const phs,
  132. void *const pvData,
  133. DWORD *const pHandle)
  134. {
  135. DWORD dwIndex;
  136. HRESULT hResultCode = S_OK;
  137. DPFX(DPFPREP, 9,"Parameters: phs [0x%p], pvData [0x%p], pHandle [0x%p]",phs,pvData,pHandle);
  138. if (pHandle == NULL)
  139. {
  140. DPFERR("Invalid handle pointer");
  141. return(E_INVALIDARG);
  142. }
  143. // Lock
  144. DNEnterCriticalSection(&phs->dncs);
  145. // If there are no free handles, double the handle array
  146. if (phs->dwNumFreeHandles == 0)
  147. {
  148. if ((hResultCode = H_Grow(phs,phs->dwNumHandles)) != S_OK) // Double the size
  149. {
  150. DPFERR("H_Grow() failed");
  151. goto EXIT_H_Create;
  152. }
  153. }
  154. // Update internal handle pointers
  155. dwIndex = phs->dwFirstFreeHandle;
  156. phs->dwFirstFreeHandle = phs->HandleArray[dwIndex].Entry.dwIndex;
  157. phs->dwNumFreeHandles--;
  158. do
  159. {
  160. // Update handle information
  161. INC_SERIAL_COUNT(phs);
  162. phs->HandleArray[dwIndex].dwSerial = phs->dwSerial;
  163. phs->HandleArray[dwIndex].Entry.pvData = pvData;
  164. // Create user's handle
  165. *pHandle = MAKE_HANDLE(dwIndex,phs->dwSerial);
  166. } while (*pHandle == 0); // Don't want 0 handle
  167. DPFX(DPFPREP, 9,"Returning: *pHandle = [0x%lx]",*pHandle);
  168. EXIT_H_Create:
  169. // Unlock
  170. DNLeaveCriticalSection(&phs->dncs);
  171. DPFX(DPFPREP, 9,"Returning: [0x%lx]",hResultCode);
  172. return(hResultCode);
  173. }
  174. #undef DPF_MODNAME
  175. #define DPF_MODNAME "H_Destroy"
  176. HRESULT H_Destroy(HANDLESTRUCT *const phs,
  177. const DWORD handle)
  178. {
  179. DWORD dwIndex;
  180. DWORD dwSerial;
  181. HRESULT hResultCode = S_OK;
  182. DPFX(DPFPREP, 9,"Parameters: phs [0x%p], handle [0x%lx]",phs,handle);
  183. // Lock
  184. DNEnterCriticalSection(&phs->dncs);
  185. // Ensure valid handle supplied
  186. if (!VERIFY_HANDLE(phs,handle))
  187. {
  188. DPFERR("Invalid handle");
  189. hResultCode = E_INVALIDARG;
  190. goto EXIT_H_Destroy;
  191. }
  192. dwIndex = GET_INDEX(handle);
  193. dwSerial = GET_SERIAL(handle);
  194. // Add handle to end of free list
  195. if (phs->dwNumFreeHandles == 0) // Only free handle
  196. {
  197. phs->dwFirstFreeHandle = phs->dwLastFreeHandle = dwIndex;
  198. }
  199. else // Other handles, so add to end of list
  200. {
  201. phs->HandleArray[phs->dwLastFreeHandle].Entry.dwIndex = dwIndex;
  202. phs->dwLastFreeHandle = dwIndex;
  203. }
  204. // Clear out returned handle
  205. phs->HandleArray[dwIndex].dwSerial = 0;
  206. phs->HandleArray[dwIndex].Entry.pvData = NULL;
  207. // Update handle structure
  208. INC_SERIAL_COUNT(phs);
  209. phs->dwNumFreeHandles++;
  210. EXIT_H_Destroy:
  211. // Unlock
  212. DNLeaveCriticalSection(&phs->dncs);
  213. DPFX(DPFPREP, 9,"Returning: [0x%lx]",hResultCode);
  214. return(hResultCode);
  215. }
  216. #undef DPF_MODNAME
  217. #define DPF_MODNAME "H_Retrieve"
  218. HRESULT H_Retrieve(HANDLESTRUCT *const phs,
  219. const DWORD handle,
  220. void **const ppvData)
  221. {
  222. DWORD dwIndex;
  223. DWORD dwSerial;
  224. HRESULT hResultCode = S_OK;
  225. DPFX(DPFPREP, 9,"Parameters: phs [0x%p], handle [0x%lx], ppvData [0x%p]",phs,handle,ppvData);
  226. // Lock
  227. DNEnterCriticalSection(&phs->dncs);
  228. // Ensure valid handle supplied
  229. if (!VERIFY_HANDLE(phs,handle))
  230. {
  231. DPFERR("Invalid handle");
  232. hResultCode = DPNERR_INVALIDHANDLE;
  233. goto EXIT_H_Retrieve;
  234. }
  235. if (ppvData == NULL)
  236. {
  237. DPFERR("Invalid data return pointer");
  238. hResultCode = DPNERR_INVALIDHANDLE;
  239. goto EXIT_H_Retrieve;
  240. }
  241. dwIndex = GET_INDEX(handle);
  242. dwSerial = GET_SERIAL(handle);
  243. *ppvData = phs->HandleArray[GET_INDEX(handle)].Entry.pvData;
  244. DPFX(DPFPREP, 9,"Returning: *ppvData = [0x%p]",*ppvData);
  245. EXIT_H_Retrieve:
  246. // Unlock
  247. DNLeaveCriticalSection(&phs->dncs);
  248. DPFX(DPFPREP, 9,"Returning: [0x%lx]",hResultCode);
  249. return(hResultCode);
  250. }
  251. #undef DPF_MODNAME
  252. #define DPF_MODNAME "H_Enum"
  253. HRESULT H_Enum(HANDLESTRUCT *const phs,
  254. DWORD *const pdwNumHandles,
  255. DWORD *const rgHandles)
  256. {
  257. HRESULT hResultCode;
  258. DWORD dw;
  259. DWORD dwNumHandles;
  260. DWORD *pHandle;
  261. DPFX(DPFPREP, 3,"Parameters: phs [0x%p], pdwNumHandles [0x%p], rgHandles [0x%p]",
  262. phs,pdwNumHandles,rgHandles);
  263. DNASSERT(phs != NULL);
  264. DNASSERT(pdwNumHandles != NULL);
  265. DNASSERT(rgHandles != NULL || *pdwNumHandles == 0);
  266. hResultCode = S_OK;
  267. dwNumHandles = 0;
  268. DNEnterCriticalSection(&phs->dncs);
  269. for (dw = 0 ; dw < phs->dwNumHandles ; dw++)
  270. {
  271. if (phs->HandleArray[dw].dwSerial != NULL)
  272. {
  273. DPFX(DPFPREP, 5,"Found handle data at [%ld]",dw);
  274. dwNumHandles++;
  275. }
  276. }
  277. if (dwNumHandles)
  278. {
  279. if( rgHandles == NULL )
  280. {
  281. DPFX(DPFPREP, 1, "Buffer too small!" );
  282. *pdwNumHandles = dwNumHandles;
  283. DNLeaveCriticalSection(&phs->dncs);
  284. return E_POINTER;
  285. }
  286. if (dwNumHandles <= *pdwNumHandles)
  287. {
  288. pHandle = rgHandles;
  289. for (dw = 0 ; dw < phs->dwNumHandles ; dw++)
  290. {
  291. if (phs->HandleArray[dw].dwSerial != NULL)
  292. {
  293. *pHandle++ = MAKE_HANDLE(dw,phs->HandleArray[dw].dwSerial);
  294. }
  295. }
  296. }
  297. else
  298. {
  299. hResultCode = E_POINTER;
  300. }
  301. }
  302. *pdwNumHandles = dwNumHandles;
  303. DNLeaveCriticalSection(&phs->dncs);
  304. DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
  305. return(hResultCode);
  306. }