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.

236 lines
6.5 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 = STATUS_SUCCESS;
  37. if (ARGUMENT_PRESENT (BaseAddress))
  38. {
  39. Status = NtFreeVirtualMemory( NtCurrentProcess(),
  40. &BaseAddress,
  41. &ReserveSize,
  42. MEM_RELEASE
  43. );
  44. }
  45. return Status;
  46. }
  47. PRTL_HANDLE_TABLE_ENTRY
  48. RtlAllocateHandle(
  49. IN PRTL_HANDLE_TABLE HandleTable,
  50. OUT PULONG HandleIndex OPTIONAL
  51. )
  52. {
  53. NTSTATUS Status;
  54. PVOID BaseAddress;
  55. ULONG n;
  56. SIZE_T ReserveSize;
  57. SIZE_T CommitSize;
  58. PRTL_HANDLE_TABLE_ENTRY p, *pp;
  59. if (HandleTable->FreeHandles == NULL) {
  60. try {
  61. if (HandleTable->UnCommittedHandles == NULL) {
  62. ReserveSize = HandleTable->MaximumNumberOfHandles *
  63. HandleTable->SizeOfHandleTableEntry;
  64. BaseAddress = NULL;
  65. Status = NtAllocateVirtualMemory( NtCurrentProcess(),
  66. &BaseAddress,
  67. 0,
  68. &ReserveSize,
  69. MEM_RESERVE,
  70. PAGE_READWRITE
  71. );
  72. if (NT_SUCCESS( Status )) {
  73. HandleTable->CommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)BaseAddress;
  74. HandleTable->UnCommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)BaseAddress;
  75. HandleTable->MaxReservedHandles = (PRTL_HANDLE_TABLE_ENTRY)
  76. ((PCHAR)BaseAddress + ReserveSize);
  77. }
  78. }
  79. else {
  80. Status = STATUS_SUCCESS;
  81. }
  82. if (NT_SUCCESS( Status )) {
  83. p = HandleTable->UnCommittedHandles;
  84. if (p >= HandleTable->MaxReservedHandles) {
  85. Status = STATUS_NO_MEMORY;
  86. }
  87. else {
  88. CommitSize = PAGE_SIZE;
  89. Status = NtAllocateVirtualMemory( NtCurrentProcess(),
  90. (PVOID *)&p,
  91. 0,
  92. &CommitSize,
  93. MEM_COMMIT,
  94. PAGE_READWRITE
  95. );
  96. if (NT_SUCCESS( Status )) {
  97. HandleTable->UnCommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)
  98. ((PCH)p + CommitSize);
  99. }
  100. }
  101. }
  102. }
  103. except( EXCEPTION_EXECUTE_HANDLER ) {
  104. Status = GetExceptionCode();
  105. }
  106. if (!NT_SUCCESS( Status )) {
  107. return NULL;
  108. }
  109. pp = &HandleTable->FreeHandles;
  110. while (p < HandleTable->UnCommittedHandles) {
  111. *pp = p;
  112. pp = &p->NextFree;
  113. p = (PRTL_HANDLE_TABLE_ENTRY)((PUCHAR)p + HandleTable->SizeOfHandleTableEntry);
  114. }
  115. }
  116. //
  117. // Remove handle table entry from head of free list.
  118. //
  119. p = HandleTable->FreeHandles;
  120. HandleTable->FreeHandles = p->NextFree;
  121. //
  122. // Clear free list link field, which also leaves the handle allocated bit
  123. // clear. This allows the caller to mark it is allocated after they are
  124. // done filling in their portion.
  125. //
  126. p->NextFree = NULL;
  127. //
  128. // If requested, return the index of this handle table entry
  129. //
  130. if (ARGUMENT_PRESENT( HandleIndex )) {
  131. *HandleIndex = (ULONG) (((PCHAR)p - (PCHAR)HandleTable->CommittedHandles) /
  132. HandleTable->SizeOfHandleTableEntry);
  133. }
  134. //
  135. // Return a pointer to the handle table entry.
  136. //
  137. return p;
  138. }
  139. BOOLEAN
  140. RtlFreeHandle(
  141. IN PRTL_HANDLE_TABLE HandleTable,
  142. IN PRTL_HANDLE_TABLE_ENTRY Handle
  143. )
  144. {
  145. #if DBG
  146. if (!RtlIsValidHandle( HandleTable, Handle )) {
  147. DbgPrint( "RTL: RtlFreeHandle( %lx ) - invalid handle\n", Handle );
  148. if (NtCurrentPeb()->BeingDebugged) {
  149. DbgBreakPoint();
  150. }
  151. return FALSE;
  152. }
  153. #endif
  154. RtlZeroMemory( Handle, HandleTable->SizeOfHandleTableEntry );
  155. Handle->NextFree = HandleTable->FreeHandles;
  156. HandleTable->FreeHandles = Handle;
  157. return TRUE;
  158. }
  159. BOOLEAN
  160. RtlIsValidHandle(
  161. IN PRTL_HANDLE_TABLE HandleTable,
  162. IN PRTL_HANDLE_TABLE_ENTRY Handle
  163. )
  164. {
  165. if (Handle == NULL ||
  166. Handle < HandleTable->CommittedHandles ||
  167. Handle >= HandleTable->UnCommittedHandles ||
  168. (ULONG_PTR)Handle & (HandleTable->SizeOfHandleTableEntry - 1) ||
  169. !(Handle->Flags & RTL_HANDLE_ALLOCATED)
  170. ) {
  171. return FALSE;
  172. }
  173. else {
  174. return TRUE;
  175. }
  176. }
  177. BOOLEAN
  178. RtlIsValidIndexHandle(
  179. IN PRTL_HANDLE_TABLE HandleTable,
  180. IN ULONG HandleIndex,
  181. OUT PRTL_HANDLE_TABLE_ENTRY *Handle
  182. )
  183. {
  184. PRTL_HANDLE_TABLE_ENTRY p;
  185. p = (PRTL_HANDLE_TABLE_ENTRY)
  186. ((PCHAR)HandleTable->CommittedHandles + (HandleIndex * HandleTable->SizeOfHandleTableEntry));
  187. if (RtlIsValidHandle( HandleTable, p )) {
  188. *Handle = p;
  189. return TRUE;
  190. }
  191. else {
  192. return FALSE;
  193. }
  194. }