- Implement new ExHandle* implementation using pushlocks and the Windows 2003 HANDLE_...
[reactos.git] / reactos / ntoskrnl / rtl / libsupp.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/rtl/libsupp.c
5 * PURPOSE: RTL Support Routines
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * Gunnar Dalsnes
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <internal/debug.h>
15
16 extern ULONG NtGlobalFlag;
17
18 /* FUNCTIONS *****************************************************************/
19
20 BOOLEAN
21 NTAPI
22 RtlpCheckForActiveDebugger(BOOLEAN Type)
23 {
24 /* This check is meaningless in kernel-mode */
25 return Type;
26 }
27
28 BOOLEAN
29 NTAPI
30 RtlpSetInDbgPrint(IN BOOLEAN NewValue)
31 {
32 /* This check is meaningless in kernel-mode */
33 return FALSE;
34 }
35
36 KPROCESSOR_MODE
37 STDCALL
38 RtlpGetMode()
39 {
40 return KernelMode;
41 }
42
43 PVOID
44 STDCALL
45 RtlpAllocateMemory(ULONG Bytes,
46 ULONG Tag)
47 {
48 return ExAllocatePoolWithTag(PagedPool,
49 (SIZE_T)Bytes,
50 Tag);
51 }
52
53
54 VOID
55 STDCALL
56 RtlpFreeMemory(PVOID Mem,
57 ULONG Tag)
58 {
59 ExFreePoolWithTag(Mem,
60 Tag);
61 }
62
63 /*
64 * @implemented
65 */
66 VOID STDCALL
67 RtlAcquirePebLock(VOID)
68 {
69
70 }
71
72 /*
73 * @implemented
74 */
75 VOID STDCALL
76 RtlReleasePebLock(VOID)
77 {
78
79 }
80
81 NTSTATUS
82 STDCALL
83 LdrShutdownThread(VOID)
84 {
85 return STATUS_SUCCESS;
86 }
87
88
89 PPEB
90 STDCALL
91 RtlpCurrentPeb(VOID)
92 {
93 return ((PEPROCESS)(KeGetCurrentThread()->ApcState.Process))->Peb;
94 }
95
96 NTSTATUS
97 STDCALL
98 RtlDeleteHeapLock(
99 PRTL_CRITICAL_SECTION CriticalSection)
100 {
101 KEBUGCHECK(0);
102 return STATUS_SUCCESS;
103 }
104
105 NTSTATUS
106 STDCALL
107 RtlEnterHeapLock(
108 PRTL_CRITICAL_SECTION CriticalSection)
109 {
110 KEBUGCHECK(0);
111 return STATUS_SUCCESS;
112 }
113
114 NTSTATUS
115 STDCALL
116 RtlInitializeHeapLock(
117 PRTL_CRITICAL_SECTION CriticalSection)
118 {
119 KEBUGCHECK(0);
120 return STATUS_SUCCESS;
121 }
122
123 NTSTATUS
124 STDCALL
125 RtlLeaveHeapLock(
126 PRTL_CRITICAL_SECTION CriticalSection)
127 {
128 KEBUGCHECK(0);
129 return STATUS_SUCCESS;
130 }
131
132 #ifdef DBG
133 VOID FASTCALL
134 CHECK_PAGED_CODE_RTL(char *file, int line)
135 {
136 if(KeGetCurrentIrql() > APC_LEVEL)
137 {
138 DbgPrint("%s:%i: Pagable code called at IRQL > APC_LEVEL (%d)\n", file, line, KeGetCurrentIrql());
139 KEBUGCHECK(0);
140 }
141 }
142 #endif
143
144 VOID
145 NTAPI
146 RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord,
147 IN PCONTEXT ContextRecord,
148 IN PVOID ContextData,
149 IN ULONG Size)
150 {
151 /* Check the global flag */
152 if (NtGlobalFlag & FLG_ENABLE_EXCEPTION_LOGGING)
153 {
154 /* FIXME: Log this exception */
155 }
156 }
157
158 BOOLEAN
159 NTAPI
160 RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame,
161 IN ULONG_PTR RegistrationFrameEnd,
162 IN OUT PULONG_PTR StackLow,
163 IN OUT PULONG_PTR StackHigh)
164 {
165 PKPRCB Prcb;
166 ULONG_PTR DpcStack;
167
168 /* Check if we are at DISPATCH or higher */
169 if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
170 {
171 /* Get the PRCB and DPC Stack */
172 Prcb = KeGetCurrentPrcb();
173 DpcStack = (ULONG_PTR)Prcb->DpcStack;
174
175 /* Check if we are in a DPC and the stack matches */
176 if ((Prcb->DpcRoutineActive) &&
177 (RegistrationFrameEnd <= DpcStack) &&
178 ((ULONG_PTR)RegistrationFrame >= DpcStack - 4096))
179 {
180 /* Update the limits to the DPC Stack's */
181 *StackHigh = DpcStack;
182 *StackLow = DpcStack - 4096;
183 return TRUE;
184 }
185 }
186
187 /* Not in DPC stack */
188 return FALSE;
189 }
190
191 BOOLEAN
192 NTAPI
193 RtlpCaptureStackLimits(IN ULONG_PTR Ebp,
194 IN ULONG_PTR *StackBegin,
195 IN ULONG_PTR *StackEnd)
196 {
197 PKTHREAD Thread = KeGetCurrentThread();
198
199 /* FIXME: Super native implementation */
200
201 /* Start with defaults */
202 *StackBegin = Thread->StackLimit;
203 *StackEnd = (ULONG_PTR)Thread->StackBase;
204
205 /* Check if we seem to be on the DPC stack */
206 if ((*StackBegin > Ebp) || (Ebp > *StackEnd))
207 {
208 /* FIXME: TODO */
209 //ASSERT(FALSE);
210 DPRINT1("Stacks: %p %p %p\n", Ebp, *StackBegin, *StackEnd);
211 }
212
213 /* Return success */
214 return TRUE;
215 }
216
217 /* RTL Atom Tables ************************************************************/
218
219 NTSTATUS
220 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable)
221 {
222 ExInitializeFastMutex(&AtomTable->FastMutex);
223
224 return STATUS_SUCCESS;
225 }
226
227
228 VOID
229 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable)
230 {
231 }
232
233
234 BOOLEAN
235 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable)
236 {
237 ExAcquireFastMutex(&AtomTable->FastMutex);
238 return TRUE;
239 }
240
241 VOID
242 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable)
243 {
244 ExReleaseFastMutex(&AtomTable->FastMutex);
245 }
246
247 BOOLEAN
248 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
249 {
250 AtomTable->ExHandleTable = ExCreateHandleTable(NULL);
251 return (AtomTable->ExHandleTable != NULL);
252 }
253
254 VOID
255 RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
256 {
257 if (AtomTable->ExHandleTable)
258 {
259 ExSweepHandleTable(AtomTable->ExHandleTable,
260 NULL,
261 NULL);
262 ExDestroyHandleTable(AtomTable->ExHandleTable, NULL);
263 AtomTable->ExHandleTable = NULL;
264 }
265 }
266
267 PRTL_ATOM_TABLE
268 RtlpAllocAtomTable(ULONG Size)
269 {
270 PRTL_ATOM_TABLE Table = ExAllocatePool(NonPagedPool,
271 Size);
272 if (Table != NULL)
273 {
274 RtlZeroMemory(Table,
275 Size);
276 }
277
278 return Table;
279 }
280
281 VOID
282 RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable)
283 {
284 ExFreePool(AtomTable);
285 }
286
287 PRTL_ATOM_TABLE_ENTRY
288 RtlpAllocAtomTableEntry(ULONG Size)
289 {
290 PRTL_ATOM_TABLE_ENTRY Entry = ExAllocatePool(NonPagedPool,
291 Size);
292 if (Entry != NULL)
293 {
294 RtlZeroMemory(Entry,
295 Size);
296 }
297
298 return Entry;
299 }
300
301 VOID
302 RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry)
303 {
304 ExFreePool(Entry);
305 }
306
307 VOID
308 RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
309 {
310 ExDestroyHandle(AtomTable->ExHandleTable,
311 (HANDLE)((ULONG_PTR)Entry->HandleIndex << 2),
312 NULL);
313 }
314
315 BOOLEAN
316 RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
317 {
318 HANDLE_TABLE_ENTRY ExEntry;
319 HANDLE Handle;
320 USHORT HandleIndex;
321
322 ExEntry.Object = Entry;
323 ExEntry.GrantedAccess = 0x1; /* FIXME - valid handle */
324
325 Handle = ExCreateHandle(AtomTable->ExHandleTable,
326 &ExEntry);
327 if (Handle != NULL)
328 {
329 HandleIndex = (USHORT)((ULONG_PTR)Handle >> 2);
330 /* FIXME - Handle Indexes >= 0xC000 ?! */
331 if ((ULONG_PTR)HandleIndex >> 2 < 0xC000)
332 {
333 Entry->HandleIndex = HandleIndex;
334 Entry->Atom = 0xC000 + HandleIndex;
335
336 return TRUE;
337 }
338 else
339 ExDestroyHandle(AtomTable->ExHandleTable,
340 Handle,
341 NULL);
342 }
343
344 return FALSE;
345 }
346
347 PRTL_ATOM_TABLE_ENTRY
348 RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable, ULONG Index)
349 {
350 PHANDLE_TABLE_ENTRY ExEntry;
351 PRTL_ATOM_TABLE_ENTRY Entry = NULL;
352
353 /* NOTE: There's no need to explicitly enter a critical region because it's
354 guaranteed that we're in a critical region right now (as we hold
355 the atom table lock) */
356
357 ExEntry = ExMapHandleToPointer(AtomTable->ExHandleTable,
358 (HANDLE)((ULONG_PTR)Index << 2));
359 if (ExEntry != NULL)
360 {
361 Entry = ExEntry->Object;
362
363 ExUnlockHandleTableEntry(AtomTable->ExHandleTable,
364 ExEntry);
365 }
366
367 return Entry;
368 }
369
370 /* FIXME - RtlpCreateUnicodeString is obsolete and should be removed ASAP! */
371 BOOLEAN FASTCALL
372 RtlpCreateUnicodeString(
373 IN OUT PUNICODE_STRING UniDest,
374 IN PCWSTR Source,
375 IN POOL_TYPE PoolType)
376 {
377 ULONG Length;
378
379 Length = (wcslen (Source) + 1) * sizeof(WCHAR);
380 UniDest->Buffer = ExAllocatePoolWithTag(PoolType, Length, TAG('U', 'S', 'T', 'R'));
381 if (UniDest->Buffer == NULL)
382 return FALSE;
383
384 RtlCopyMemory (UniDest->Buffer,
385 Source,
386 Length);
387
388 UniDest->MaximumLength = (USHORT)Length;
389 UniDest->Length = (USHORT)Length - sizeof (WCHAR);
390
391 return TRUE;
392 }
393
394 /*
395 * Ldr Resource support code
396 */
397
398 IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir,
399 LPCWSTR name, void *root,
400 int want_dir );
401 IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( IMAGE_RESOURCE_DIRECTORY *dir,
402 USHORT id, void *root, int want_dir );
403 IMAGE_RESOURCE_DIRECTORY *find_first_entry( IMAGE_RESOURCE_DIRECTORY *dir,
404 void *root, int want_dir );
405
406 /**********************************************************************
407 * find_entry
408 *
409 * Find a resource entry
410 */
411 NTSTATUS find_entry( PVOID BaseAddress, LDR_RESOURCE_INFO *info,
412 ULONG level, void **ret, int want_dir )
413 {
414 ULONG size;
415 void *root;
416 IMAGE_RESOURCE_DIRECTORY *resdirptr;
417
418 root = RtlImageDirectoryEntryToData( BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size );
419 if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND;
420 resdirptr = root;
421
422 if (!level--) goto done;
423 if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Type, root, want_dir || level )))
424 return STATUS_RESOURCE_TYPE_NOT_FOUND;
425 if (!level--) return STATUS_SUCCESS;
426
427 resdirptr = *ret;
428 if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Name, root, want_dir || level )))
429 return STATUS_RESOURCE_NAME_NOT_FOUND;
430 if (!level--) return STATUS_SUCCESS;
431 if (level) return STATUS_INVALID_PARAMETER; /* level > 3 */
432
433 resdirptr = *ret;
434
435 if ((*ret = find_first_entry( resdirptr, root, want_dir ))) return STATUS_SUCCESS;
436
437 return STATUS_RESOURCE_DATA_NOT_FOUND;
438
439 done:
440 *ret = resdirptr;
441 return STATUS_SUCCESS;
442 }
443
444
445 /* EOF */