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.

231 lines
6.2 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. handle.c
  5. Abstract:
  6. This module contains a simple handle allocator for use by the Local and
  7. Global memory allocators.
  8. Author:
  9. Steve Wood (stevewo) 25-Jul-1991
  10. Revision History:
  11. --*/
  12. #include "ntrtlp.h"
  13. void
  14. RtlInitializeHandleTable(
  15. IN ULONG MaximumNumberOfHandles,
  16. IN ULONG SizeOfHandleTableEntry,
  17. OUT PRTL_HANDLE_TABLE HandleTable
  18. )
  19. {
  20. RtlZeroMemory( HandleTable, sizeof( *HandleTable ) );
  21. HandleTable->MaximumNumberOfHandles = MaximumNumberOfHandles;
  22. HandleTable->SizeOfHandleTableEntry = SizeOfHandleTableEntry;
  23. return;
  24. }
  25. NTSTATUS
  26. RtlDestroyHandleTable(
  27. IN OUT PRTL_HANDLE_TABLE HandleTable
  28. )
  29. {
  30. NTSTATUS Status;
  31. PVOID BaseAddress;
  32. SIZE_T ReserveSize;
  33. BaseAddress = HandleTable->CommittedHandles;
  34. ReserveSize = (PUCHAR)(HandleTable->MaxReservedHandles) -
  35. (PUCHAR)(HandleTable->CommittedHandles);
  36. Status = NtFreeVirtualMemory( NtCurrentProcess(),
  37. &BaseAddress,
  38. &ReserveSize,
  39. MEM_RELEASE
  40. );
  41. return Status;
  42. }
  43. PRTL_HANDLE_TABLE_ENTRY
  44. RtlAllocateHandle(
  45. IN PRTL_HANDLE_TABLE HandleTable,
  46. OUT PULONG HandleIndex OPTIONAL
  47. )
  48. {
  49. NTSTATUS Status;
  50. PVOID BaseAddress;
  51. ULONG n;
  52. SIZE_T ReserveSize;
  53. SIZE_T CommitSize;
  54. PRTL_HANDLE_TABLE_ENTRY p, *pp;
  55. if (HandleTable->FreeHandles == NULL) {
  56. try {
  57. if (HandleTable->UnCommittedHandles == NULL) {
  58. ReserveSize = HandleTable->MaximumNumberOfHandles *
  59. HandleTable->SizeOfHandleTableEntry;
  60. BaseAddress = NULL;
  61. Status = NtAllocateVirtualMemory( NtCurrentProcess(),
  62. &BaseAddress,
  63. 0,
  64. &ReserveSize,
  65. MEM_RESERVE,
  66. PAGE_READWRITE
  67. );
  68. if (NT_SUCCESS( Status )) {
  69. HandleTable->CommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)BaseAddress;
  70. HandleTable->UnCommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)BaseAddress;
  71. HandleTable->MaxReservedHandles = (PRTL_HANDLE_TABLE_ENTRY)
  72. ((PCHAR)BaseAddress + ReserveSize);
  73. }
  74. }
  75. else {
  76. Status = STATUS_SUCCESS;
  77. }
  78. if (NT_SUCCESS( Status )) {
  79. p = HandleTable->UnCommittedHandles;
  80. if (p >= HandleTable->MaxReservedHandles) {
  81. Status = STATUS_NO_MEMORY;
  82. }
  83. else {
  84. CommitSize = PAGE_SIZE;
  85. Status = NtAllocateVirtualMemory( NtCurrentProcess(),
  86. (PVOID *)&p,
  87. 0,
  88. &CommitSize,
  89. MEM_COMMIT,
  90. PAGE_READWRITE
  91. );
  92. if (NT_SUCCESS( Status )) {
  93. HandleTable->UnCommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)
  94. ((PCH)p + CommitSize);
  95. }
  96. }
  97. }
  98. }
  99. except( EXCEPTION_EXECUTE_HANDLER ) {
  100. Status = GetExceptionCode();
  101. }
  102. if (!NT_SUCCESS( Status )) {
  103. return NULL;
  104. }
  105. pp = &HandleTable->FreeHandles;
  106. while (p < HandleTable->UnCommittedHandles) {
  107. *pp = p;
  108. pp = &p->NextFree;
  109. p = (PRTL_HANDLE_TABLE_ENTRY)((PUCHAR)p + HandleTable->SizeOfHandleTableEntry);
  110. }
  111. }
  112. //
  113. // Remove handle table entry from head of free list.
  114. //
  115. p = HandleTable->FreeHandles;
  116. HandleTable->FreeHandles = p->NextFree;
  117. //
  118. // Clear free list link field, which also leaves the handle allocated bit
  119. // clear. This allows the caller to mark it is allocated after they are
  120. // done filling in their portion.
  121. //
  122. p->NextFree = NULL;
  123. //
  124. // If requested, return the index of this handle table entry
  125. //
  126. if (ARGUMENT_PRESENT( HandleIndex )) {
  127. *HandleIndex = (ULONG) (((PCHAR)p - (PCHAR)HandleTable->CommittedHandles) /
  128. HandleTable->SizeOfHandleTableEntry);
  129. }
  130. //
  131. // Return a pointer to the handle table entry.
  132. //
  133. return p;
  134. }
  135. BOOLEAN
  136. RtlFreeHandle(
  137. IN PRTL_HANDLE_TABLE HandleTable,
  138. IN PRTL_HANDLE_TABLE_ENTRY Handle
  139. )
  140. {
  141. #if DBG
  142. if (!RtlIsValidHandle( HandleTable, Handle )) {
  143. DbgPrint( "RTL: RtlFreeHandle( %lx ) - invalid handle\n", Handle );
  144. if (NtCurrentPeb()->BeingDebugged) {
  145. DbgBreakPoint();
  146. }
  147. return FALSE;
  148. }
  149. #endif
  150. RtlZeroMemory( Handle, HandleTable->SizeOfHandleTableEntry );
  151. Handle->NextFree = HandleTable->FreeHandles;
  152. HandleTable->FreeHandles = Handle;
  153. return TRUE;
  154. }
  155. BOOLEAN
  156. RtlIsValidHandle(
  157. IN PRTL_HANDLE_TABLE HandleTable,
  158. IN PRTL_HANDLE_TABLE_ENTRY Handle
  159. )
  160. {
  161. if (Handle == NULL ||
  162. Handle < HandleTable->CommittedHandles ||
  163. Handle >= HandleTable->UnCommittedHandles ||
  164. (ULONG_PTR)Handle & (HandleTable->SizeOfHandleTableEntry - 1) ||
  165. !(Handle->Flags & RTL_HANDLE_ALLOCATED)
  166. ) {
  167. return FALSE;
  168. }
  169. else {
  170. return TRUE;
  171. }
  172. }
  173. BOOLEAN
  174. RtlIsValidIndexHandle(
  175. IN PRTL_HANDLE_TABLE HandleTable,
  176. IN ULONG HandleIndex,
  177. OUT PRTL_HANDLE_TABLE_ENTRY *Handle
  178. )
  179. {
  180. PRTL_HANDLE_TABLE_ENTRY p;
  181. p = (PRTL_HANDLE_TABLE_ENTRY)
  182. ((PCHAR)HandleTable->CommittedHandles + (HandleIndex * HandleTable->SizeOfHandleTableEntry));
  183. if (RtlIsValidHandle( HandleTable, p )) {
  184. *Handle = p;
  185. return TRUE;
  186. }
  187. else {
  188. return FALSE;
  189. }
  190. }