Big merge: thanks alex and greatlord. Not a complete merge but most
[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(UINT 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 /* FIXME: ROS HACK */
202 if (!Thread) return FALSE;
203
204 /* Start with defaults */
205 *StackBegin = Thread->StackLimit;
206 *StackEnd = (ULONG_PTR)Thread->StackBase;
207
208 /* Check if we seem to be on the DPC stack */
209 if ((*StackBegin > Ebp) || (Ebp > *StackEnd))
210 {
211 /* FIXME: TODO */
212 ASSERT(FALSE);
213 }
214
215 /* Return success */
216 return TRUE;
217 }
218
219 /* RTL Atom Tables ************************************************************/
220
221 NTSTATUS
222 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable)
223 {
224 ExInitializeFastMutex(&AtomTable->FastMutex);
225
226 return STATUS_SUCCESS;
227 }
228
229
230 VOID
231 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable)
232 {
233 }
234
235
236 BOOLEAN
237 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable)
238 {
239 ExAcquireFastMutex(&AtomTable->FastMutex);
240 return TRUE;
241 }
242
243 VOID
244 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable)
245 {
246 ExReleaseFastMutex(&AtomTable->FastMutex);
247 }
248
249 BOOLEAN
250 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
251 {
252 AtomTable->ExHandleTable = ExCreateHandleTable(NULL);
253 return (AtomTable->ExHandleTable != NULL);
254 }
255
256 VOID
257 RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
258 {
259 if (AtomTable->ExHandleTable)
260 {
261 ExSweepHandleTable(AtomTable->ExHandleTable,
262 NULL,
263 NULL);
264 ExDestroyHandleTable(AtomTable->ExHandleTable);
265 AtomTable->ExHandleTable = NULL;
266 }
267 }
268
269 PRTL_ATOM_TABLE
270 RtlpAllocAtomTable(ULONG Size)
271 {
272 PRTL_ATOM_TABLE Table = ExAllocatePool(NonPagedPool,
273 Size);
274 if (Table != NULL)
275 {
276 RtlZeroMemory(Table,
277 Size);
278 }
279
280 return Table;
281 }
282
283 VOID
284 RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable)
285 {
286 ExFreePool(AtomTable);
287 }
288
289 PRTL_ATOM_TABLE_ENTRY
290 RtlpAllocAtomTableEntry(ULONG Size)
291 {
292 PRTL_ATOM_TABLE_ENTRY Entry = ExAllocatePool(NonPagedPool,
293 Size);
294 if (Entry != NULL)
295 {
296 RtlZeroMemory(Entry,
297 Size);
298 }
299
300 return Entry;
301 }
302
303 VOID
304 RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry)
305 {
306 ExFreePool(Entry);
307 }
308
309 VOID
310 RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
311 {
312 ExDestroyHandle(AtomTable->ExHandleTable,
313 (HANDLE)((ULONG_PTR)Entry->HandleIndex << 2));
314 }
315
316 BOOLEAN
317 RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
318 {
319 HANDLE_TABLE_ENTRY ExEntry;
320 HANDLE Handle;
321 USHORT HandleIndex;
322
323 ExEntry.Object = Entry;
324 ExEntry.GrantedAccess = 0x1; /* FIXME - valid handle */
325
326 Handle = ExCreateHandle(AtomTable->ExHandleTable,
327 &ExEntry);
328 if (Handle != NULL)
329 {
330 HandleIndex = (USHORT)((ULONG_PTR)Handle >> 2);
331 /* FIXME - Handle Indexes >= 0xC000 ?! */
332 if ((ULONG_PTR)HandleIndex >> 2 < 0xC000)
333 {
334 Entry->HandleIndex = HandleIndex;
335 Entry->Atom = 0xC000 + HandleIndex;
336
337 return TRUE;
338 }
339 else
340 ExDestroyHandle(AtomTable->ExHandleTable,
341 Handle);
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 = Length;
389 UniDest->Length = 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 WORD 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 */