dd841153b4d35df7fe4bcf789ca33a8ffe59928d
[reactos.git] / reactos / lib / 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 /* RTL Atom Tables ************************************************************/
177
178 typedef struct _RTL_ATOM_HANDLE
179 {
180 RTL_HANDLE_TABLE_ENTRY Handle;
181 PRTL_ATOM_TABLE_ENTRY AtomEntry;
182 } RTL_ATOM_HANDLE, *PRTL_ATOM_HANDLE;
183
184 NTSTATUS
185 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable)
186 {
187 RtlInitializeCriticalSection(&AtomTable->CriticalSection);
188 return STATUS_SUCCESS;
189 }
190
191
192 VOID
193 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable)
194 {
195 RtlDeleteCriticalSection(&AtomTable->CriticalSection);
196 }
197
198
199 BOOLEAN
200 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable)
201 {
202 RtlEnterCriticalSection(&AtomTable->CriticalSection);
203 return TRUE;
204 }
205
206
207 VOID
208 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable)
209 {
210 RtlLeaveCriticalSection(&AtomTable->CriticalSection);
211 }
212
213
214 /* handle functions */
215
216 BOOLEAN
217 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
218 {
219 RtlInitializeHandleTable(0xCFFF,
220 sizeof(RTL_ATOM_HANDLE),
221 &AtomTable->RtlHandleTable);
222
223 return TRUE;
224 }
225
226 VOID
227 RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
228 {
229 RtlDestroyHandleTable(&AtomTable->RtlHandleTable);
230 }
231
232 PRTL_ATOM_TABLE
233 RtlpAllocAtomTable(ULONG Size)
234 {
235 return (PRTL_ATOM_TABLE)RtlAllocateHeap(RtlGetProcessHeap(),
236 HEAP_ZERO_MEMORY,
237 Size);
238 }
239
240 VOID
241 RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable)
242 {
243 RtlFreeHeap(RtlGetProcessHeap(),
244 0,
245 AtomTable);
246 }
247
248 PRTL_ATOM_TABLE_ENTRY
249 RtlpAllocAtomTableEntry(ULONG Size)
250 {
251 return (PRTL_ATOM_TABLE_ENTRY)RtlAllocateHeap(RtlGetProcessHeap(),
252 HEAP_ZERO_MEMORY,
253 Size);
254 }
255
256 VOID
257 RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry)
258 {
259 RtlFreeHeap(RtlGetProcessHeap(),
260 0,
261 Entry);
262 }
263
264 VOID
265 RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
266 {
267 PRTL_HANDLE_TABLE_ENTRY RtlHandleEntry;
268
269 if (RtlIsValidIndexHandle(&AtomTable->RtlHandleTable,
270 (ULONG)Entry->HandleIndex,
271 &RtlHandleEntry))
272 {
273 RtlFreeHandle(&AtomTable->RtlHandleTable,
274 RtlHandleEntry);
275 }
276 }
277
278 BOOLEAN
279 RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
280 {
281 ULONG HandleIndex;
282 PRTL_HANDLE_TABLE_ENTRY RtlHandle;
283
284 RtlHandle = RtlAllocateHandle(&AtomTable->RtlHandleTable,
285 &HandleIndex);
286 if (RtlHandle != NULL)
287 {
288 PRTL_ATOM_HANDLE AtomHandle = (PRTL_ATOM_HANDLE)RtlHandle;
289
290 /* FIXME - Handle Indexes >= 0xC000 ?! */
291 if (HandleIndex < 0xC000)
292 {
293 Entry->HandleIndex = (USHORT)HandleIndex;
294 Entry->Atom = 0xC000 + (USHORT)HandleIndex;
295
296 AtomHandle->AtomEntry = Entry;
297 AtomHandle->Handle.Flags = RTL_HANDLE_VALID;
298
299 return TRUE;
300 }
301 else
302 {
303 /* set the valid flag, otherwise RtlFreeHandle will fail! */
304 AtomHandle->Handle.Flags = RTL_HANDLE_VALID;
305
306 RtlFreeHandle(&AtomTable->RtlHandleTable,
307 RtlHandle);
308 }
309 }
310
311 return FALSE;
312 }
313
314 PRTL_ATOM_TABLE_ENTRY
315 RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable, ULONG Index)
316 {
317 PRTL_HANDLE_TABLE_ENTRY RtlHandle;
318
319 if (RtlIsValidIndexHandle(&AtomTable->RtlHandleTable,
320 Index,
321 &RtlHandle))
322 {
323 PRTL_ATOM_HANDLE AtomHandle = (PRTL_ATOM_HANDLE)RtlHandle;
324
325 return AtomHandle->AtomEntry;
326 }
327
328 return NULL;
329 }
330
331
332 /*
333 * Ldr Resource support code
334 */
335
336 IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir,
337 LPCWSTR name, void *root,
338 int want_dir );
339 IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( IMAGE_RESOURCE_DIRECTORY *dir,
340 WORD id, void *root, int want_dir );
341 IMAGE_RESOURCE_DIRECTORY *find_first_entry( IMAGE_RESOURCE_DIRECTORY *dir,
342 void *root, int want_dir );
343 int push_language( USHORT *list, ULONG pos, WORD lang );
344
345 /**********************************************************************
346 * find_entry
347 *
348 * Find a resource entry
349 */
350 NTSTATUS find_entry( PVOID BaseAddress, LDR_RESOURCE_INFO *info,
351 ULONG level, void **ret, int want_dir )
352 {
353 ULONG size;
354 void *root;
355 IMAGE_RESOURCE_DIRECTORY *resdirptr;
356 USHORT list[9]; /* list of languages to try */
357 int i, pos = 0;
358 LCID user_lcid, system_lcid;
359
360 root = RtlImageDirectoryEntryToData( BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size );
361 if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND;
362 resdirptr = root;
363
364 if (!level--) goto done;
365 if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Type, root, want_dir || level )))
366 return STATUS_RESOURCE_TYPE_NOT_FOUND;
367 if (!level--) return STATUS_SUCCESS;
368
369 resdirptr = *ret;
370 if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Name, root, want_dir || level )))
371 return STATUS_RESOURCE_NAME_NOT_FOUND;
372 if (!level--) return STATUS_SUCCESS;
373 if (level) return STATUS_INVALID_PARAMETER; /* level > 3 */
374
375 /* 1. specified language */
376 pos = push_language( list, pos, info->Language );
377
378 /* 2. specified language with neutral sublanguage */
379 pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(info->Language), SUBLANG_NEUTRAL ) );
380
381 /* 3. neutral language with neutral sublanguage */
382 pos = push_language( list, pos, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
383
384 /* if no explicitly specified language, try some defaults */
385 if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL)
386 {
387 /* user defaults, unless SYS_DEFAULT sublanguage specified */
388 if (SUBLANGID(info->Language) != SUBLANG_SYS_DEFAULT)
389 {
390 /* 4. current thread locale language */
391 pos = push_language( list, pos, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale) );
392
393 if (NT_SUCCESS(NtQueryDefaultLocale(TRUE, &user_lcid)))
394 {
395 /* 5. user locale language */
396 pos = push_language( list, pos, LANGIDFROMLCID(user_lcid) );
397
398 /* 6. user locale language with neutral sublanguage */
399 pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(user_lcid), SUBLANG_NEUTRAL ) );
400 }
401 }
402
403 /* now system defaults */
404
405 if (NT_SUCCESS(NtQueryDefaultLocale(FALSE, &system_lcid)))
406 {
407 /* 7. system locale language */
408 pos = push_language( list, pos, LANGIDFROMLCID( system_lcid ) );
409
410 /* 8. system locale language with neutral sublanguage */
411 pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(system_lcid), SUBLANG_NEUTRAL ) );
412 }
413
414 /* 9. English */
415 pos = push_language( list, pos, MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT ) );
416 }
417
418 resdirptr = *ret;
419 for (i = 0; i < pos; i++)
420 if ((*ret = find_entry_by_id( resdirptr, list[i], root, want_dir ))) return STATUS_SUCCESS;
421
422 /* if no explicitly specified language, return the first entry */
423 if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL)
424 {
425 if ((*ret = find_first_entry( resdirptr, root, want_dir ))) return STATUS_SUCCESS;
426 }
427 return STATUS_RESOURCE_LANG_NOT_FOUND;
428
429 done:
430 *ret = resdirptr;
431 return STATUS_SUCCESS;
432 }