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)
10 /* INCLUDES *****************************************************************/
17 SIZE_T RtlpAllocDeallocQueryBufferSize
= PAGE_SIZE
;
18 PTEB LdrpTopLevelDllBeingLoadedTeb
= NULL
;
19 PVOID MmHighestUserAddress
= (PVOID
)MI_HIGHEST_USER_ADDRESS
;
21 /* FUNCTIONS ***************************************************************/
25 RtlpCheckForActiveDebugger(VOID
)
27 /* Return the flag in the PEB */
28 return NtCurrentPeb()->BeingDebugged
;
33 RtlpSetInDbgPrint(VOID
)
35 /* Check if it's already set and return TRUE if so */
36 if (NtCurrentTeb()->InDbgPrint
) return TRUE
;
38 /* Set it and return */
39 NtCurrentTeb()->InDbgPrint
= TRUE
;
45 RtlpClearInDbgPrint(VOID
)
48 NtCurrentTeb()->InDbgPrint
= FALSE
;
63 RtlGetCurrentPeb(VOID
)
65 return NtCurrentPeb();
72 RtlAcquirePebLock(VOID
)
74 PPEB Peb
= NtCurrentPeb ();
75 RtlEnterCriticalSection(Peb
->FastPebLock
);
82 RtlReleasePebLock(VOID
)
84 PPEB Peb
= NtCurrentPeb ();
85 RtlLeaveCriticalSection(Peb
->FastPebLock
);
93 RtlGetNtGlobalFlags(VOID
)
95 PPEB pPeb
= NtCurrentPeb();
96 return pPeb
->NtGlobalFlag
;
101 RtlDeleteHeapLock(IN OUT PHEAP_LOCK Lock
)
103 return RtlDeleteCriticalSection(&Lock
->CriticalSection
);
108 RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock
, IN BOOLEAN Exclusive
)
110 UNREFERENCED_PARAMETER(Exclusive
);
112 return RtlEnterCriticalSection(&Lock
->CriticalSection
);
117 RtlTryEnterHeapLock(IN OUT PHEAP_LOCK Lock
, IN BOOLEAN Exclusive
)
119 UNREFERENCED_PARAMETER(Exclusive
);
121 return RtlTryEnterCriticalSection(&Lock
->CriticalSection
);
126 RtlInitializeHeapLock(IN OUT PHEAP_LOCK
*Lock
)
128 return RtlInitializeCriticalSection(&(*Lock
)->CriticalSection
);
133 RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock
)
135 return RtlLeaveCriticalSection(&Lock
->CriticalSection
);
140 RtlpAllocateMemory(UINT Bytes
,
143 UNREFERENCED_PARAMETER(Tag
);
145 return RtlAllocateHeap(RtlGetProcessHeap(),
153 RtlpFreeMemory(PVOID Mem
,
156 UNREFERENCED_PARAMETER(Tag
);
158 RtlFreeHeap(RtlGetProcessHeap(),
166 CHECK_PAGED_CODE_RTL(char *file
, int line
)
168 /* meaningless in user mode */
174 RtlpSetHeapParameters(IN PRTL_HEAP_PARAMETERS Parameters
)
179 Peb
= RtlGetCurrentPeb();
181 /* Apply defaults for non-set parameters */
182 if (!Parameters
->SegmentCommit
) Parameters
->SegmentCommit
= Peb
->HeapSegmentCommit
;
183 if (!Parameters
->SegmentReserve
) Parameters
->SegmentReserve
= Peb
->HeapSegmentReserve
;
184 if (!Parameters
->DeCommitFreeBlockThreshold
) Parameters
->DeCommitFreeBlockThreshold
= Peb
->HeapDeCommitFreeBlockThreshold
;
185 if (!Parameters
->DeCommitTotalFreeThreshold
) Parameters
->DeCommitTotalFreeThreshold
= Peb
->HeapDeCommitTotalFreeThreshold
;
190 RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame
,
191 IN ULONG_PTR RegistrationFrameEnd
,
192 IN OUT PULONG_PTR StackLow
,
193 IN OUT PULONG_PTR StackHigh
)
195 /* There's no such thing as a DPC stack in user-mode */
201 RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord
,
202 IN PCONTEXT ContextRecord
,
203 IN PVOID ContextData
,
206 /* Exception logging is not done in user-mode */
211 RtlpCaptureStackLimits(IN ULONG_PTR Ebp
,
212 IN ULONG_PTR
*StackBegin
,
213 IN ULONG_PTR
*StackEnd
)
216 *StackBegin
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackLimit
;
217 *StackEnd
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackBase
;
227 RtlWalkFrameChain(OUT PVOID
*Callers
,
231 ULONG_PTR Stack
, NewStack
, StackBegin
, StackEnd
= 0;
233 BOOLEAN Result
, StopSearch
= FALSE
;
236 /* Get current EBP */
239 __asm__("mov %%ebp, %0" : "=r" (Stack
) : );
240 #elif defined(_MSC_VER)
243 #elif defined(_M_MIPS)
244 __asm__("move $sp, %0" : "=r" (Stack
) : );
245 #elif defined(_M_PPC)
246 __asm__("mr %0,1" : "=r" (Stack
) : );
247 #elif defined(_M_ARM)
249 __asm__("mov sp, %0" : "=r"(Stack
) : );
250 #elif defined(_MSC_VER)
251 // FIXME: Hack. Probably won't work if this ever actually manages to run someday.
252 Stack
= (ULONG_PTR
)&Stack
;
255 #error Unknown architecture
258 /* Set it as the stack begin limit as well */
259 StackBegin
= (ULONG_PTR
)Stack
;
261 /* Check if we're called for non-logging mode */
264 /* Get the actual safe limits */
265 Result
= RtlpCaptureStackLimits((ULONG_PTR
)Stack
,
268 if (!Result
) return 0;
271 /* Use a SEH block for maximum protection */
274 /* Loop the frames */
275 for (i
= 0; i
< Count
; i
++)
278 * Leave if we're past the stack,
279 * if we're before the stack,
280 * or if we've reached ourselves.
282 if ((Stack
>= StackEnd
) ||
283 (!i
? (Stack
< StackBegin
) : (Stack
<= StackBegin
)) ||
284 ((StackEnd
- Stack
) < (2 * sizeof(ULONG_PTR
))))
286 /* We're done or hit a bad address */
290 /* Get new stack and EIP */
291 NewStack
= *(PULONG_PTR
)Stack
;
292 Eip
= *(PULONG_PTR
)(Stack
+ sizeof(ULONG_PTR
));
294 /* Check if the new pointer is above the oldone and past the end */
295 if (!((Stack
< NewStack
) && (NewStack
< StackEnd
)))
297 /* Stop searching after this entry */
301 /* Also make sure that the EIP isn't a stack address */
302 if ((StackBegin
< Eip
) && (Eip
< StackEnd
)) break;
304 /* FIXME: Check that EIP is inside a loaded module */
306 /* Save this frame */
307 Callers
[i
] = (PVOID
)Eip
;
309 /* Check if we should continue */
312 /* Return the next index */
317 /* Move to the next stack */
321 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
328 /* Return frames parsed */
337 OUT PULONG_PTR LowLimit
,
338 OUT PULONG_PTR HighLimit
)
340 *LowLimit
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackLimit
;
341 *HighLimit
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackBase
;
348 RtlIsThreadWithinLoaderCallout(VOID
)
350 return LdrpTopLevelDllBeingLoadedTeb
== NtCurrentTeb();
353 /* RTL Atom Tables ************************************************************/
355 typedef struct _RTL_ATOM_HANDLE
357 RTL_HANDLE_TABLE_ENTRY Handle
;
358 PRTL_ATOM_TABLE_ENTRY AtomEntry
;
359 } RTL_ATOM_HANDLE
, *PRTL_ATOM_HANDLE
;
362 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
364 RtlInitializeCriticalSection(&AtomTable
->CriticalSection
);
365 return STATUS_SUCCESS
;
370 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
372 RtlDeleteCriticalSection(&AtomTable
->CriticalSection
);
377 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable
)
379 RtlEnterCriticalSection(&AtomTable
->CriticalSection
);
385 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable
)
387 RtlLeaveCriticalSection(&AtomTable
->CriticalSection
);
391 /* handle functions */
394 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
396 RtlInitializeHandleTable(0xCFFF,
397 sizeof(RTL_ATOM_HANDLE
),
398 &AtomTable
->RtlHandleTable
);
404 RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
406 RtlDestroyHandleTable(&AtomTable
->RtlHandleTable
);
410 RtlpAllocAtomTable(ULONG Size
)
412 return (PRTL_ATOM_TABLE
)RtlAllocateHeap(RtlGetProcessHeap(),
418 RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable
)
420 RtlFreeHeap(RtlGetProcessHeap(),
425 PRTL_ATOM_TABLE_ENTRY
426 RtlpAllocAtomTableEntry(ULONG Size
)
428 return (PRTL_ATOM_TABLE_ENTRY
)RtlAllocateHeap(RtlGetProcessHeap(),
434 RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry
)
436 RtlFreeHeap(RtlGetProcessHeap(),
442 RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
444 PRTL_HANDLE_TABLE_ENTRY RtlHandleEntry
;
446 if (RtlIsValidIndexHandle(&AtomTable
->RtlHandleTable
,
447 (ULONG
)Entry
->HandleIndex
,
450 RtlFreeHandle(&AtomTable
->RtlHandleTable
,
456 RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
459 PRTL_HANDLE_TABLE_ENTRY RtlHandle
;
461 RtlHandle
= RtlAllocateHandle(&AtomTable
->RtlHandleTable
,
463 if (RtlHandle
!= NULL
)
465 PRTL_ATOM_HANDLE AtomHandle
= (PRTL_ATOM_HANDLE
)RtlHandle
;
467 /* FIXME - Handle Indexes >= 0xC000 ?! */
468 if (HandleIndex
< 0xC000)
470 Entry
->HandleIndex
= (USHORT
)HandleIndex
;
471 Entry
->Atom
= 0xC000 + (USHORT
)HandleIndex
;
473 AtomHandle
->AtomEntry
= Entry
;
474 AtomHandle
->Handle
.Flags
= RTL_HANDLE_VALID
;
480 /* set the valid flag, otherwise RtlFreeHandle will fail! */
481 AtomHandle
->Handle
.Flags
= RTL_HANDLE_VALID
;
483 RtlFreeHandle(&AtomTable
->RtlHandleTable
,
491 PRTL_ATOM_TABLE_ENTRY
492 RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable
, ULONG Index
)
494 PRTL_HANDLE_TABLE_ENTRY RtlHandle
;
496 if (RtlIsValidIndexHandle(&AtomTable
->RtlHandleTable
,
500 PRTL_ATOM_HANDLE AtomHandle
= (PRTL_ATOM_HANDLE
)RtlHandle
;
502 return AtomHandle
->AtomEntry
;
510 * Ldr Resource support code
513 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_name( IMAGE_RESOURCE_DIRECTORY
*dir
,
514 LPCWSTR name
, void *root
,
516 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_id( IMAGE_RESOURCE_DIRECTORY
*dir
,
517 WORD id
, void *root
, int want_dir
);
518 IMAGE_RESOURCE_DIRECTORY
*find_first_entry( IMAGE_RESOURCE_DIRECTORY
*dir
,
519 void *root
, int want_dir
);
520 int push_language( USHORT
*list
, ULONG pos
, WORD lang
);
522 /**********************************************************************
525 * Find a resource entry
527 NTSTATUS
find_entry( PVOID BaseAddress
, LDR_RESOURCE_INFO
*info
,
528 ULONG level
, void **ret
, int want_dir
)
532 IMAGE_RESOURCE_DIRECTORY
*resdirptr
;
533 USHORT list
[9]; /* list of languages to try */
535 LCID user_lcid
, system_lcid
;
537 root
= RtlImageDirectoryEntryToData( BaseAddress
, TRUE
, IMAGE_DIRECTORY_ENTRY_RESOURCE
, &size
);
538 if (!root
) return STATUS_RESOURCE_DATA_NOT_FOUND
;
539 if (size
< sizeof(*resdirptr
)) return STATUS_RESOURCE_DATA_NOT_FOUND
;
542 if (!level
--) goto done
;
543 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Type
, root
, want_dir
|| level
)))
544 return STATUS_RESOURCE_TYPE_NOT_FOUND
;
545 if (!level
--) return STATUS_SUCCESS
;
548 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Name
, root
, want_dir
|| level
)))
549 return STATUS_RESOURCE_NAME_NOT_FOUND
;
550 if (!level
--) return STATUS_SUCCESS
;
551 if (level
) return STATUS_INVALID_PARAMETER
; /* level > 3 */
553 /* 1. specified language */
554 pos
= push_language( list
, pos
, info
->Language
);
556 /* 2. specified language with neutral sublanguage */
557 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(info
->Language
), SUBLANG_NEUTRAL
) );
559 /* 3. neutral language with neutral sublanguage */
560 pos
= push_language( list
, pos
, MAKELANGID( LANG_NEUTRAL
, SUBLANG_NEUTRAL
) );
562 /* if no explicitly specified language, try some defaults */
563 if (PRIMARYLANGID(info
->Language
) == LANG_NEUTRAL
)
565 /* user defaults, unless SYS_DEFAULT sublanguage specified */
566 if (SUBLANGID(info
->Language
) != SUBLANG_SYS_DEFAULT
)
568 /* 4. current thread locale language */
569 pos
= push_language( list
, pos
, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale
) );
571 if (NT_SUCCESS(NtQueryDefaultLocale(TRUE
, &user_lcid
)))
573 /* 5. user locale language */
574 pos
= push_language( list
, pos
, LANGIDFROMLCID(user_lcid
) );
576 /* 6. user locale language with neutral sublanguage */
577 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(user_lcid
), SUBLANG_NEUTRAL
) );
581 /* now system defaults */
583 if (NT_SUCCESS(NtQueryDefaultLocale(FALSE
, &system_lcid
)))
585 /* 7. system locale language */
586 pos
= push_language( list
, pos
, LANGIDFROMLCID( system_lcid
) );
588 /* 8. system locale language with neutral sublanguage */
589 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(system_lcid
), SUBLANG_NEUTRAL
) );
593 pos
= push_language( list
, pos
, MAKELANGID( LANG_ENGLISH
, SUBLANG_DEFAULT
) );
597 for (i
= 0; i
< pos
; i
++)
598 if ((*ret
= find_entry_by_id( resdirptr
, list
[i
], root
, want_dir
))) return STATUS_SUCCESS
;
600 /* if no explicitly specified language, return the first entry */
601 if (PRIMARYLANGID(info
->Language
) == LANG_NEUTRAL
)
603 if ((*ret
= find_first_entry( resdirptr
, root
, want_dir
))) return STATUS_SUCCESS
;
605 return STATUS_RESOURCE_LANG_NOT_FOUND
;
609 return STATUS_SUCCESS
;
616 RtlPcToFileHeader(IN PVOID PcValue
,
619 PLIST_ENTRY ModuleListHead
;
621 PLDR_DATA_TABLE_ENTRY Module
;
622 PVOID ImageBase
= NULL
;
624 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
625 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
626 Entry
= ModuleListHead
->Flink
;
627 while (Entry
!= ModuleListHead
)
629 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
631 if ((ULONG_PTR
)PcValue
>= (ULONG_PTR
)Module
->DllBase
&&
632 (ULONG_PTR
)PcValue
< (ULONG_PTR
)Module
->DllBase
+ Module
->SizeOfImage
)
634 ImageBase
= Module
->DllBase
;
637 Entry
= Entry
->Flink
;
639 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
641 *BaseOfImage
= ImageBase
;
645 NTSTATUS
get_buffer(LPWSTR
*buffer
, SIZE_T needed
, PUNICODE_STRING CallerBuffer
, BOOLEAN bAllocateBuffer
)
649 if (CallerBuffer
&& CallerBuffer
->MaximumLength
> needed
)
651 p
= CallerBuffer
->Buffer
;
652 CallerBuffer
->Length
= needed
- sizeof(WCHAR
);
656 if (!bAllocateBuffer
)
657 return STATUS_BUFFER_TOO_SMALL
;
660 CallerBuffer
->Buffer
[0] = 0;
662 p
= RtlAllocateHeap(RtlGetProcessHeap(), 0, needed
);
664 return STATUS_NO_MEMORY
;
668 return STATUS_SUCCESS
;
671 /* NOTE: Remove this one once our actctx support becomes better */
672 NTSTATUS
find_actctx_dll( PUNICODE_STRING pnameW
, LPWSTR
*fullname
, PUNICODE_STRING CallerBuffer
, BOOLEAN bAllocateBuffer
)
674 static const WCHAR winsxsW
[] = {'\\','w','i','n','s','x','s','\\'};
675 static const WCHAR dotManifestW
[] = {'.','m','a','n','i','f','e','s','t',0};
677 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*info
;
678 ACTCTX_SECTION_KEYED_DATA data
;
680 SIZE_T needed
, size
= 1024;
683 data
.cbSize
= sizeof(data
);
684 status
= RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
, NULL
,
685 ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
,
687 if (status
!= STATUS_SUCCESS
)
689 //DPRINT1("RtlFindActivationContextSectionString returned 0x%x for %wZ\n", status, pnameW);
695 if (!(info
= RtlAllocateHeap( RtlGetProcessHeap(), 0, size
)))
697 status
= STATUS_NO_MEMORY
;
700 status
= RtlQueryInformationActivationContext( 0, data
.hActCtx
, &data
.ulAssemblyRosterIndex
,
701 AssemblyDetailedInformationInActivationContext
,
702 info
, size
, &needed
);
703 if (status
== STATUS_SUCCESS
) break;
704 if (status
!= STATUS_BUFFER_TOO_SMALL
) goto done
;
705 RtlFreeHeap( RtlGetProcessHeap(), 0, info
);
709 DPRINT("manifestpath === %S\n", info
->lpAssemblyManifestPath
);
710 DPRINT("DirectoryName === %S\n", info
->lpAssemblyDirectoryName
);
711 if (!info
->lpAssemblyManifestPath
/*|| !info->lpAssemblyDirectoryName*/)
713 status
= STATUS_SXS_KEY_NOT_FOUND
;
717 if ((p
= wcsrchr( info
->lpAssemblyManifestPath
, '\\' )))
719 DWORD dirlen
= info
->ulAssemblyDirectoryNameLength
/ sizeof(WCHAR
);
722 if (!info
->lpAssemblyDirectoryName
|| _wcsnicmp( p
, info
->lpAssemblyDirectoryName
, dirlen
) || wcsicmp( p
+ dirlen
, dotManifestW
))
724 /* manifest name does not match directory name, so it's not a global
725 * windows/winsxs manifest; use the manifest directory name instead */
726 dirlen
= p
- info
->lpAssemblyManifestPath
;
727 needed
= (dirlen
+ 1) * sizeof(WCHAR
) + pnameW
->Length
;
729 status
= get_buffer(fullname
, needed
, CallerBuffer
, bAllocateBuffer
);
730 if (!NT_SUCCESS(status
))
735 memcpy( p
, info
->lpAssemblyManifestPath
, dirlen
* sizeof(WCHAR
) );
737 memcpy( p
, pnameW
->Buffer
, pnameW
->Length
);
738 p
+= (pnameW
->Length
/ sizeof(WCHAR
));
745 needed
= (wcslen(SharedUserData
->NtSystemRoot
) * sizeof(WCHAR
) +
746 sizeof(winsxsW
) + info
->ulAssemblyDirectoryNameLength
+ pnameW
->Length
+ 2*sizeof(WCHAR
));
748 status
= get_buffer(fullname
, needed
, CallerBuffer
, bAllocateBuffer
);
749 if (!NT_SUCCESS(status
))
754 wcscpy( p
, SharedUserData
->NtSystemRoot
);
756 memcpy( p
, winsxsW
, sizeof(winsxsW
) );
757 p
+= sizeof(winsxsW
) / sizeof(WCHAR
);
758 memcpy( p
, info
->lpAssemblyDirectoryName
, info
->ulAssemblyDirectoryNameLength
);
759 p
+= info
->ulAssemblyDirectoryNameLength
/ sizeof(WCHAR
);
761 memcpy( p
, pnameW
->Buffer
, pnameW
->Length
);
762 p
+= (pnameW
->Length
/ sizeof(WCHAR
));
766 RtlFreeHeap( RtlGetProcessHeap(), 0, info
);
767 RtlReleaseActivationContext( data
.hActCtx
);
768 DPRINT("%S\n", fullname
);
778 RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG Flags
,
779 IN PUNICODE_STRING OriginalName
,
780 IN PUNICODE_STRING Extension
,
781 IN OUT PUNICODE_STRING StaticString
,
782 IN OUT PUNICODE_STRING DynamicString
,
783 IN OUT PUNICODE_STRING
*NewName
,
785 IN PSIZE_T FileNameSize
,
786 IN PSIZE_T RequiredLength
)
790 WCHAR buffer
[MAX_PATH
];
791 UNICODE_STRING localStr
, localStr2
, *pstrParam
;
793 BOOLEAN GotExtension
;
795 C_ASSERT(sizeof(UNICODE_NULL
) == sizeof(WCHAR
));
798 /* Check for invalid parameters */
801 return STATUS_INVALID_PARAMETER
;
804 if (!DynamicString
&& !StaticString
)
806 return STATUS_INVALID_PARAMETER
;
809 if ((DynamicString
) && (StaticString
) && !(NewName
))
811 return STATUS_INVALID_PARAMETER
;
814 if (!OriginalName
->Buffer
|| OriginalName
->Length
== 0)
816 return STATUS_SXS_KEY_NOT_FOUND
;
819 if (StaticString
&& (OriginalName
== StaticString
|| OriginalName
->Buffer
== StaticString
->Buffer
))
821 return STATUS_SXS_KEY_NOT_FOUND
;
824 if (NtCurrentPeb()->ProcessParameters
&&
825 (NtCurrentPeb()->ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_PRIVATE_DLL_PATH
))
827 UNICODE_STRING RealName
, LocalName
;
828 WCHAR RealNameBuf
[MAX_PATH
], LocalNameBuf
[MAX_PATH
];
830 RtlInitEmptyUnicodeString(&RealName
, RealNameBuf
, sizeof(RealNameBuf
));
831 RtlInitEmptyUnicodeString(&LocalName
, LocalNameBuf
, sizeof(LocalNameBuf
));
833 Status
= RtlComputePrivatizedDllName_U(OriginalName
, &RealName
, &LocalName
);
834 if (!NT_SUCCESS(Status
))
836 DPRINT1("RtlComputePrivatizedDllName_U failed for %wZ: 0x%lx\n", OriginalName
, Status
);
840 if (RtlDoesFileExists_UStr(&LocalName
))
842 Status
= get_buffer(&fullname
, LocalName
.Length
+ sizeof(UNICODE_NULL
), StaticString
, DynamicString
!= NULL
);
843 if (NT_SUCCESS(Status
))
845 RtlCopyMemory(fullname
, LocalName
.Buffer
, LocalName
.Length
+ sizeof(UNICODE_NULL
));
849 DPRINT1("Error while retrieving buffer for %wZ: 0x%lx\n", OriginalName
, Status
);
852 else if (RtlDoesFileExists_UStr(&RealName
))
854 Status
= get_buffer(&fullname
, RealName
.Length
+ sizeof(UNICODE_NULL
), StaticString
, DynamicString
!= NULL
);
855 if (NT_SUCCESS(Status
))
857 RtlCopyMemory(fullname
, RealName
.Buffer
, RealName
.Length
+ sizeof(UNICODE_NULL
));
861 DPRINT1("Error while retrieving buffer for %wZ: 0x%lx\n", OriginalName
, Status
);
866 Status
= STATUS_NOT_FOUND
;
869 if (RealName
.Buffer
!= RealNameBuf
)
870 RtlFreeUnicodeString(&RealName
);
871 if (LocalName
.Buffer
!= LocalNameBuf
)
872 RtlFreeUnicodeString(&LocalName
);
874 if (NT_SUCCESS(Status
))
876 DPRINT("Redirecting %wZ to %S\n", OriginalName
, fullname
);
877 if (!StaticString
|| StaticString
->Buffer
!= fullname
)
879 RtlInitUnicodeString(DynamicString
, fullname
);
880 *NewName
= DynamicString
;
884 *NewName
= StaticString
;
890 pstrParam
= OriginalName
;
892 /* Get the file name with an extension */
893 p
= OriginalName
->Buffer
+ OriginalName
->Length
/ sizeof(WCHAR
) - 1;
894 GotExtension
= FALSE
;
895 while (p
>= OriginalName
->Buffer
)
904 localStr
.Buffer
= p
+ 2;
905 localStr
.Length
= OriginalName
->Length
- ((ULONG_PTR
)localStr
.Buffer
- (ULONG_PTR
)OriginalName
->Buffer
);
906 localStr
.MaximumLength
= OriginalName
->MaximumLength
- ((ULONG_PTR
)localStr
.Buffer
- (ULONG_PTR
)OriginalName
->Buffer
);
907 pstrParam
= &localStr
;
916 return STATUS_SXS_KEY_NOT_FOUND
;
919 if (pstrParam
->Length
+ Extension
->Length
> sizeof(buffer
))
922 return STATUS_NO_MEMORY
;
925 RtlInitEmptyUnicodeString(&localStr2
, buffer
, sizeof(buffer
));
926 RtlAppendUnicodeStringToString(&localStr2
, pstrParam
);
927 RtlAppendUnicodeStringToString(&localStr2
, Extension
);
928 pstrParam
= &localStr2
;
931 /* Use wine's function as long as we use wine's sxs implementation in ntdll */
932 Status
= find_actctx_dll(pstrParam
, &fullname
, StaticString
, DynamicString
!= NULL
);
933 if (!NT_SUCCESS(Status
))
938 DPRINT("Redirecting %wZ to %S\n", OriginalName
, fullname
);
940 if (!StaticString
|| StaticString
->Buffer
!= fullname
)
942 RtlInitUnicodeString(DynamicString
, fullname
);
943 *NewName
= DynamicString
;
947 *NewName
= StaticString
;
959 RtlWow64EnableFsRedirection(IN BOOLEAN Wow64FsEnableRedirection
)
961 /* This is what Windows returns on x86 */
962 return STATUS_NOT_IMPLEMENTED
;
971 RtlWow64EnableFsRedirectionEx(IN PVOID Wow64FsEnableRedirection
,
972 OUT PVOID
*OldFsRedirectionLevel
)
974 /* This is what Windows returns on x86 */
975 return STATUS_NOT_IMPLEMENTED
;
984 RtlComputeImportTableHash(IN HANDLE FileHandle
,
986 IN ULONG ImportTableHashSize
)
989 return STATUS_NOT_IMPLEMENTED
;
995 _Out_writes_bytes_all_(Length
) VOID UNALIGNED
*Destination
,
996 _In_reads_bytes_(Length
) CONST VOID UNALIGNED
*Source
,
1001 RtlCopyMemory(Destination
, Source
, Length
);
1003 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1005 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1009 return STATUS_SUCCESS
;
1012 /* FIXME: code duplication with kernel32/client/time.c */
1015 RtlGetTickCount(VOID
)
1017 ULARGE_INTEGER TickCount
;
1020 TickCount
.QuadPart
= *((volatile ULONG64
*)&SharedUserData
->TickCount
);
1024 TickCount
.HighPart
= (ULONG
)SharedUserData
->TickCount
.High1Time
;
1025 TickCount
.LowPart
= SharedUserData
->TickCount
.LowPart
;
1027 if (TickCount
.HighPart
== (ULONG
)SharedUserData
->TickCount
.High2Time
)
1034 return (ULONG
)((UInt32x32To64(TickCount
.LowPart
,
1035 SharedUserData
->TickCountMultiplier
) >> 24) +
1036 UInt32x32To64((TickCount
.HighPart
<< 8) & 0xFFFFFFFF,
1037 SharedUserData
->TickCountMultiplier
));