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