- Implement RtlCaptureStackBackTrace and RtlWalkFrameChain and add definitions to...
[reactos.git] / reactos / dll / ntdll / rtl / libsupp.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NT User-Mode DLL
4 * FILE: lib/ntdll/rtl/libsup.c
5 * PURPOSE: RTL Support Routines
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * Gunnar Dalsnes
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <ntdll.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* FUNCTIONS ***************************************************************/
17
18 BOOLEAN
19 NTAPI
20 RtlpCheckForActiveDebugger(BOOLEAN Type)
21 {
22 return (NtCurrentPeb()->BeingDebugged);
23 }
24
25 BOOLEAN
26 NTAPI
27 RtlpSetInDbgPrint(IN BOOLEAN NewValue)
28 {
29 /* If we're setting it to false, do it and return */
30 if (NewValue == FALSE)
31 {
32 NtCurrentTeb()->InDbgPrint = FALSE;
33 return FALSE;
34 }
35
36 /* Setting to true; check if it's not already */
37 if (NtCurrentTeb()->InDbgPrint) return TRUE;
38
39 /* Set it and return */
40 NtCurrentTeb()->InDbgPrint = TRUE;
41 return FALSE;
42 }
43
44 KPROCESSOR_MODE
45 NTAPI
46 RtlpGetMode()
47 {
48 return UserMode;
49 }
50
51 PPEB
52 NTAPI
53 RtlpCurrentPeb(VOID)
54 {
55 return NtCurrentPeb();
56 }
57
58 /*
59 * @implemented
60 */
61 VOID NTAPI
62 RtlAcquirePebLock(VOID)
63 {
64 PPEB Peb = NtCurrentPeb ();
65 Peb->FastPebLockRoutine (Peb->FastPebLock);
66 }
67
68 /*
69 * @implemented
70 */
71 VOID NTAPI
72 RtlReleasePebLock(VOID)
73 {
74 PPEB Peb = NtCurrentPeb ();
75 Peb->FastPebUnlockRoutine (Peb->FastPebLock);
76 }
77
78 /*
79 * @implemented
80 */
81 ULONG
82 NTAPI
83 RtlGetNtGlobalFlags(VOID)
84 {
85 PPEB pPeb = NtCurrentPeb();
86 return pPeb->NtGlobalFlag;
87 }
88
89 NTSTATUS
90 NTAPI
91 RtlDeleteHeapLock(
92 PRTL_CRITICAL_SECTION CriticalSection)
93 {
94 return RtlDeleteCriticalSection(CriticalSection);
95 }
96
97 NTSTATUS
98 NTAPI
99 RtlEnterHeapLock(
100 PRTL_CRITICAL_SECTION CriticalSection)
101 {
102 return RtlEnterCriticalSection(CriticalSection);
103 }
104
105 NTSTATUS
106 NTAPI
107 RtlInitializeHeapLock(
108 PRTL_CRITICAL_SECTION CriticalSection)
109 {
110 return RtlInitializeCriticalSection(CriticalSection);
111 }
112
113 NTSTATUS
114 NTAPI
115 RtlLeaveHeapLock(
116 PRTL_CRITICAL_SECTION CriticalSection)
117 {
118 return RtlLeaveCriticalSection(CriticalSection );
119 }
120
121 PVOID
122 NTAPI
123 RtlpAllocateMemory(UINT Bytes,
124 ULONG Tag)
125 {
126 UNREFERENCED_PARAMETER(Tag);
127
128 return RtlAllocateHeap(RtlGetProcessHeap(),
129 0,
130 Bytes);
131 }
132
133
134 VOID
135 NTAPI
136 RtlpFreeMemory(PVOID Mem,
137 ULONG Tag)
138 {
139 UNREFERENCED_PARAMETER(Tag);
140
141 RtlFreeHeap(RtlGetProcessHeap(),
142 0,
143 Mem);
144 }
145
146
147 #ifdef DBG
148 VOID FASTCALL
149 CHECK_PAGED_CODE_RTL(char *file, int line)
150 {
151 /* meaningless in user mode */
152 }
153 #endif
154
155 BOOLEAN
156 NTAPI
157 RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame,
158 IN ULONG_PTR RegistrationFrameEnd,
159 IN OUT PULONG_PTR StackLow,
160 IN OUT PULONG_PTR StackHigh)
161 {
162 /* There's no such thing as a DPC stack in user-mode */
163 return FALSE;
164 }
165
166 VOID
167 NTAPI
168 RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord,
169 IN PCONTEXT ContextRecord,
170 IN PVOID ContextData,
171 IN ULONG Size)
172 {
173 /* Exception logging is not done in user-mode */
174 }
175
176 BOOLEAN
177 NTAPI
178 RtlpCaptureStackLimits(IN ULONG_PTR Ebp,
179 IN ULONG_PTR *StackBegin,
180 IN ULONG_PTR *StackEnd)
181 {
182 /* FIXME: Verify */
183 *StackBegin = (ULONG_PTR)NtCurrentTeb()->Tib.StackLimit;
184 *StackEnd = (ULONG_PTR)NtCurrentTeb()->Tib.StackBase;
185 return TRUE;
186 }
187
188 /* RTL Atom Tables ************************************************************/
189
190 typedef struct _RTL_ATOM_HANDLE
191 {
192 RTL_HANDLE_TABLE_ENTRY Handle;
193 PRTL_ATOM_TABLE_ENTRY AtomEntry;
194 } RTL_ATOM_HANDLE, *PRTL_ATOM_HANDLE;
195
196 NTSTATUS
197 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable)
198 {
199 RtlInitializeCriticalSection(&AtomTable->CriticalSection);
200 return STATUS_SUCCESS;
201 }
202
203
204 VOID
205 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable)
206 {
207 RtlDeleteCriticalSection(&AtomTable->CriticalSection);
208 }
209
210
211 BOOLEAN
212 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable)
213 {
214 RtlEnterCriticalSection(&AtomTable->CriticalSection);
215 return TRUE;
216 }
217
218
219 VOID
220 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable)
221 {
222 RtlLeaveCriticalSection(&AtomTable->CriticalSection);
223 }
224
225
226 /* handle functions */
227
228 BOOLEAN
229 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
230 {
231 RtlInitializeHandleTable(0xCFFF,
232 sizeof(RTL_ATOM_HANDLE),
233 &AtomTable->RtlHandleTable);
234
235 return TRUE;
236 }
237
238 VOID
239 RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
240 {
241 RtlDestroyHandleTable(&AtomTable->RtlHandleTable);
242 }
243
244 PRTL_ATOM_TABLE
245 RtlpAllocAtomTable(ULONG Size)
246 {
247 return (PRTL_ATOM_TABLE)RtlAllocateHeap(RtlGetProcessHeap(),
248 HEAP_ZERO_MEMORY,
249 Size);
250 }
251
252 VOID
253 RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable)
254 {
255 RtlFreeHeap(RtlGetProcessHeap(),
256 0,
257 AtomTable);
258 }
259
260 PRTL_ATOM_TABLE_ENTRY
261 RtlpAllocAtomTableEntry(ULONG Size)
262 {
263 return (PRTL_ATOM_TABLE_ENTRY)RtlAllocateHeap(RtlGetProcessHeap(),
264 HEAP_ZERO_MEMORY,
265 Size);
266 }
267
268 VOID
269 RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry)
270 {
271 RtlFreeHeap(RtlGetProcessHeap(),
272 0,
273 Entry);
274 }
275
276 VOID
277 RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
278 {
279 PRTL_HANDLE_TABLE_ENTRY RtlHandleEntry;
280
281 if (RtlIsValidIndexHandle(&AtomTable->RtlHandleTable,
282 (ULONG)Entry->HandleIndex,
283 &RtlHandleEntry))
284 {
285 RtlFreeHandle(&AtomTable->RtlHandleTable,
286 RtlHandleEntry);
287 }
288 }
289
290 BOOLEAN
291 RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
292 {
293 ULONG HandleIndex;
294 PRTL_HANDLE_TABLE_ENTRY RtlHandle;
295
296 RtlHandle = RtlAllocateHandle(&AtomTable->RtlHandleTable,
297 &HandleIndex);
298 if (RtlHandle != NULL)
299 {
300 PRTL_ATOM_HANDLE AtomHandle = (PRTL_ATOM_HANDLE)RtlHandle;
301
302 /* FIXME - Handle Indexes >= 0xC000 ?! */
303 if (HandleIndex < 0xC000)
304 {
305 Entry->HandleIndex = (USHORT)HandleIndex;
306 Entry->Atom = 0xC000 + (USHORT)HandleIndex;
307
308 AtomHandle->AtomEntry = Entry;
309 AtomHandle->Handle.Flags = RTL_HANDLE_VALID;
310
311 return TRUE;
312 }
313 else
314 {
315 /* set the valid flag, otherwise RtlFreeHandle will fail! */
316 AtomHandle->Handle.Flags = RTL_HANDLE_VALID;
317
318 RtlFreeHandle(&AtomTable->RtlHandleTable,
319 RtlHandle);
320 }
321 }
322
323 return FALSE;
324 }
325
326 PRTL_ATOM_TABLE_ENTRY
327 RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable, ULONG Index)
328 {
329 PRTL_HANDLE_TABLE_ENTRY RtlHandle;
330
331 if (RtlIsValidIndexHandle(&AtomTable->RtlHandleTable,
332 Index,
333 &RtlHandle))
334 {
335 PRTL_ATOM_HANDLE AtomHandle = (PRTL_ATOM_HANDLE)RtlHandle;
336
337 return AtomHandle->AtomEntry;
338 }
339
340 return NULL;
341 }
342
343
344 /*
345 * Ldr Resource support code
346 */
347
348 IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir,
349 LPCWSTR name, void *root,
350 int want_dir );
351 IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( IMAGE_RESOURCE_DIRECTORY *dir,
352 WORD id, void *root, int want_dir );
353 IMAGE_RESOURCE_DIRECTORY *find_first_entry( IMAGE_RESOURCE_DIRECTORY *dir,
354 void *root, int want_dir );
355 int push_language( USHORT *list, ULONG pos, WORD lang );
356
357 /**********************************************************************
358 * find_entry
359 *
360 * Find a resource entry
361 */
362 NTSTATUS find_entry( PVOID BaseAddress, LDR_RESOURCE_INFO *info,
363 ULONG level, void **ret, int want_dir )
364 {
365 ULONG size;
366 void *root;
367 IMAGE_RESOURCE_DIRECTORY *resdirptr;
368 USHORT list[9]; /* list of languages to try */
369 int i, pos = 0;
370 LCID user_lcid, system_lcid;
371
372 root = RtlImageDirectoryEntryToData( BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size );
373 if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND;
374 resdirptr = root;
375
376 if (!level--) goto done;
377 if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Type, root, want_dir || level )))
378 return STATUS_RESOURCE_TYPE_NOT_FOUND;
379 if (!level--) return STATUS_SUCCESS;
380
381 resdirptr = *ret;
382 if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Name, root, want_dir || level )))
383 return STATUS_RESOURCE_NAME_NOT_FOUND;
384 if (!level--) return STATUS_SUCCESS;
385 if (level) return STATUS_INVALID_PARAMETER; /* level > 3 */
386
387 /* 1. specified language */
388 pos = push_language( list, pos, info->Language );
389
390 /* 2. specified language with neutral sublanguage */
391 pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(info->Language), SUBLANG_NEUTRAL ) );
392
393 /* 3. neutral language with neutral sublanguage */
394 pos = push_language( list, pos, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
395
396 /* if no explicitly specified language, try some defaults */
397 if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL)
398 {
399 /* user defaults, unless SYS_DEFAULT sublanguage specified */
400 if (SUBLANGID(info->Language) != SUBLANG_SYS_DEFAULT)
401 {
402 /* 4. current thread locale language */
403 pos = push_language( list, pos, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale) );
404
405 if (NT_SUCCESS(NtQueryDefaultLocale(TRUE, &user_lcid)))
406 {
407 /* 5. user locale language */
408 pos = push_language( list, pos, LANGIDFROMLCID(user_lcid) );
409
410 /* 6. user locale language with neutral sublanguage */
411 pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(user_lcid), SUBLANG_NEUTRAL ) );
412 }
413 }
414
415 /* now system defaults */
416
417 if (NT_SUCCESS(NtQueryDefaultLocale(FALSE, &system_lcid)))
418 {
419 /* 7. system locale language */
420 pos = push_language( list, pos, LANGIDFROMLCID( system_lcid ) );
421
422 /* 8. system locale language with neutral sublanguage */
423 pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(system_lcid), SUBLANG_NEUTRAL ) );
424 }
425
426 /* 9. English */
427 pos = push_language( list, pos, MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT ) );
428 }
429
430 resdirptr = *ret;
431 for (i = 0; i < pos; i++)
432 if ((*ret = find_entry_by_id( resdirptr, list[i], root, want_dir ))) return STATUS_SUCCESS;
433
434 /* if no explicitly specified language, return the first entry */
435 if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL)
436 {
437 if ((*ret = find_first_entry( resdirptr, root, want_dir ))) return STATUS_SUCCESS;
438 }
439 return STATUS_RESOURCE_LANG_NOT_FOUND;
440
441 done:
442 *ret = resdirptr;
443 return STATUS_SUCCESS;
444 }