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