Sync with trunk for console graphics palettes.
[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 PTEB LdrpTopLevelDllBeingLoadedTeb = NULL;
18
19 /* FUNCTIONS ***************************************************************/
20
21 #ifndef _M_AMD64
22 // FIXME: Why "Not implemented"???
23 /*
24 * @implemented
25 */
26 ULONG
27 NTAPI
28 RtlWalkFrameChain(OUT PVOID *Callers,
29 IN ULONG Count,
30 IN ULONG Flags)
31 {
32 /* Not implemented for user-mode */
33 return 0;
34 }
35 #endif
36
37 BOOLEAN
38 NTAPI
39 RtlpCheckForActiveDebugger(VOID)
40 {
41 /* Return the flag in the PEB */
42 return NtCurrentPeb()->BeingDebugged;
43 }
44
45 BOOLEAN
46 NTAPI
47 RtlpSetInDbgPrint(VOID)
48 {
49 /* Check if it's already set and return TRUE if so */
50 if (NtCurrentTeb()->InDbgPrint) return TRUE;
51
52 /* Set it and return */
53 NtCurrentTeb()->InDbgPrint = TRUE;
54 return FALSE;
55 }
56
57 VOID
58 NTAPI
59 RtlpClearInDbgPrint(VOID)
60 {
61 /* Clear the flag */
62 NtCurrentTeb()->InDbgPrint = FALSE;
63 }
64
65 KPROCESSOR_MODE
66 NTAPI
67 RtlpGetMode()
68 {
69 return UserMode;
70 }
71
72 /*
73 * @implemented
74 */
75 PPEB
76 NTAPI
77 RtlGetCurrentPeb(VOID)
78 {
79 return NtCurrentPeb();
80 }
81
82 /*
83 * @implemented
84 */
85 VOID NTAPI
86 RtlAcquirePebLock(VOID)
87 {
88 PPEB Peb = NtCurrentPeb ();
89 RtlEnterCriticalSection(Peb->FastPebLock);
90 }
91
92 /*
93 * @implemented
94 */
95 VOID NTAPI
96 RtlReleasePebLock(VOID)
97 {
98 PPEB Peb = NtCurrentPeb ();
99 RtlLeaveCriticalSection(Peb->FastPebLock);
100 }
101
102 /*
103 * @implemented
104 */
105 ULONG
106 NTAPI
107 RtlGetNtGlobalFlags(VOID)
108 {
109 PPEB pPeb = NtCurrentPeb();
110 return pPeb->NtGlobalFlag;
111 }
112
113 NTSTATUS
114 NTAPI
115 RtlDeleteHeapLock(IN OUT PHEAP_LOCK Lock)
116 {
117 return RtlDeleteCriticalSection(&Lock->CriticalSection);
118 }
119
120 NTSTATUS
121 NTAPI
122 RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
123 {
124 UNREFERENCED_PARAMETER(Exclusive);
125
126 return RtlEnterCriticalSection(&Lock->CriticalSection);
127 }
128
129 NTSTATUS
130 NTAPI
131 RtlInitializeHeapLock(IN OUT PHEAP_LOCK *Lock)
132 {
133 return RtlInitializeCriticalSection(&(*Lock)->CriticalSection);
134 }
135
136 NTSTATUS
137 NTAPI
138 RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock)
139 {
140 return RtlLeaveCriticalSection(&Lock->CriticalSection);
141 }
142
143 PVOID
144 NTAPI
145 RtlpAllocateMemory(UINT Bytes,
146 ULONG Tag)
147 {
148 UNREFERENCED_PARAMETER(Tag);
149
150 return RtlAllocateHeap(RtlGetProcessHeap(),
151 0,
152 Bytes);
153 }
154
155
156 VOID
157 NTAPI
158 RtlpFreeMemory(PVOID Mem,
159 ULONG Tag)
160 {
161 UNREFERENCED_PARAMETER(Tag);
162
163 RtlFreeHeap(RtlGetProcessHeap(),
164 0,
165 Mem);
166 }
167
168
169 #if DBG
170 VOID FASTCALL
171 CHECK_PAGED_CODE_RTL(char *file, int line)
172 {
173 /* meaningless in user mode */
174 }
175 #endif
176
177 VOID
178 NTAPI
179 RtlpSetHeapParameters(IN PRTL_HEAP_PARAMETERS Parameters)
180 {
181 PPEB Peb;
182
183 /* Get PEB */
184 Peb = RtlGetCurrentPeb();
185
186 /* Apply defaults for non-set parameters */
187 if (!Parameters->SegmentCommit) Parameters->SegmentCommit = Peb->HeapSegmentCommit;
188 if (!Parameters->SegmentReserve) Parameters->SegmentReserve = Peb->HeapSegmentReserve;
189 if (!Parameters->DeCommitFreeBlockThreshold) Parameters->DeCommitFreeBlockThreshold = Peb->HeapDeCommitFreeBlockThreshold;
190 if (!Parameters->DeCommitTotalFreeThreshold) Parameters->DeCommitTotalFreeThreshold = Peb->HeapDeCommitTotalFreeThreshold;
191 }
192
193 BOOLEAN
194 NTAPI
195 RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame,
196 IN ULONG_PTR RegistrationFrameEnd,
197 IN OUT PULONG_PTR StackLow,
198 IN OUT PULONG_PTR StackHigh)
199 {
200 /* There's no such thing as a DPC stack in user-mode */
201 return FALSE;
202 }
203
204 VOID
205 NTAPI
206 RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord,
207 IN PCONTEXT ContextRecord,
208 IN PVOID ContextData,
209 IN ULONG Size)
210 {
211 /* Exception logging is not done in user-mode */
212 }
213
214 BOOLEAN
215 NTAPI
216 RtlpCaptureStackLimits(IN ULONG_PTR Ebp,
217 IN ULONG_PTR *StackBegin,
218 IN ULONG_PTR *StackEnd)
219 {
220 /* FIXME: Verify */
221 *StackBegin = (ULONG_PTR)NtCurrentTeb()->NtTib.StackLimit;
222 *StackEnd = (ULONG_PTR)NtCurrentTeb()->NtTib.StackBase;
223 return TRUE;
224 }
225
226 #ifdef _AMD64_
227 VOID
228 NTAPI
229 RtlpGetStackLimits(
230 OUT PULONG_PTR LowLimit,
231 OUT PULONG_PTR HighLimit)
232 {
233 *LowLimit = (ULONG_PTR)NtCurrentTeb()->NtTib.StackLimit;
234 *HighLimit = (ULONG_PTR)NtCurrentTeb()->NtTib.StackBase;
235 return;
236 }
237 #endif
238
239 BOOLEAN
240 NTAPI
241 RtlIsThreadWithinLoaderCallout(VOID)
242 {
243 return LdrpTopLevelDllBeingLoadedTeb == NtCurrentTeb();
244 }
245
246 /* RTL Atom Tables ************************************************************/
247
248 typedef struct _RTL_ATOM_HANDLE
249 {
250 RTL_HANDLE_TABLE_ENTRY Handle;
251 PRTL_ATOM_TABLE_ENTRY AtomEntry;
252 } RTL_ATOM_HANDLE, *PRTL_ATOM_HANDLE;
253
254 NTSTATUS
255 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable)
256 {
257 RtlInitializeCriticalSection(&AtomTable->CriticalSection);
258 return STATUS_SUCCESS;
259 }
260
261
262 VOID
263 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable)
264 {
265 RtlDeleteCriticalSection(&AtomTable->CriticalSection);
266 }
267
268
269 BOOLEAN
270 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable)
271 {
272 RtlEnterCriticalSection(&AtomTable->CriticalSection);
273 return TRUE;
274 }
275
276
277 VOID
278 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable)
279 {
280 RtlLeaveCriticalSection(&AtomTable->CriticalSection);
281 }
282
283
284 /* handle functions */
285
286 BOOLEAN
287 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
288 {
289 RtlInitializeHandleTable(0xCFFF,
290 sizeof(RTL_ATOM_HANDLE),
291 &AtomTable->RtlHandleTable);
292
293 return TRUE;
294 }
295
296 VOID
297 RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
298 {
299 RtlDestroyHandleTable(&AtomTable->RtlHandleTable);
300 }
301
302 PRTL_ATOM_TABLE
303 RtlpAllocAtomTable(ULONG Size)
304 {
305 return (PRTL_ATOM_TABLE)RtlAllocateHeap(RtlGetProcessHeap(),
306 HEAP_ZERO_MEMORY,
307 Size);
308 }
309
310 VOID
311 RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable)
312 {
313 RtlFreeHeap(RtlGetProcessHeap(),
314 0,
315 AtomTable);
316 }
317
318 PRTL_ATOM_TABLE_ENTRY
319 RtlpAllocAtomTableEntry(ULONG Size)
320 {
321 return (PRTL_ATOM_TABLE_ENTRY)RtlAllocateHeap(RtlGetProcessHeap(),
322 HEAP_ZERO_MEMORY,
323 Size);
324 }
325
326 VOID
327 RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry)
328 {
329 RtlFreeHeap(RtlGetProcessHeap(),
330 0,
331 Entry);
332 }
333
334 VOID
335 RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
336 {
337 PRTL_HANDLE_TABLE_ENTRY RtlHandleEntry;
338
339 if (RtlIsValidIndexHandle(&AtomTable->RtlHandleTable,
340 (ULONG)Entry->HandleIndex,
341 &RtlHandleEntry))
342 {
343 RtlFreeHandle(&AtomTable->RtlHandleTable,
344 RtlHandleEntry);
345 }
346 }
347
348 BOOLEAN
349 RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
350 {
351 ULONG HandleIndex;
352 PRTL_HANDLE_TABLE_ENTRY RtlHandle;
353
354 RtlHandle = RtlAllocateHandle(&AtomTable->RtlHandleTable,
355 &HandleIndex);
356 if (RtlHandle != NULL)
357 {
358 PRTL_ATOM_HANDLE AtomHandle = (PRTL_ATOM_HANDLE)RtlHandle;
359
360 /* FIXME - Handle Indexes >= 0xC000 ?! */
361 if (HandleIndex < 0xC000)
362 {
363 Entry->HandleIndex = (USHORT)HandleIndex;
364 Entry->Atom = 0xC000 + (USHORT)HandleIndex;
365
366 AtomHandle->AtomEntry = Entry;
367 AtomHandle->Handle.Flags = RTL_HANDLE_VALID;
368
369 return TRUE;
370 }
371 else
372 {
373 /* set the valid flag, otherwise RtlFreeHandle will fail! */
374 AtomHandle->Handle.Flags = RTL_HANDLE_VALID;
375
376 RtlFreeHandle(&AtomTable->RtlHandleTable,
377 RtlHandle);
378 }
379 }
380
381 return FALSE;
382 }
383
384 PRTL_ATOM_TABLE_ENTRY
385 RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable, ULONG Index)
386 {
387 PRTL_HANDLE_TABLE_ENTRY RtlHandle;
388
389 if (RtlIsValidIndexHandle(&AtomTable->RtlHandleTable,
390 Index,
391 &RtlHandle))
392 {
393 PRTL_ATOM_HANDLE AtomHandle = (PRTL_ATOM_HANDLE)RtlHandle;
394
395 return AtomHandle->AtomEntry;
396 }
397
398 return NULL;
399 }
400
401
402 /*
403 * Ldr Resource support code
404 */
405
406 IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir,
407 LPCWSTR name, void *root,
408 int want_dir );
409 IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( IMAGE_RESOURCE_DIRECTORY *dir,
410 WORD id, void *root, int want_dir );
411 IMAGE_RESOURCE_DIRECTORY *find_first_entry( IMAGE_RESOURCE_DIRECTORY *dir,
412 void *root, int want_dir );
413 int push_language( USHORT *list, ULONG pos, WORD lang );
414
415 /**********************************************************************
416 * find_entry
417 *
418 * Find a resource entry
419 */
420 NTSTATUS find_entry( PVOID BaseAddress, LDR_RESOURCE_INFO *info,
421 ULONG level, void **ret, int want_dir )
422 {
423 ULONG size;
424 void *root;
425 IMAGE_RESOURCE_DIRECTORY *resdirptr;
426 USHORT list[9]; /* list of languages to try */
427 int i, pos = 0;
428 LCID user_lcid, system_lcid;
429
430 root = RtlImageDirectoryEntryToData( BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size );
431 if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND;
432 resdirptr = root;
433
434 if (!level--) goto done;
435 if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Type, root, want_dir || level )))
436 return STATUS_RESOURCE_TYPE_NOT_FOUND;
437 if (!level--) return STATUS_SUCCESS;
438
439 resdirptr = *ret;
440 if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Name, root, want_dir || level )))
441 return STATUS_RESOURCE_NAME_NOT_FOUND;
442 if (!level--) return STATUS_SUCCESS;
443 if (level) return STATUS_INVALID_PARAMETER; /* level > 3 */
444
445 /* 1. specified language */
446 pos = push_language( list, pos, info->Language );
447
448 /* 2. specified language with neutral sublanguage */
449 pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(info->Language), SUBLANG_NEUTRAL ) );
450
451 /* 3. neutral language with neutral sublanguage */
452 pos = push_language( list, pos, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
453
454 /* if no explicitly specified language, try some defaults */
455 if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL)
456 {
457 /* user defaults, unless SYS_DEFAULT sublanguage specified */
458 if (SUBLANGID(info->Language) != SUBLANG_SYS_DEFAULT)
459 {
460 /* 4. current thread locale language */
461 pos = push_language( list, pos, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale) );
462
463 if (NT_SUCCESS(NtQueryDefaultLocale(TRUE, &user_lcid)))
464 {
465 /* 5. user locale language */
466 pos = push_language( list, pos, LANGIDFROMLCID(user_lcid) );
467
468 /* 6. user locale language with neutral sublanguage */
469 pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(user_lcid), SUBLANG_NEUTRAL ) );
470 }
471 }
472
473 /* now system defaults */
474
475 if (NT_SUCCESS(NtQueryDefaultLocale(FALSE, &system_lcid)))
476 {
477 /* 7. system locale language */
478 pos = push_language( list, pos, LANGIDFROMLCID( system_lcid ) );
479
480 /* 8. system locale language with neutral sublanguage */
481 pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(system_lcid), SUBLANG_NEUTRAL ) );
482 }
483
484 /* 9. English */
485 pos = push_language( list, pos, MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT ) );
486 }
487
488 resdirptr = *ret;
489 for (i = 0; i < pos; i++)
490 if ((*ret = find_entry_by_id( resdirptr, list[i], root, want_dir ))) return STATUS_SUCCESS;
491
492 /* if no explicitly specified language, return the first entry */
493 if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL)
494 {
495 if ((*ret = find_first_entry( resdirptr, root, want_dir ))) return STATUS_SUCCESS;
496 }
497 return STATUS_RESOURCE_LANG_NOT_FOUND;
498
499 done:
500 *ret = resdirptr;
501 return STATUS_SUCCESS;
502 }
503
504 /*
505 * @implemented
506 */
507 PVOID NTAPI
508 RtlPcToFileHeader(IN PVOID PcValue,
509 PVOID* BaseOfImage)
510 {
511 PLIST_ENTRY ModuleListHead;
512 PLIST_ENTRY Entry;
513 PLDR_DATA_TABLE_ENTRY Module;
514 PVOID ImageBase = NULL;
515
516 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
517 ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
518 Entry = ModuleListHead->Flink;
519 while (Entry != ModuleListHead)
520 {
521 Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
522
523 if ((ULONG_PTR)PcValue >= (ULONG_PTR)Module->DllBase &&
524 (ULONG_PTR)PcValue < (ULONG_PTR)Module->DllBase + Module->SizeOfImage)
525 {
526 ImageBase = Module->DllBase;
527 break;
528 }
529 Entry = Entry->Flink;
530 }
531 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
532
533 *BaseOfImage = ImageBase;
534 return ImageBase;
535 }
536
537 /*
538 * @unimplemented
539 */
540 NTSYSAPI
541 NTSTATUS
542 NTAPI
543 RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG Flags,
544 IN PUNICODE_STRING OriginalName,
545 IN PUNICODE_STRING Extension,
546 IN OUT PUNICODE_STRING StaticString,
547 IN OUT PUNICODE_STRING DynamicString,
548 IN OUT PUNICODE_STRING *NewName,
549 IN PULONG NewFlags,
550 IN PSIZE_T FileNameSize,
551 IN PSIZE_T RequiredLength)
552 {
553 return STATUS_SXS_KEY_NOT_FOUND;
554 }
555
556 /*
557 * @implemented
558 */
559 NTSYSAPI
560 NTSTATUS
561 NTAPI
562 RtlWow64EnableFsRedirection(IN BOOLEAN Wow64FsEnableRedirection)
563 {
564 /* This is what Windows returns on x86 */
565 return STATUS_NOT_IMPLEMENTED;
566 }
567
568 /*
569 * @implemented
570 */
571 NTSYSAPI
572 NTSTATUS
573 NTAPI
574 RtlWow64EnableFsRedirectionEx(IN PVOID Wow64FsEnableRedirection,
575 OUT PVOID *OldFsRedirectionLevel)
576 {
577 /* This is what Windows returns on x86 */
578 return STATUS_NOT_IMPLEMENTED;
579 }
580
581 /*
582 * @unimplemented
583 */
584 NTSYSAPI
585 NTSTATUS
586 NTAPI
587 RtlComputeImportTableHash(IN HANDLE FileHandle,
588 OUT PCHAR Hash,
589 IN ULONG ImporTTableHashSize)
590 {
591 UNIMPLEMENTED;
592 return STATUS_NOT_IMPLEMENTED;
593 }
594
595 NTSTATUS
596 NTAPI
597 RtlpSafeCopyMemory(
598 _Out_writes_bytes_all_(Length) VOID UNALIGNED *Destination,
599 _In_reads_bytes_(Length) CONST VOID UNALIGNED *Source,
600 _In_ SIZE_T Length)
601 {
602 _SEH2_TRY
603 {
604 RtlCopyMemory(Destination, Source, Length);
605 }
606 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
607 {
608 _SEH2_YIELD(return _SEH2_GetExceptionCode());
609 }
610 _SEH2_END;
611
612 return STATUS_SUCCESS;
613 }
614
615 /* EOF */