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