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