- fixed definition of RtlImageRvaToVa
[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 /* RTL Atom Tables ************************************************************/
192
193 NTSTATUS
194 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable)
195 {
196 ExInitializeFastMutex(&AtomTable->FastMutex);
197
198 return STATUS_SUCCESS;
199 }
200
201
202 VOID
203 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable)
204 {
205 }
206
207
208 BOOLEAN
209 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable)
210 {
211 ExAcquireFastMutex(&AtomTable->FastMutex);
212 return TRUE;
213 }
214
215 VOID
216 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable)
217 {
218 ExReleaseFastMutex(&AtomTable->FastMutex);
219 }
220
221 BOOLEAN
222 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
223 {
224 AtomTable->ExHandleTable = ExCreateHandleTable(NULL);
225 return (AtomTable->ExHandleTable != NULL);
226 }
227
228 VOID
229 RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
230 {
231 if (AtomTable->ExHandleTable)
232 {
233 ExSweepHandleTable(AtomTable->ExHandleTable,
234 NULL,
235 NULL);
236 ExDestroyHandleTable(AtomTable->ExHandleTable);
237 AtomTable->ExHandleTable = NULL;
238 }
239 }
240
241 PRTL_ATOM_TABLE
242 RtlpAllocAtomTable(ULONG Size)
243 {
244 PRTL_ATOM_TABLE Table = ExAllocatePool(NonPagedPool,
245 Size);
246 if (Table != NULL)
247 {
248 RtlZeroMemory(Table,
249 Size);
250 }
251
252 return Table;
253 }
254
255 VOID
256 RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable)
257 {
258 ExFreePool(AtomTable);
259 }
260
261 PRTL_ATOM_TABLE_ENTRY
262 RtlpAllocAtomTableEntry(ULONG Size)
263 {
264 PRTL_ATOM_TABLE_ENTRY Entry = ExAllocatePool(NonPagedPool,
265 Size);
266 if (Entry != NULL)
267 {
268 RtlZeroMemory(Entry,
269 Size);
270 }
271
272 return Entry;
273 }
274
275 VOID
276 RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry)
277 {
278 ExFreePool(Entry);
279 }
280
281 VOID
282 RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
283 {
284 ExDestroyHandle(AtomTable->ExHandleTable,
285 (HANDLE)((ULONG_PTR)Entry->HandleIndex << 2));
286 }
287
288 BOOLEAN
289 RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
290 {
291 HANDLE_TABLE_ENTRY ExEntry;
292 HANDLE Handle;
293 USHORT HandleIndex;
294
295 ExEntry.u1.Object = Entry;
296 ExEntry.u2.GrantedAccess = 0x1; /* FIXME - valid handle */
297
298 Handle = ExCreateHandle(AtomTable->ExHandleTable,
299 &ExEntry);
300 if (Handle != NULL)
301 {
302 HandleIndex = (USHORT)((ULONG_PTR)Handle >> 2);
303 /* FIXME - Handle Indexes >= 0xC000 ?! */
304 if ((ULONG_PTR)HandleIndex >> 2 < 0xC000)
305 {
306 Entry->HandleIndex = HandleIndex;
307 Entry->Atom = 0xC000 + HandleIndex;
308
309 return TRUE;
310 }
311 else
312 ExDestroyHandle(AtomTable->ExHandleTable,
313 Handle);
314 }
315
316 return FALSE;
317 }
318
319 PRTL_ATOM_TABLE_ENTRY
320 RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable, ULONG Index)
321 {
322 PHANDLE_TABLE_ENTRY ExEntry;
323 PRTL_ATOM_TABLE_ENTRY Entry = NULL;
324
325 /* NOTE: There's no need to explicitly enter a critical region because it's
326 guaranteed that we're in a critical region right now (as we hold
327 the atom table lock) */
328
329 ExEntry = ExMapHandleToPointer(AtomTable->ExHandleTable,
330 (HANDLE)((ULONG_PTR)Index << 2));
331 if (ExEntry != NULL)
332 {
333 Entry = ExEntry->u1.Object;
334
335 ExUnlockHandleTableEntry(AtomTable->ExHandleTable,
336 ExEntry);
337 }
338
339 return Entry;
340 }
341
342 /* FIXME - RtlpCreateUnicodeString is obsolete and should be removed ASAP! */
343 BOOLEAN FASTCALL
344 RtlpCreateUnicodeString(
345 IN OUT PUNICODE_STRING UniDest,
346 IN PCWSTR Source,
347 IN POOL_TYPE PoolType)
348 {
349 ULONG Length;
350
351 Length = (wcslen (Source) + 1) * sizeof(WCHAR);
352 UniDest->Buffer = ExAllocatePoolWithTag(PoolType, Length, TAG('U', 'S', 'T', 'R'));
353 if (UniDest->Buffer == NULL)
354 return FALSE;
355
356 RtlCopyMemory (UniDest->Buffer,
357 Source,
358 Length);
359
360 UniDest->MaximumLength = Length;
361 UniDest->Length = Length - sizeof (WCHAR);
362
363 return TRUE;
364 }
365
366 /*
367 * Ldr Resource support code
368 */
369
370 IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir,
371 LPCWSTR name, void *root,
372 int want_dir );
373 IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( IMAGE_RESOURCE_DIRECTORY *dir,
374 WORD id, void *root, int want_dir );
375 IMAGE_RESOURCE_DIRECTORY *find_first_entry( IMAGE_RESOURCE_DIRECTORY *dir,
376 void *root, int want_dir );
377
378 /**********************************************************************
379 * find_entry
380 *
381 * Find a resource entry
382 */
383 NTSTATUS find_entry( PVOID BaseAddress, LDR_RESOURCE_INFO *info,
384 ULONG level, void **ret, int want_dir )
385 {
386 ULONG size;
387 void *root;
388 IMAGE_RESOURCE_DIRECTORY *resdirptr;
389
390 root = RtlImageDirectoryEntryToData( BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size );
391 if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND;
392 resdirptr = root;
393
394 if (!level--) goto done;
395 if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Type, root, want_dir || level )))
396 return STATUS_RESOURCE_TYPE_NOT_FOUND;
397 if (!level--) return STATUS_SUCCESS;
398
399 resdirptr = *ret;
400 if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Name, root, want_dir || level )))
401 return STATUS_RESOURCE_NAME_NOT_FOUND;
402 if (!level--) return STATUS_SUCCESS;
403 if (level) return STATUS_INVALID_PARAMETER; /* level > 3 */
404
405 resdirptr = *ret;
406
407 if ((*ret = find_first_entry( resdirptr, root, want_dir ))) return STATUS_SUCCESS;
408
409 return STATUS_RESOURCE_DATA_NOT_FOUND;
410
411 done:
412 *ret = resdirptr;
413 return STATUS_SUCCESS;
414 }
415
416
417 /* EOF */