2005-09-08 00:09:32 +00:00
|
|
|
/*
|
2004-05-31 19:33:59 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
Major refactoring of the exception handling code + misc fixes:
- Fix/add prototypes for RtlCaptureContext, RtlDispatchException and RtlUnwind
- Fix EXCEPTION_REGISTRATION_RECORD structure and PEXCEPTION_ROUTINE
- Add w32api excpt.h (based on mingw) with PSDK compatibility fixes
- Fix seriously broken User-Mode Ldr thunk and APC Callback prototypes
- Fix KiUserExceptionDispatcher
- Remove useless NTDLL entrypoint
- Implement NTDLL Ki* callbacks in ASM
- Implement RtlCaptureContext
- Fix RtlRaiseException to handle cases when a user-mode debugger is present
- Fix RtlRaiseStatus as above, plus set the exception address and capture context
- Little cleanup of RTL headers
- Implement RtlpGetStackLimits, RtlpGetExceptionList, RtlpSetExceptionList, RtlpGetExceptionAddress in ASM
- Fix RtlDispatchException, add cases for exceptions in the DPC stack and validate the validity of the
exception frames. Add support for exception logging by the global flag. Use TRAP_FRAME/EXCPETION_FRAME instead of
Context.
- Fix RtlUnwind logic, support cases where it's called with custom arguments instead of NULL.
- Reimplement RtlpCaptureContext to work properly, convert exception handler calling functions to INTEL syntax
and fix some bugs (like checking for the right unwind flag, clearing volatile register values, etc. Also use some
optimizations to increase speed.
- Modify some kernel functions (like KeContextToTrapFrame, KiDispatchException, KiInitializeUserApc, etc.) to
support a PKEXCEPTION_FRAME for future PPC compatibility.
- Reimplement RtlCaptureUnicodeString/FreeUnicodeString as inlined probe macros and optimize them.
- Export ExRaiseStatus/Exception as Rtl*
- Reimplement NtContinue to have more platform-independent code, and to protect and validate user-mode context
and parameters with SEH.
- Implement KiRaiseException, add SEH to all user-mode parameters and when copying data to the user-mode stack.
- Fix KiInitializeUserApc to use KeTrapFrameToContext, to save the debug registers, not to deliver APCs during
v86 mode, and to protect user-mode stack operations in SEH and probing. Also make it generate the proper stack for the
user-mode callback.
- Implement KiUnexpectedInterrupt and KiCoprocessorError
- Reimplement NtRaiseException in ASM to take advantage of optimizations due to the trap frame being in the
stack when called through System call interface.
- Fix Ntcontinue to respect AlertThread paramter
- Fix some functiosn to return with KiServiceExit2 instead of KiServiceExit when required/needed
- Fix KiDispatchException's logic, fix hacks when calling KeUserExceptionDispatcher, use correct context
flags,...
- Make NTDLL Ki* callbacks have SEH to protect them and return to kernel-mode with notification of any
exceptions (the kernel-mode code to handle this isn't written yet though)
svn path=/trunk/; revision=17811
2005-09-11 22:32:20 +00:00
|
|
|
* PROJECT: ReactOS NT User-Mode DLL
|
2004-05-31 19:33:59 +00:00
|
|
|
* FILE: lib/ntdll/rtl/libsup.c
|
Major refactoring of the exception handling code + misc fixes:
- Fix/add prototypes for RtlCaptureContext, RtlDispatchException and RtlUnwind
- Fix EXCEPTION_REGISTRATION_RECORD structure and PEXCEPTION_ROUTINE
- Add w32api excpt.h (based on mingw) with PSDK compatibility fixes
- Fix seriously broken User-Mode Ldr thunk and APC Callback prototypes
- Fix KiUserExceptionDispatcher
- Remove useless NTDLL entrypoint
- Implement NTDLL Ki* callbacks in ASM
- Implement RtlCaptureContext
- Fix RtlRaiseException to handle cases when a user-mode debugger is present
- Fix RtlRaiseStatus as above, plus set the exception address and capture context
- Little cleanup of RTL headers
- Implement RtlpGetStackLimits, RtlpGetExceptionList, RtlpSetExceptionList, RtlpGetExceptionAddress in ASM
- Fix RtlDispatchException, add cases for exceptions in the DPC stack and validate the validity of the
exception frames. Add support for exception logging by the global flag. Use TRAP_FRAME/EXCPETION_FRAME instead of
Context.
- Fix RtlUnwind logic, support cases where it's called with custom arguments instead of NULL.
- Reimplement RtlpCaptureContext to work properly, convert exception handler calling functions to INTEL syntax
and fix some bugs (like checking for the right unwind flag, clearing volatile register values, etc. Also use some
optimizations to increase speed.
- Modify some kernel functions (like KeContextToTrapFrame, KiDispatchException, KiInitializeUserApc, etc.) to
support a PKEXCEPTION_FRAME for future PPC compatibility.
- Reimplement RtlCaptureUnicodeString/FreeUnicodeString as inlined probe macros and optimize them.
- Export ExRaiseStatus/Exception as Rtl*
- Reimplement NtContinue to have more platform-independent code, and to protect and validate user-mode context
and parameters with SEH.
- Implement KiRaiseException, add SEH to all user-mode parameters and when copying data to the user-mode stack.
- Fix KiInitializeUserApc to use KeTrapFrameToContext, to save the debug registers, not to deliver APCs during
v86 mode, and to protect user-mode stack operations in SEH and probing. Also make it generate the proper stack for the
user-mode callback.
- Implement KiUnexpectedInterrupt and KiCoprocessorError
- Reimplement NtRaiseException in ASM to take advantage of optimizations due to the trap frame being in the
stack when called through System call interface.
- Fix Ntcontinue to respect AlertThread paramter
- Fix some functiosn to return with KiServiceExit2 instead of KiServiceExit when required/needed
- Fix KiDispatchException's logic, fix hacks when calling KeUserExceptionDispatcher, use correct context
flags,...
- Make NTDLL Ki* callbacks have SEH to protect them and return to kernel-mode with notification of any
exceptions (the kernel-mode code to handle this isn't written yet though)
svn path=/trunk/; revision=17811
2005-09-11 22:32:20 +00:00
|
|
|
* PURPOSE: RTL Support Routines
|
|
|
|
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
|
|
|
* Gunnar Dalsnes
|
2004-05-31 19:33:59 +00:00
|
|
|
*/
|
|
|
|
|
2005-09-08 00:09:32 +00:00
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
2005-06-17 17:22:27 +00:00
|
|
|
#include <ntdll.h>
|
2014-01-20 12:59:27 +00:00
|
|
|
|
2005-06-19 22:50:59 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
2004-05-31 19:33:59 +00:00
|
|
|
|
2007-12-11 21:52:12 +00:00
|
|
|
SIZE_T RtlpAllocDeallocQueryBufferSize = PAGE_SIZE;
|
2009-09-11 07:12:30 +00:00
|
|
|
PTEB LdrpTopLevelDllBeingLoadedTeb = NULL;
|
2015-04-10 19:21:22 +00:00
|
|
|
PVOID MmHighestUserAddress = (PVOID)MI_HIGHEST_USER_ADDRESS;
|
2007-12-11 21:52:12 +00:00
|
|
|
|
2004-05-31 19:33:59 +00:00
|
|
|
/* FUNCTIONS ***************************************************************/
|
|
|
|
|
Major refactoring of the exception handling code + misc fixes:
- Fix/add prototypes for RtlCaptureContext, RtlDispatchException and RtlUnwind
- Fix EXCEPTION_REGISTRATION_RECORD structure and PEXCEPTION_ROUTINE
- Add w32api excpt.h (based on mingw) with PSDK compatibility fixes
- Fix seriously broken User-Mode Ldr thunk and APC Callback prototypes
- Fix KiUserExceptionDispatcher
- Remove useless NTDLL entrypoint
- Implement NTDLL Ki* callbacks in ASM
- Implement RtlCaptureContext
- Fix RtlRaiseException to handle cases when a user-mode debugger is present
- Fix RtlRaiseStatus as above, plus set the exception address and capture context
- Little cleanup of RTL headers
- Implement RtlpGetStackLimits, RtlpGetExceptionList, RtlpSetExceptionList, RtlpGetExceptionAddress in ASM
- Fix RtlDispatchException, add cases for exceptions in the DPC stack and validate the validity of the
exception frames. Add support for exception logging by the global flag. Use TRAP_FRAME/EXCPETION_FRAME instead of
Context.
- Fix RtlUnwind logic, support cases where it's called with custom arguments instead of NULL.
- Reimplement RtlpCaptureContext to work properly, convert exception handler calling functions to INTEL syntax
and fix some bugs (like checking for the right unwind flag, clearing volatile register values, etc. Also use some
optimizations to increase speed.
- Modify some kernel functions (like KeContextToTrapFrame, KiDispatchException, KiInitializeUserApc, etc.) to
support a PKEXCEPTION_FRAME for future PPC compatibility.
- Reimplement RtlCaptureUnicodeString/FreeUnicodeString as inlined probe macros and optimize them.
- Export ExRaiseStatus/Exception as Rtl*
- Reimplement NtContinue to have more platform-independent code, and to protect and validate user-mode context
and parameters with SEH.
- Implement KiRaiseException, add SEH to all user-mode parameters and when copying data to the user-mode stack.
- Fix KiInitializeUserApc to use KeTrapFrameToContext, to save the debug registers, not to deliver APCs during
v86 mode, and to protect user-mode stack operations in SEH and probing. Also make it generate the proper stack for the
user-mode callback.
- Implement KiUnexpectedInterrupt and KiCoprocessorError
- Reimplement NtRaiseException in ASM to take advantage of optimizations due to the trap frame being in the
stack when called through System call interface.
- Fix Ntcontinue to respect AlertThread paramter
- Fix some functiosn to return with KiServiceExit2 instead of KiServiceExit when required/needed
- Fix KiDispatchException's logic, fix hacks when calling KeUserExceptionDispatcher, use correct context
flags,...
- Make NTDLL Ki* callbacks have SEH to protect them and return to kernel-mode with notification of any
exceptions (the kernel-mode code to handle this isn't written yet though)
svn path=/trunk/; revision=17811
2005-09-11 22:32:20 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
2009-10-23 22:51:39 +00:00
|
|
|
RtlpCheckForActiveDebugger(VOID)
|
Major refactoring of the exception handling code + misc fixes:
- Fix/add prototypes for RtlCaptureContext, RtlDispatchException and RtlUnwind
- Fix EXCEPTION_REGISTRATION_RECORD structure and PEXCEPTION_ROUTINE
- Add w32api excpt.h (based on mingw) with PSDK compatibility fixes
- Fix seriously broken User-Mode Ldr thunk and APC Callback prototypes
- Fix KiUserExceptionDispatcher
- Remove useless NTDLL entrypoint
- Implement NTDLL Ki* callbacks in ASM
- Implement RtlCaptureContext
- Fix RtlRaiseException to handle cases when a user-mode debugger is present
- Fix RtlRaiseStatus as above, plus set the exception address and capture context
- Little cleanup of RTL headers
- Implement RtlpGetStackLimits, RtlpGetExceptionList, RtlpSetExceptionList, RtlpGetExceptionAddress in ASM
- Fix RtlDispatchException, add cases for exceptions in the DPC stack and validate the validity of the
exception frames. Add support for exception logging by the global flag. Use TRAP_FRAME/EXCPETION_FRAME instead of
Context.
- Fix RtlUnwind logic, support cases where it's called with custom arguments instead of NULL.
- Reimplement RtlpCaptureContext to work properly, convert exception handler calling functions to INTEL syntax
and fix some bugs (like checking for the right unwind flag, clearing volatile register values, etc. Also use some
optimizations to increase speed.
- Modify some kernel functions (like KeContextToTrapFrame, KiDispatchException, KiInitializeUserApc, etc.) to
support a PKEXCEPTION_FRAME for future PPC compatibility.
- Reimplement RtlCaptureUnicodeString/FreeUnicodeString as inlined probe macros and optimize them.
- Export ExRaiseStatus/Exception as Rtl*
- Reimplement NtContinue to have more platform-independent code, and to protect and validate user-mode context
and parameters with SEH.
- Implement KiRaiseException, add SEH to all user-mode parameters and when copying data to the user-mode stack.
- Fix KiInitializeUserApc to use KeTrapFrameToContext, to save the debug registers, not to deliver APCs during
v86 mode, and to protect user-mode stack operations in SEH and probing. Also make it generate the proper stack for the
user-mode callback.
- Implement KiUnexpectedInterrupt and KiCoprocessorError
- Reimplement NtRaiseException in ASM to take advantage of optimizations due to the trap frame being in the
stack when called through System call interface.
- Fix Ntcontinue to respect AlertThread paramter
- Fix some functiosn to return with KiServiceExit2 instead of KiServiceExit when required/needed
- Fix KiDispatchException's logic, fix hacks when calling KeUserExceptionDispatcher, use correct context
flags,...
- Make NTDLL Ki* callbacks have SEH to protect them and return to kernel-mode with notification of any
exceptions (the kernel-mode code to handle this isn't written yet though)
svn path=/trunk/; revision=17811
2005-09-11 22:32:20 +00:00
|
|
|
{
|
2009-10-23 22:51:39 +00:00
|
|
|
/* Return the flag in the PEB */
|
|
|
|
return NtCurrentPeb()->BeingDebugged;
|
Major refactoring of the exception handling code + misc fixes:
- Fix/add prototypes for RtlCaptureContext, RtlDispatchException and RtlUnwind
- Fix EXCEPTION_REGISTRATION_RECORD structure and PEXCEPTION_ROUTINE
- Add w32api excpt.h (based on mingw) with PSDK compatibility fixes
- Fix seriously broken User-Mode Ldr thunk and APC Callback prototypes
- Fix KiUserExceptionDispatcher
- Remove useless NTDLL entrypoint
- Implement NTDLL Ki* callbacks in ASM
- Implement RtlCaptureContext
- Fix RtlRaiseException to handle cases when a user-mode debugger is present
- Fix RtlRaiseStatus as above, plus set the exception address and capture context
- Little cleanup of RTL headers
- Implement RtlpGetStackLimits, RtlpGetExceptionList, RtlpSetExceptionList, RtlpGetExceptionAddress in ASM
- Fix RtlDispatchException, add cases for exceptions in the DPC stack and validate the validity of the
exception frames. Add support for exception logging by the global flag. Use TRAP_FRAME/EXCPETION_FRAME instead of
Context.
- Fix RtlUnwind logic, support cases where it's called with custom arguments instead of NULL.
- Reimplement RtlpCaptureContext to work properly, convert exception handler calling functions to INTEL syntax
and fix some bugs (like checking for the right unwind flag, clearing volatile register values, etc. Also use some
optimizations to increase speed.
- Modify some kernel functions (like KeContextToTrapFrame, KiDispatchException, KiInitializeUserApc, etc.) to
support a PKEXCEPTION_FRAME for future PPC compatibility.
- Reimplement RtlCaptureUnicodeString/FreeUnicodeString as inlined probe macros and optimize them.
- Export ExRaiseStatus/Exception as Rtl*
- Reimplement NtContinue to have more platform-independent code, and to protect and validate user-mode context
and parameters with SEH.
- Implement KiRaiseException, add SEH to all user-mode parameters and when copying data to the user-mode stack.
- Fix KiInitializeUserApc to use KeTrapFrameToContext, to save the debug registers, not to deliver APCs during
v86 mode, and to protect user-mode stack operations in SEH and probing. Also make it generate the proper stack for the
user-mode callback.
- Implement KiUnexpectedInterrupt and KiCoprocessorError
- Reimplement NtRaiseException in ASM to take advantage of optimizations due to the trap frame being in the
stack when called through System call interface.
- Fix Ntcontinue to respect AlertThread paramter
- Fix some functiosn to return with KiServiceExit2 instead of KiServiceExit when required/needed
- Fix KiDispatchException's logic, fix hacks when calling KeUserExceptionDispatcher, use correct context
flags,...
- Make NTDLL Ki* callbacks have SEH to protect them and return to kernel-mode with notification of any
exceptions (the kernel-mode code to handle this isn't written yet though)
svn path=/trunk/; revision=17811
2005-09-11 22:32:20 +00:00
|
|
|
}
|
|
|
|
|
- More sharing between ntdll/ntoskrnl: shared Dbg code.
- Added NtCreateDebugObject, NtDebugContinue, NtQueryDebugFilterState, NtSetDebugFilterState, NtWaitForDebugEvent to system call list.
- Added some debug constants to headers
- Updated RtlpCheckForActiveDebugger in ntoskrnl to return whatever we're expecting as the "normal" case.
- Added RtlpSetInDbgPrint to rtl support library for special DbgPrint implementation difference in user-mode
- Removed all the deprecated debug APIs in ntdll.
- Implemented NtQueryDebugFilterState and NtSetDebugFilterState based on royce's implementation.
- Started modifications on KeDebugService, and implemented DebugService in rtl
- Implemented all the Dbg* APIs in RTL.
- Implemented DbgUiConnectToDbg, DbgUiContinue, DbgUiWaitStateChange, DbgUiRemoteBreakin, DbgUiIssueRemoteBreakin
- Changed KD Print callbacks to also receive the length of the string.
Right now, one call that should be shared still isn't (the final DebugPrint call) because calling KeDebugService from kernel-mode seems to cause a hang. Also, DebugService does not currently cause an exception like it should (instead it still calls the Kdp handler), because those changes would've made the patch even bigger and are still untested.
svn path=/trunk/; revision=18078
2005-09-26 04:59:48 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
2009-11-02 17:45:51 +00:00
|
|
|
RtlpSetInDbgPrint(VOID)
|
- More sharing between ntdll/ntoskrnl: shared Dbg code.
- Added NtCreateDebugObject, NtDebugContinue, NtQueryDebugFilterState, NtSetDebugFilterState, NtWaitForDebugEvent to system call list.
- Added some debug constants to headers
- Updated RtlpCheckForActiveDebugger in ntoskrnl to return whatever we're expecting as the "normal" case.
- Added RtlpSetInDbgPrint to rtl support library for special DbgPrint implementation difference in user-mode
- Removed all the deprecated debug APIs in ntdll.
- Implemented NtQueryDebugFilterState and NtSetDebugFilterState based on royce's implementation.
- Started modifications on KeDebugService, and implemented DebugService in rtl
- Implemented all the Dbg* APIs in RTL.
- Implemented DbgUiConnectToDbg, DbgUiContinue, DbgUiWaitStateChange, DbgUiRemoteBreakin, DbgUiIssueRemoteBreakin
- Changed KD Print callbacks to also receive the length of the string.
Right now, one call that should be shared still isn't (the final DebugPrint call) because calling KeDebugService from kernel-mode seems to cause a hang. Also, DebugService does not currently cause an exception like it should (instead it still calls the Kdp handler), because those changes would've made the patch even bigger and are still untested.
svn path=/trunk/; revision=18078
2005-09-26 04:59:48 +00:00
|
|
|
{
|
2009-11-02 17:45:51 +00:00
|
|
|
/* Check if it's already set and return TRUE if so */
|
- More sharing between ntdll/ntoskrnl: shared Dbg code.
- Added NtCreateDebugObject, NtDebugContinue, NtQueryDebugFilterState, NtSetDebugFilterState, NtWaitForDebugEvent to system call list.
- Added some debug constants to headers
- Updated RtlpCheckForActiveDebugger in ntoskrnl to return whatever we're expecting as the "normal" case.
- Added RtlpSetInDbgPrint to rtl support library for special DbgPrint implementation difference in user-mode
- Removed all the deprecated debug APIs in ntdll.
- Implemented NtQueryDebugFilterState and NtSetDebugFilterState based on royce's implementation.
- Started modifications on KeDebugService, and implemented DebugService in rtl
- Implemented all the Dbg* APIs in RTL.
- Implemented DbgUiConnectToDbg, DbgUiContinue, DbgUiWaitStateChange, DbgUiRemoteBreakin, DbgUiIssueRemoteBreakin
- Changed KD Print callbacks to also receive the length of the string.
Right now, one call that should be shared still isn't (the final DebugPrint call) because calling KeDebugService from kernel-mode seems to cause a hang. Also, DebugService does not currently cause an exception like it should (instead it still calls the Kdp handler), because those changes would've made the patch even bigger and are still untested.
svn path=/trunk/; revision=18078
2005-09-26 04:59:48 +00:00
|
|
|
if (NtCurrentTeb()->InDbgPrint) return TRUE;
|
|
|
|
|
|
|
|
/* Set it and return */
|
|
|
|
NtCurrentTeb()->InDbgPrint = TRUE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2009-11-02 17:45:51 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
RtlpClearInDbgPrint(VOID)
|
|
|
|
{
|
|
|
|
/* Clear the flag */
|
|
|
|
NtCurrentTeb()->InDbgPrint = FALSE;
|
|
|
|
}
|
|
|
|
|
2005-04-01 00:04:15 +00:00
|
|
|
KPROCESSOR_MODE
|
2005-10-19 23:08:12 +00:00
|
|
|
NTAPI
|
2015-09-03 23:57:39 +00:00
|
|
|
RtlpGetMode(VOID)
|
2005-05-09 01:43:25 +00:00
|
|
|
{
|
|
|
|
return UserMode;
|
2005-04-01 00:04:15 +00:00
|
|
|
}
|
|
|
|
|
2008-09-12 15:09:17 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-09-08 00:09:32 +00:00
|
|
|
PPEB
|
2005-10-19 23:08:12 +00:00
|
|
|
NTAPI
|
2008-09-12 15:09:17 +00:00
|
|
|
RtlGetCurrentPeb(VOID)
|
2005-09-08 00:09:32 +00:00
|
|
|
{
|
|
|
|
return NtCurrentPeb();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-10-19 23:08:12 +00:00
|
|
|
VOID NTAPI
|
2005-09-08 00:09:32 +00:00
|
|
|
RtlAcquirePebLock(VOID)
|
|
|
|
{
|
|
|
|
PPEB Peb = NtCurrentPeb ();
|
2010-03-25 12:22:59 +00:00
|
|
|
RtlEnterCriticalSection(Peb->FastPebLock);
|
2005-09-08 00:09:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-10-19 23:08:12 +00:00
|
|
|
VOID NTAPI
|
2005-09-08 00:09:32 +00:00
|
|
|
RtlReleasePebLock(VOID)
|
|
|
|
{
|
|
|
|
PPEB Peb = NtCurrentPeb ();
|
2010-03-25 12:22:59 +00:00
|
|
|
RtlLeaveCriticalSection(Peb->FastPebLock);
|
2005-09-08 00:09:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
ULONG
|
2005-10-19 23:08:12 +00:00
|
|
|
NTAPI
|
2005-09-08 00:09:32 +00:00
|
|
|
RtlGetNtGlobalFlags(VOID)
|
|
|
|
{
|
Major refactoring of the exception handling code + misc fixes:
- Fix/add prototypes for RtlCaptureContext, RtlDispatchException and RtlUnwind
- Fix EXCEPTION_REGISTRATION_RECORD structure and PEXCEPTION_ROUTINE
- Add w32api excpt.h (based on mingw) with PSDK compatibility fixes
- Fix seriously broken User-Mode Ldr thunk and APC Callback prototypes
- Fix KiUserExceptionDispatcher
- Remove useless NTDLL entrypoint
- Implement NTDLL Ki* callbacks in ASM
- Implement RtlCaptureContext
- Fix RtlRaiseException to handle cases when a user-mode debugger is present
- Fix RtlRaiseStatus as above, plus set the exception address and capture context
- Little cleanup of RTL headers
- Implement RtlpGetStackLimits, RtlpGetExceptionList, RtlpSetExceptionList, RtlpGetExceptionAddress in ASM
- Fix RtlDispatchException, add cases for exceptions in the DPC stack and validate the validity of the
exception frames. Add support for exception logging by the global flag. Use TRAP_FRAME/EXCPETION_FRAME instead of
Context.
- Fix RtlUnwind logic, support cases where it's called with custom arguments instead of NULL.
- Reimplement RtlpCaptureContext to work properly, convert exception handler calling functions to INTEL syntax
and fix some bugs (like checking for the right unwind flag, clearing volatile register values, etc. Also use some
optimizations to increase speed.
- Modify some kernel functions (like KeContextToTrapFrame, KiDispatchException, KiInitializeUserApc, etc.) to
support a PKEXCEPTION_FRAME for future PPC compatibility.
- Reimplement RtlCaptureUnicodeString/FreeUnicodeString as inlined probe macros and optimize them.
- Export ExRaiseStatus/Exception as Rtl*
- Reimplement NtContinue to have more platform-independent code, and to protect and validate user-mode context
and parameters with SEH.
- Implement KiRaiseException, add SEH to all user-mode parameters and when copying data to the user-mode stack.
- Fix KiInitializeUserApc to use KeTrapFrameToContext, to save the debug registers, not to deliver APCs during
v86 mode, and to protect user-mode stack operations in SEH and probing. Also make it generate the proper stack for the
user-mode callback.
- Implement KiUnexpectedInterrupt and KiCoprocessorError
- Reimplement NtRaiseException in ASM to take advantage of optimizations due to the trap frame being in the
stack when called through System call interface.
- Fix Ntcontinue to respect AlertThread paramter
- Fix some functiosn to return with KiServiceExit2 instead of KiServiceExit when required/needed
- Fix KiDispatchException's logic, fix hacks when calling KeUserExceptionDispatcher, use correct context
flags,...
- Make NTDLL Ki* callbacks have SEH to protect them and return to kernel-mode with notification of any
exceptions (the kernel-mode code to handle this isn't written yet though)
svn path=/trunk/; revision=17811
2005-09-11 22:32:20 +00:00
|
|
|
PPEB pPeb = NtCurrentPeb();
|
|
|
|
return pPeb->NtGlobalFlag;
|
2005-09-08 02:29:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
2005-10-19 23:08:12 +00:00
|
|
|
NTAPI
|
2011-09-19 16:52:37 +00:00
|
|
|
RtlDeleteHeapLock(IN OUT PHEAP_LOCK Lock)
|
2005-09-08 02:29:30 +00:00
|
|
|
{
|
2010-10-05 12:42:55 +00:00
|
|
|
return RtlDeleteCriticalSection(&Lock->CriticalSection);
|
2005-09-08 02:29:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
2005-10-19 23:08:12 +00:00
|
|
|
NTAPI
|
2011-09-19 16:52:37 +00:00
|
|
|
RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
|
2005-09-08 02:29:30 +00:00
|
|
|
{
|
2011-09-19 16:52:37 +00:00
|
|
|
UNREFERENCED_PARAMETER(Exclusive);
|
|
|
|
|
2010-10-05 12:42:55 +00:00
|
|
|
return RtlEnterCriticalSection(&Lock->CriticalSection);
|
2005-09-08 02:29:30 +00:00
|
|
|
}
|
|
|
|
|
2014-10-24 19:05:54 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
RtlTryEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
|
|
|
|
{
|
|
|
|
UNREFERENCED_PARAMETER(Exclusive);
|
|
|
|
|
|
|
|
return RtlTryEnterCriticalSection(&Lock->CriticalSection);
|
|
|
|
}
|
|
|
|
|
2005-09-08 02:29:30 +00:00
|
|
|
NTSTATUS
|
2005-10-19 23:08:12 +00:00
|
|
|
NTAPI
|
2011-09-19 16:52:37 +00:00
|
|
|
RtlInitializeHeapLock(IN OUT PHEAP_LOCK *Lock)
|
2005-09-08 02:29:30 +00:00
|
|
|
{
|
2011-09-19 16:52:37 +00:00
|
|
|
return RtlInitializeCriticalSection(&(*Lock)->CriticalSection);
|
2005-09-08 02:29:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
2005-10-19 23:08:12 +00:00
|
|
|
NTAPI
|
2011-09-19 16:52:37 +00:00
|
|
|
RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock)
|
2005-09-08 02:29:30 +00:00
|
|
|
{
|
2010-10-05 12:42:55 +00:00
|
|
|
return RtlLeaveCriticalSection(&Lock->CriticalSection);
|
2005-09-08 00:09:32 +00:00
|
|
|
}
|
2005-04-01 00:04:15 +00:00
|
|
|
|
2005-05-09 01:43:25 +00:00
|
|
|
PVOID
|
2005-10-19 23:08:12 +00:00
|
|
|
NTAPI
|
2005-07-20 23:35:59 +00:00
|
|
|
RtlpAllocateMemory(UINT Bytes,
|
|
|
|
ULONG Tag)
|
2004-05-31 19:33:59 +00:00
|
|
|
{
|
2005-07-20 23:35:59 +00:00
|
|
|
UNREFERENCED_PARAMETER(Tag);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-07-20 23:35:59 +00:00
|
|
|
return RtlAllocateHeap(RtlGetProcessHeap(),
|
|
|
|
0,
|
|
|
|
Bytes);
|
2004-05-31 19:33:59 +00:00
|
|
|
}
|
|
|
|
|
2005-02-22 17:58:19 +00:00
|
|
|
|
2005-05-05 19:36:25 +00:00
|
|
|
VOID
|
2005-10-19 23:08:12 +00:00
|
|
|
NTAPI
|
2005-07-20 23:35:59 +00:00
|
|
|
RtlpFreeMemory(PVOID Mem,
|
|
|
|
ULONG Tag)
|
2005-05-05 19:36:25 +00:00
|
|
|
{
|
2005-07-20 23:35:59 +00:00
|
|
|
UNREFERENCED_PARAMETER(Tag);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-07-20 23:35:59 +00:00
|
|
|
RtlFreeHeap(RtlGetProcessHeap(),
|
|
|
|
0,
|
|
|
|
Mem);
|
2005-05-05 19:36:25 +00:00
|
|
|
}
|
|
|
|
|
2005-02-22 17:58:19 +00:00
|
|
|
|
2009-06-17 12:44:05 +00:00
|
|
|
#if DBG
|
2005-02-22 17:58:19 +00:00
|
|
|
VOID FASTCALL
|
|
|
|
CHECK_PAGED_CODE_RTL(char *file, int line)
|
|
|
|
{
|
|
|
|
/* meaningless in user mode */
|
|
|
|
}
|
|
|
|
#endif
|
2005-06-24 18:11:16 +00:00
|
|
|
|
2013-08-28 18:57:29 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
RtlpSetHeapParameters(IN PRTL_HEAP_PARAMETERS Parameters)
|
|
|
|
{
|
|
|
|
PPEB Peb;
|
|
|
|
|
|
|
|
/* Get PEB */
|
|
|
|
Peb = RtlGetCurrentPeb();
|
|
|
|
|
|
|
|
/* Apply defaults for non-set parameters */
|
|
|
|
if (!Parameters->SegmentCommit) Parameters->SegmentCommit = Peb->HeapSegmentCommit;
|
|
|
|
if (!Parameters->SegmentReserve) Parameters->SegmentReserve = Peb->HeapSegmentReserve;
|
|
|
|
if (!Parameters->DeCommitFreeBlockThreshold) Parameters->DeCommitFreeBlockThreshold = Peb->HeapDeCommitFreeBlockThreshold;
|
|
|
|
if (!Parameters->DeCommitTotalFreeThreshold) Parameters->DeCommitTotalFreeThreshold = Peb->HeapDeCommitTotalFreeThreshold;
|
|
|
|
}
|
|
|
|
|
Major refactoring of the exception handling code + misc fixes:
- Fix/add prototypes for RtlCaptureContext, RtlDispatchException and RtlUnwind
- Fix EXCEPTION_REGISTRATION_RECORD structure and PEXCEPTION_ROUTINE
- Add w32api excpt.h (based on mingw) with PSDK compatibility fixes
- Fix seriously broken User-Mode Ldr thunk and APC Callback prototypes
- Fix KiUserExceptionDispatcher
- Remove useless NTDLL entrypoint
- Implement NTDLL Ki* callbacks in ASM
- Implement RtlCaptureContext
- Fix RtlRaiseException to handle cases when a user-mode debugger is present
- Fix RtlRaiseStatus as above, plus set the exception address and capture context
- Little cleanup of RTL headers
- Implement RtlpGetStackLimits, RtlpGetExceptionList, RtlpSetExceptionList, RtlpGetExceptionAddress in ASM
- Fix RtlDispatchException, add cases for exceptions in the DPC stack and validate the validity of the
exception frames. Add support for exception logging by the global flag. Use TRAP_FRAME/EXCPETION_FRAME instead of
Context.
- Fix RtlUnwind logic, support cases where it's called with custom arguments instead of NULL.
- Reimplement RtlpCaptureContext to work properly, convert exception handler calling functions to INTEL syntax
and fix some bugs (like checking for the right unwind flag, clearing volatile register values, etc. Also use some
optimizations to increase speed.
- Modify some kernel functions (like KeContextToTrapFrame, KiDispatchException, KiInitializeUserApc, etc.) to
support a PKEXCEPTION_FRAME for future PPC compatibility.
- Reimplement RtlCaptureUnicodeString/FreeUnicodeString as inlined probe macros and optimize them.
- Export ExRaiseStatus/Exception as Rtl*
- Reimplement NtContinue to have more platform-independent code, and to protect and validate user-mode context
and parameters with SEH.
- Implement KiRaiseException, add SEH to all user-mode parameters and when copying data to the user-mode stack.
- Fix KiInitializeUserApc to use KeTrapFrameToContext, to save the debug registers, not to deliver APCs during
v86 mode, and to protect user-mode stack operations in SEH and probing. Also make it generate the proper stack for the
user-mode callback.
- Implement KiUnexpectedInterrupt and KiCoprocessorError
- Reimplement NtRaiseException in ASM to take advantage of optimizations due to the trap frame being in the
stack when called through System call interface.
- Fix Ntcontinue to respect AlertThread paramter
- Fix some functiosn to return with KiServiceExit2 instead of KiServiceExit when required/needed
- Fix KiDispatchException's logic, fix hacks when calling KeUserExceptionDispatcher, use correct context
flags,...
- Make NTDLL Ki* callbacks have SEH to protect them and return to kernel-mode with notification of any
exceptions (the kernel-mode code to handle this isn't written yet though)
svn path=/trunk/; revision=17811
2005-09-11 22:32:20 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame,
|
|
|
|
IN ULONG_PTR RegistrationFrameEnd,
|
|
|
|
IN OUT PULONG_PTR StackLow,
|
|
|
|
IN OUT PULONG_PTR StackHigh)
|
|
|
|
{
|
|
|
|
/* There's no such thing as a DPC stack in user-mode */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord,
|
|
|
|
IN PCONTEXT ContextRecord,
|
|
|
|
IN PVOID ContextData,
|
|
|
|
IN ULONG Size)
|
|
|
|
{
|
|
|
|
/* Exception logging is not done in user-mode */
|
|
|
|
}
|
|
|
|
|
2006-08-30 06:52:10 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
RtlpCaptureStackLimits(IN ULONG_PTR Ebp,
|
|
|
|
IN ULONG_PTR *StackBegin,
|
|
|
|
IN ULONG_PTR *StackEnd)
|
|
|
|
{
|
|
|
|
/* FIXME: Verify */
|
2009-12-10 00:35:12 +00:00
|
|
|
*StackBegin = (ULONG_PTR)NtCurrentTeb()->NtTib.StackLimit;
|
|
|
|
*StackEnd = (ULONG_PTR)NtCurrentTeb()->NtTib.StackBase;
|
2006-08-30 06:52:10 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2017-05-06 17:51:26 +00:00
|
|
|
#ifndef _M_AMD64
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
ULONG
|
|
|
|
NTAPI
|
|
|
|
RtlWalkFrameChain(OUT PVOID *Callers,
|
|
|
|
IN ULONG Count,
|
|
|
|
IN ULONG Flags)
|
|
|
|
{
|
|
|
|
ULONG_PTR Stack, NewStack, StackBegin, StackEnd = 0;
|
|
|
|
ULONG Eip;
|
|
|
|
BOOLEAN Result, StopSearch = FALSE;
|
|
|
|
ULONG i = 0;
|
|
|
|
|
|
|
|
/* Get current EBP */
|
|
|
|
#if defined(_M_IX86)
|
|
|
|
#if defined __GNUC__
|
|
|
|
__asm__("mov %%ebp, %0" : "=r" (Stack) : );
|
|
|
|
#elif defined(_MSC_VER)
|
|
|
|
__asm mov Stack, ebp
|
|
|
|
#endif
|
|
|
|
#elif defined(_M_MIPS)
|
|
|
|
__asm__("move $sp, %0" : "=r" (Stack) : );
|
|
|
|
#elif defined(_M_PPC)
|
|
|
|
__asm__("mr %0,1" : "=r" (Stack) : );
|
|
|
|
#elif defined(_M_ARM)
|
2017-07-25 17:30:21 +00:00
|
|
|
#if defined __GNUC__
|
2017-05-06 17:51:26 +00:00
|
|
|
__asm__("mov sp, %0" : "=r"(Stack) : );
|
2017-07-25 17:30:21 +00:00
|
|
|
#elif defined(_MSC_VER)
|
|
|
|
// FIXME: Hack. Probably won't work if this ever actually manages to run someday.
|
|
|
|
Stack = (ULONG_PTR)&Stack;
|
|
|
|
#endif
|
2017-05-06 17:51:26 +00:00
|
|
|
#else
|
|
|
|
#error Unknown architecture
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Set it as the stack begin limit as well */
|
|
|
|
StackBegin = (ULONG_PTR)Stack;
|
|
|
|
|
|
|
|
/* Check if we're called for non-logging mode */
|
|
|
|
if (!Flags)
|
|
|
|
{
|
|
|
|
/* Get the actual safe limits */
|
|
|
|
Result = RtlpCaptureStackLimits((ULONG_PTR)Stack,
|
|
|
|
&StackBegin,
|
|
|
|
&StackEnd);
|
|
|
|
if (!Result) return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Use a SEH block for maximum protection */
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
/* Loop the frames */
|
|
|
|
for (i = 0; i < Count; i++)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Leave if we're past the stack,
|
|
|
|
* if we're before the stack,
|
|
|
|
* or if we've reached ourselves.
|
|
|
|
*/
|
|
|
|
if ((Stack >= StackEnd) ||
|
|
|
|
(!i ? (Stack < StackBegin) : (Stack <= StackBegin)) ||
|
|
|
|
((StackEnd - Stack) < (2 * sizeof(ULONG_PTR))))
|
|
|
|
{
|
|
|
|
/* We're done or hit a bad address */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get new stack and EIP */
|
|
|
|
NewStack = *(PULONG_PTR)Stack;
|
|
|
|
Eip = *(PULONG_PTR)(Stack + sizeof(ULONG_PTR));
|
|
|
|
|
|
|
|
/* Check if the new pointer is above the oldone and past the end */
|
|
|
|
if (!((Stack < NewStack) && (NewStack < StackEnd)))
|
|
|
|
{
|
|
|
|
/* Stop searching after this entry */
|
|
|
|
StopSearch = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Also make sure that the EIP isn't a stack address */
|
|
|
|
if ((StackBegin < Eip) && (Eip < StackEnd)) break;
|
|
|
|
|
|
|
|
/* FIXME: Check that EIP is inside a loaded module */
|
|
|
|
|
|
|
|
/* Save this frame */
|
|
|
|
Callers[i] = (PVOID)Eip;
|
|
|
|
|
|
|
|
/* Check if we should continue */
|
|
|
|
if (StopSearch)
|
|
|
|
{
|
|
|
|
/* Return the next index */
|
|
|
|
i++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Move to the next stack */
|
|
|
|
Stack = NewStack;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
/* No index */
|
|
|
|
i = 0;
|
|
|
|
}
|
|
|
|
_SEH2_END;
|
|
|
|
|
|
|
|
/* Return frames parsed */
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2008-11-18 00:31:22 +00:00
|
|
|
#ifdef _AMD64_
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
RtlpGetStackLimits(
|
|
|
|
OUT PULONG_PTR LowLimit,
|
|
|
|
OUT PULONG_PTR HighLimit)
|
|
|
|
{
|
2009-12-10 00:35:12 +00:00
|
|
|
*LowLimit = (ULONG_PTR)NtCurrentTeb()->NtTib.StackLimit;
|
|
|
|
*HighLimit = (ULONG_PTR)NtCurrentTeb()->NtTib.StackBase;
|
2008-11-18 00:31:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-09-11 07:12:30 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
RtlIsThreadWithinLoaderCallout(VOID)
|
|
|
|
{
|
|
|
|
return LdrpTopLevelDllBeingLoadedTeb == NtCurrentTeb();
|
|
|
|
}
|
|
|
|
|
2005-06-24 18:11:16 +00:00
|
|
|
/* RTL Atom Tables ************************************************************/
|
|
|
|
|
|
|
|
typedef struct _RTL_ATOM_HANDLE
|
|
|
|
{
|
|
|
|
RTL_HANDLE_TABLE_ENTRY Handle;
|
|
|
|
PRTL_ATOM_TABLE_ENTRY AtomEntry;
|
|
|
|
} RTL_ATOM_HANDLE, *PRTL_ATOM_HANDLE;
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable)
|
|
|
|
{
|
|
|
|
RtlInitializeCriticalSection(&AtomTable->CriticalSection);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
|
|
RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable)
|
|
|
|
{
|
|
|
|
RtlDeleteCriticalSection(&AtomTable->CriticalSection);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable)
|
|
|
|
{
|
|
|
|
RtlEnterCriticalSection(&AtomTable->CriticalSection);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
|
|
RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable)
|
|
|
|
{
|
|
|
|
RtlLeaveCriticalSection(&AtomTable->CriticalSection);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* handle functions */
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
|
|
|
|
{
|
|
|
|
RtlInitializeHandleTable(0xCFFF,
|
2015-09-03 23:57:39 +00:00
|
|
|
sizeof(RTL_ATOM_HANDLE),
|
|
|
|
&AtomTable->RtlHandleTable);
|
2005-06-24 18:11:16 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
|
|
|
|
{
|
|
|
|
RtlDestroyHandleTable(&AtomTable->RtlHandleTable);
|
|
|
|
}
|
|
|
|
|
|
|
|
PRTL_ATOM_TABLE
|
|
|
|
RtlpAllocAtomTable(ULONG Size)
|
|
|
|
{
|
|
|
|
return (PRTL_ATOM_TABLE)RtlAllocateHeap(RtlGetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
Size);
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable)
|
|
|
|
{
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(),
|
|
|
|
0,
|
|
|
|
AtomTable);
|
|
|
|
}
|
|
|
|
|
|
|
|
PRTL_ATOM_TABLE_ENTRY
|
|
|
|
RtlpAllocAtomTableEntry(ULONG Size)
|
|
|
|
{
|
|
|
|
return (PRTL_ATOM_TABLE_ENTRY)RtlAllocateHeap(RtlGetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
Size);
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry)
|
|
|
|
{
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(),
|
|
|
|
0,
|
|
|
|
Entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
|
|
|
|
{
|
|
|
|
PRTL_HANDLE_TABLE_ENTRY RtlHandleEntry;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-06-24 18:11:16 +00:00
|
|
|
if (RtlIsValidIndexHandle(&AtomTable->RtlHandleTable,
|
2005-08-07 11:47:45 +00:00
|
|
|
(ULONG)Entry->HandleIndex,
|
|
|
|
&RtlHandleEntry))
|
2005-06-24 18:11:16 +00:00
|
|
|
{
|
|
|
|
RtlFreeHandle(&AtomTable->RtlHandleTable,
|
|
|
|
RtlHandleEntry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
|
|
|
|
{
|
|
|
|
ULONG HandleIndex;
|
|
|
|
PRTL_HANDLE_TABLE_ENTRY RtlHandle;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-06-24 18:11:16 +00:00
|
|
|
RtlHandle = RtlAllocateHandle(&AtomTable->RtlHandleTable,
|
|
|
|
&HandleIndex);
|
|
|
|
if (RtlHandle != NULL)
|
|
|
|
{
|
|
|
|
PRTL_ATOM_HANDLE AtomHandle = (PRTL_ATOM_HANDLE)RtlHandle;
|
|
|
|
|
|
|
|
/* FIXME - Handle Indexes >= 0xC000 ?! */
|
|
|
|
if (HandleIndex < 0xC000)
|
|
|
|
{
|
|
|
|
Entry->HandleIndex = (USHORT)HandleIndex;
|
|
|
|
Entry->Atom = 0xC000 + (USHORT)HandleIndex;
|
|
|
|
|
|
|
|
AtomHandle->AtomEntry = Entry;
|
|
|
|
AtomHandle->Handle.Flags = RTL_HANDLE_VALID;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* set the valid flag, otherwise RtlFreeHandle will fail! */
|
|
|
|
AtomHandle->Handle.Flags = RTL_HANDLE_VALID;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-06-24 18:11:16 +00:00
|
|
|
RtlFreeHandle(&AtomTable->RtlHandleTable,
|
|
|
|
RtlHandle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRTL_ATOM_TABLE_ENTRY
|
|
|
|
RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable, ULONG Index)
|
|
|
|
{
|
|
|
|
PRTL_HANDLE_TABLE_ENTRY RtlHandle;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-06-24 18:11:16 +00:00
|
|
|
if (RtlIsValidIndexHandle(&AtomTable->RtlHandleTable,
|
2005-08-07 11:47:45 +00:00
|
|
|
Index,
|
|
|
|
&RtlHandle))
|
2005-06-24 18:11:16 +00:00
|
|
|
{
|
|
|
|
PRTL_ATOM_HANDLE AtomHandle = (PRTL_ATOM_HANDLE)RtlHandle;
|
|
|
|
|
|
|
|
return AtomHandle->AtomEntry;
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-06-24 18:11:16 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2005-12-08 23:55:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Ldr Resource support code
|
|
|
|
*/
|
|
|
|
|
|
|
|
IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir,
|
|
|
|
LPCWSTR name, void *root,
|
|
|
|
int want_dir );
|
|
|
|
IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( IMAGE_RESOURCE_DIRECTORY *dir,
|
|
|
|
WORD id, void *root, int want_dir );
|
|
|
|
IMAGE_RESOURCE_DIRECTORY *find_first_entry( IMAGE_RESOURCE_DIRECTORY *dir,
|
|
|
|
void *root, int want_dir );
|
|
|
|
int push_language( USHORT *list, ULONG pos, WORD lang );
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* find_entry
|
|
|
|
*
|
|
|
|
* Find a resource entry
|
|
|
|
*/
|
|
|
|
NTSTATUS find_entry( PVOID BaseAddress, LDR_RESOURCE_INFO *info,
|
|
|
|
ULONG level, void **ret, int want_dir )
|
|
|
|
{
|
|
|
|
ULONG size;
|
|
|
|
void *root;
|
|
|
|
IMAGE_RESOURCE_DIRECTORY *resdirptr;
|
|
|
|
USHORT list[9]; /* list of languages to try */
|
|
|
|
int i, pos = 0;
|
|
|
|
LCID user_lcid, system_lcid;
|
|
|
|
|
|
|
|
root = RtlImageDirectoryEntryToData( BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size );
|
|
|
|
if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND;
|
2014-06-22 18:44:21 +00:00
|
|
|
if (size < sizeof(*resdirptr)) return STATUS_RESOURCE_DATA_NOT_FOUND;
|
2005-12-08 23:55:34 +00:00
|
|
|
resdirptr = root;
|
|
|
|
|
|
|
|
if (!level--) goto done;
|
|
|
|
if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Type, root, want_dir || level )))
|
|
|
|
return STATUS_RESOURCE_TYPE_NOT_FOUND;
|
|
|
|
if (!level--) return STATUS_SUCCESS;
|
|
|
|
|
|
|
|
resdirptr = *ret;
|
|
|
|
if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Name, root, want_dir || level )))
|
|
|
|
return STATUS_RESOURCE_NAME_NOT_FOUND;
|
|
|
|
if (!level--) return STATUS_SUCCESS;
|
|
|
|
if (level) return STATUS_INVALID_PARAMETER; /* level > 3 */
|
|
|
|
|
|
|
|
/* 1. specified language */
|
|
|
|
pos = push_language( list, pos, info->Language );
|
|
|
|
|
|
|
|
/* 2. specified language with neutral sublanguage */
|
|
|
|
pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(info->Language), SUBLANG_NEUTRAL ) );
|
|
|
|
|
|
|
|
/* 3. neutral language with neutral sublanguage */
|
|
|
|
pos = push_language( list, pos, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
|
|
|
|
|
|
|
|
/* if no explicitly specified language, try some defaults */
|
|
|
|
if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL)
|
|
|
|
{
|
|
|
|
/* user defaults, unless SYS_DEFAULT sublanguage specified */
|
|
|
|
if (SUBLANGID(info->Language) != SUBLANG_SYS_DEFAULT)
|
|
|
|
{
|
|
|
|
/* 4. current thread locale language */
|
|
|
|
pos = push_language( list, pos, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale) );
|
|
|
|
|
|
|
|
if (NT_SUCCESS(NtQueryDefaultLocale(TRUE, &user_lcid)))
|
|
|
|
{
|
|
|
|
/* 5. user locale language */
|
|
|
|
pos = push_language( list, pos, LANGIDFROMLCID(user_lcid) );
|
|
|
|
|
|
|
|
/* 6. user locale language with neutral sublanguage */
|
|
|
|
pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(user_lcid), SUBLANG_NEUTRAL ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* now system defaults */
|
|
|
|
|
|
|
|
if (NT_SUCCESS(NtQueryDefaultLocale(FALSE, &system_lcid)))
|
|
|
|
{
|
|
|
|
/* 7. system locale language */
|
|
|
|
pos = push_language( list, pos, LANGIDFROMLCID( system_lcid ) );
|
|
|
|
|
|
|
|
/* 8. system locale language with neutral sublanguage */
|
|
|
|
pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(system_lcid), SUBLANG_NEUTRAL ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 9. English */
|
|
|
|
pos = push_language( list, pos, MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
resdirptr = *ret;
|
|
|
|
for (i = 0; i < pos; i++)
|
|
|
|
if ((*ret = find_entry_by_id( resdirptr, list[i], root, want_dir ))) return STATUS_SUCCESS;
|
|
|
|
|
|
|
|
/* if no explicitly specified language, return the first entry */
|
|
|
|
if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL)
|
|
|
|
{
|
|
|
|
if ((*ret = find_first_entry( resdirptr, root, want_dir ))) return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
return STATUS_RESOURCE_LANG_NOT_FOUND;
|
|
|
|
|
|
|
|
done:
|
|
|
|
*ret = resdirptr;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2010-12-22 13:07:04 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
PVOID NTAPI
|
|
|
|
RtlPcToFileHeader(IN PVOID PcValue,
|
|
|
|
PVOID* BaseOfImage)
|
|
|
|
{
|
|
|
|
PLIST_ENTRY ModuleListHead;
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
PLDR_DATA_TABLE_ENTRY Module;
|
|
|
|
PVOID ImageBase = NULL;
|
|
|
|
|
|
|
|
RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
|
|
|
|
ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
|
|
|
|
Entry = ModuleListHead->Flink;
|
|
|
|
while (Entry != ModuleListHead)
|
|
|
|
{
|
|
|
|
Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
|
|
|
|
|
|
|
|
if ((ULONG_PTR)PcValue >= (ULONG_PTR)Module->DllBase &&
|
|
|
|
(ULONG_PTR)PcValue < (ULONG_PTR)Module->DllBase + Module->SizeOfImage)
|
|
|
|
{
|
|
|
|
ImageBase = Module->DllBase;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Entry = Entry->Flink;
|
|
|
|
}
|
|
|
|
RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
|
|
|
|
|
|
|
|
*BaseOfImage = ImageBase;
|
|
|
|
return ImageBase;
|
|
|
|
}
|
2011-03-30 20:56:05 +00:00
|
|
|
|
2017-10-03 18:57:44 +00:00
|
|
|
NTSTATUS get_buffer(LPWSTR *buffer, SIZE_T needed, PUNICODE_STRING CallerBuffer, BOOLEAN bAllocateBuffer)
|
|
|
|
{
|
|
|
|
WCHAR *p;
|
|
|
|
|
|
|
|
if (CallerBuffer && CallerBuffer->MaximumLength > needed)
|
|
|
|
{
|
|
|
|
p = CallerBuffer->Buffer;
|
|
|
|
CallerBuffer->Length = needed - sizeof(WCHAR);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!bAllocateBuffer)
|
|
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
|
|
|
if (CallerBuffer)
|
|
|
|
CallerBuffer->Buffer[0] = 0;
|
|
|
|
|
|
|
|
p = RtlAllocateHeap(RtlGetProcessHeap(), 0, needed );
|
|
|
|
if (!p)
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
}
|
|
|
|
*buffer = p;
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* NOTE: Remove this one once our actctx support becomes better */
|
|
|
|
NTSTATUS find_actctx_dll( PUNICODE_STRING pnameW, LPWSTR *fullname, PUNICODE_STRING CallerBuffer, BOOLEAN bAllocateBuffer)
|
|
|
|
{
|
|
|
|
static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\'};
|
|
|
|
static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
|
|
|
|
|
|
|
|
ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *info;
|
|
|
|
ACTCTX_SECTION_KEYED_DATA data;
|
|
|
|
NTSTATUS status;
|
|
|
|
SIZE_T needed, size = 1024;
|
|
|
|
WCHAR *p;
|
|
|
|
|
|
|
|
data.cbSize = sizeof(data);
|
|
|
|
status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL,
|
|
|
|
ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
|
|
|
|
pnameW, &data );
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
//DPRINT1("RtlFindActivationContextSectionString returned 0x%x for %wZ\n", status, pnameW);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (!(info = RtlAllocateHeap( RtlGetProcessHeap(), 0, size )))
|
|
|
|
{
|
|
|
|
status = STATUS_NO_MEMORY;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
status = RtlQueryInformationActivationContext( 0, data.hActCtx, &data.ulAssemblyRosterIndex,
|
|
|
|
AssemblyDetailedInformationInActivationContext,
|
|
|
|
info, size, &needed );
|
|
|
|
if (status == STATUS_SUCCESS) break;
|
|
|
|
if (status != STATUS_BUFFER_TOO_SMALL) goto done;
|
|
|
|
RtlFreeHeap( RtlGetProcessHeap(), 0, info );
|
|
|
|
size = needed;
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT("manifestpath === %S\n", info->lpAssemblyManifestPath);
|
|
|
|
DPRINT("DirectoryName === %S\n", info->lpAssemblyDirectoryName);
|
|
|
|
if (!info->lpAssemblyManifestPath /*|| !info->lpAssemblyDirectoryName*/)
|
|
|
|
{
|
|
|
|
status = STATUS_SXS_KEY_NOT_FOUND;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((p = wcsrchr( info->lpAssemblyManifestPath, '\\' )))
|
|
|
|
{
|
|
|
|
DWORD dirlen = info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
|
|
|
|
|
|
|
|
p++;
|
|
|
|
if (!info->lpAssemblyDirectoryName || _wcsnicmp( p, info->lpAssemblyDirectoryName, dirlen ) || wcsicmp( p + dirlen, dotManifestW ))
|
|
|
|
{
|
|
|
|
/* manifest name does not match directory name, so it's not a global
|
|
|
|
* windows/winsxs manifest; use the manifest directory name instead */
|
|
|
|
dirlen = p - info->lpAssemblyManifestPath;
|
|
|
|
needed = (dirlen + 1) * sizeof(WCHAR) + pnameW->Length;
|
|
|
|
|
|
|
|
status = get_buffer(fullname, needed, CallerBuffer, bAllocateBuffer);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
p = *fullname;
|
|
|
|
|
|
|
|
memcpy( p, info->lpAssemblyManifestPath, dirlen * sizeof(WCHAR) );
|
|
|
|
p += dirlen;
|
|
|
|
memcpy( p, pnameW->Buffer, pnameW->Length);
|
|
|
|
p += (pnameW->Length / sizeof(WCHAR));
|
|
|
|
*p = L'\0';
|
|
|
|
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
needed = (wcslen(SharedUserData->NtSystemRoot) * sizeof(WCHAR) +
|
|
|
|
sizeof(winsxsW) + info->ulAssemblyDirectoryNameLength + pnameW->Length + 2*sizeof(WCHAR));
|
|
|
|
|
|
|
|
status = get_buffer(fullname, needed, CallerBuffer, bAllocateBuffer);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
p = *fullname;
|
|
|
|
|
|
|
|
wcscpy( p, SharedUserData->NtSystemRoot );
|
|
|
|
p += wcslen(p);
|
|
|
|
memcpy( p, winsxsW, sizeof(winsxsW) );
|
|
|
|
p += sizeof(winsxsW) / sizeof(WCHAR);
|
|
|
|
memcpy( p, info->lpAssemblyDirectoryName, info->ulAssemblyDirectoryNameLength );
|
|
|
|
p += info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
|
|
|
|
*p++ = L'\\';
|
|
|
|
memcpy( p, pnameW->Buffer, pnameW->Length);
|
|
|
|
p += (pnameW->Length / sizeof(WCHAR));
|
|
|
|
*p = L'\0';
|
|
|
|
|
|
|
|
done:
|
|
|
|
RtlFreeHeap( RtlGetProcessHeap(), 0, info );
|
|
|
|
RtlReleaseActivationContext( data.hActCtx );
|
|
|
|
DPRINT("%S\n", fullname);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2011-11-06 01:34:06 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2011-03-30 20:56:05 +00:00
|
|
|
NTSYSAPI
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2011-11-06 01:34:06 +00:00
|
|
|
RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG Flags,
|
|
|
|
IN PUNICODE_STRING OriginalName,
|
|
|
|
IN PUNICODE_STRING Extension,
|
|
|
|
IN OUT PUNICODE_STRING StaticString,
|
|
|
|
IN OUT PUNICODE_STRING DynamicString,
|
|
|
|
IN OUT PUNICODE_STRING *NewName,
|
|
|
|
IN PULONG NewFlags,
|
|
|
|
IN PSIZE_T FileNameSize,
|
|
|
|
IN PSIZE_T RequiredLength)
|
2011-03-30 20:56:05 +00:00
|
|
|
{
|
2017-10-03 18:57:44 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
LPWSTR fullname;
|
|
|
|
WCHAR buffer [MAX_PATH];
|
|
|
|
UNICODE_STRING localStr, localStr2, *pstrParam;
|
|
|
|
WCHAR *p;
|
|
|
|
BOOLEAN GotExtension;
|
|
|
|
WCHAR c;
|
2018-10-14 13:45:02 +00:00
|
|
|
C_ASSERT(sizeof(UNICODE_NULL) == sizeof(WCHAR));
|
|
|
|
|
2017-10-03 18:57:44 +00:00
|
|
|
|
|
|
|
/* Check for invalid parameters */
|
|
|
|
if (!OriginalName)
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!DynamicString && !StaticString)
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((DynamicString) && (StaticString) && !(NewName))
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!OriginalName->Buffer || OriginalName->Length == 0)
|
|
|
|
{
|
|
|
|
return STATUS_SXS_KEY_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (StaticString && (OriginalName == StaticString || OriginalName->Buffer == StaticString->Buffer))
|
|
|
|
{
|
|
|
|
return STATUS_SXS_KEY_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
2018-10-14 13:45:02 +00:00
|
|
|
if (NtCurrentPeb()->ProcessParameters &&
|
|
|
|
(NtCurrentPeb()->ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_PRIVATE_DLL_PATH))
|
|
|
|
{
|
|
|
|
UNICODE_STRING RealName, LocalName;
|
|
|
|
WCHAR RealNameBuf[MAX_PATH], LocalNameBuf[MAX_PATH];
|
|
|
|
|
|
|
|
RtlInitEmptyUnicodeString(&RealName, RealNameBuf, sizeof(RealNameBuf));
|
|
|
|
RtlInitEmptyUnicodeString(&LocalName, LocalNameBuf, sizeof(LocalNameBuf));
|
|
|
|
|
|
|
|
Status = RtlComputePrivatizedDllName_U(OriginalName, &RealName, &LocalName);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("RtlComputePrivatizedDllName_U failed for %wZ: 0x%lx\n", OriginalName, Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (RtlDoesFileExists_UStr(&LocalName))
|
|
|
|
{
|
|
|
|
Status = get_buffer(&fullname, LocalName.Length + sizeof(UNICODE_NULL), StaticString, DynamicString != NULL);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
RtlCopyMemory(fullname, LocalName.Buffer, LocalName.Length + sizeof(UNICODE_NULL));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT1("Error while retrieving buffer for %wZ: 0x%lx\n", OriginalName, Status);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (RtlDoesFileExists_UStr(&RealName))
|
|
|
|
{
|
|
|
|
Status = get_buffer(&fullname, RealName.Length + sizeof(UNICODE_NULL), StaticString, DynamicString != NULL);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
RtlCopyMemory(fullname, RealName.Buffer, RealName.Length + sizeof(UNICODE_NULL));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT1("Error while retrieving buffer for %wZ: 0x%lx\n", OriginalName, Status);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Status = STATUS_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (RealName.Buffer != RealNameBuf)
|
|
|
|
RtlFreeUnicodeString(&RealName);
|
|
|
|
if (LocalName.Buffer != LocalNameBuf)
|
|
|
|
RtlFreeUnicodeString(&LocalName);
|
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("Redirecting %wZ to %S\n", OriginalName, fullname);
|
|
|
|
if (!StaticString || StaticString->Buffer != fullname)
|
|
|
|
{
|
|
|
|
RtlInitUnicodeString(DynamicString, fullname);
|
|
|
|
*NewName = DynamicString;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*NewName = StaticString;
|
|
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-03 18:57:44 +00:00
|
|
|
pstrParam = OriginalName;
|
|
|
|
|
|
|
|
/* Get the file name with an extension */
|
|
|
|
p = OriginalName->Buffer + OriginalName->Length / sizeof(WCHAR) - 1;
|
|
|
|
GotExtension = FALSE;
|
|
|
|
while (p >= OriginalName->Buffer)
|
|
|
|
{
|
|
|
|
c = *p--;
|
|
|
|
if (c == L'.')
|
|
|
|
{
|
|
|
|
GotExtension = TRUE;
|
|
|
|
}
|
|
|
|
else if (c == L'\\')
|
|
|
|
{
|
|
|
|
localStr.Buffer = p + 2;
|
|
|
|
localStr.Length = OriginalName->Length - ((ULONG_PTR)localStr.Buffer - (ULONG_PTR)OriginalName->Buffer);
|
|
|
|
localStr.MaximumLength = OriginalName->MaximumLength - ((ULONG_PTR)localStr.Buffer - (ULONG_PTR)OriginalName->Buffer);
|
|
|
|
pstrParam = &localStr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!GotExtension)
|
|
|
|
{
|
|
|
|
if (!Extension)
|
|
|
|
{
|
|
|
|
return STATUS_SXS_KEY_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pstrParam->Length + Extension->Length > sizeof(buffer))
|
|
|
|
{
|
|
|
|
//FIXME!
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlInitEmptyUnicodeString(&localStr2, buffer, sizeof(buffer));
|
|
|
|
RtlAppendUnicodeStringToString(&localStr2, pstrParam);
|
|
|
|
RtlAppendUnicodeStringToString(&localStr2, Extension);
|
|
|
|
pstrParam = &localStr2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Use wine's function as long as we use wine's sxs implementation in ntdll */
|
|
|
|
Status = find_actctx_dll(pstrParam, &fullname, StaticString, DynamicString != NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT("Redirecting %wZ to %S\n", OriginalName, fullname);
|
|
|
|
|
|
|
|
if (!StaticString || StaticString->Buffer != fullname)
|
|
|
|
{
|
|
|
|
RtlInitUnicodeString(DynamicString, fullname);
|
|
|
|
*NewName = DynamicString;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*NewName = StaticString;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
2011-03-30 20:56:05 +00:00
|
|
|
}
|
2011-11-07 00:18:13 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
NTSYSAPI
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
RtlWow64EnableFsRedirection(IN BOOLEAN Wow64FsEnableRedirection)
|
|
|
|
{
|
|
|
|
/* This is what Windows returns on x86 */
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
NTSYSAPI
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
RtlWow64EnableFsRedirectionEx(IN PVOID Wow64FsEnableRedirection,
|
|
|
|
OUT PVOID *OldFsRedirectionLevel)
|
|
|
|
{
|
|
|
|
/* This is what Windows returns on x86 */
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2012-01-15 03:16:00 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
NTSYSAPI
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
RtlComputeImportTableHash(IN HANDLE FileHandle,
|
|
|
|
OUT PCHAR Hash,
|
2016-11-12 21:53:33 +00:00
|
|
|
IN ULONG ImportTableHashSize)
|
2012-01-15 03:16:00 +00:00
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2012-09-14 09:56:23 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
RtlpSafeCopyMemory(
|
|
|
|
_Out_writes_bytes_all_(Length) VOID UNALIGNED *Destination,
|
|
|
|
_In_reads_bytes_(Length) CONST VOID UNALIGNED *Source,
|
|
|
|
_In_ SIZE_T Length)
|
|
|
|
{
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
RtlCopyMemory(Destination, Source, Length);
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
|
|
|
}
|
|
|
|
_SEH2_END;
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2014-05-10 08:37:45 +00:00
|
|
|
/* FIXME: code duplication with kernel32/client/time.c */
|
|
|
|
ULONG
|
|
|
|
NTAPI
|
|
|
|
RtlGetTickCount(VOID)
|
|
|
|
{
|
|
|
|
ULARGE_INTEGER TickCount;
|
|
|
|
|
|
|
|
#ifdef _WIN64
|
|
|
|
TickCount.QuadPart = *((volatile ULONG64*)&SharedUserData->TickCount);
|
|
|
|
#else
|
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
TickCount.HighPart = (ULONG)SharedUserData->TickCount.High1Time;
|
|
|
|
TickCount.LowPart = SharedUserData->TickCount.LowPart;
|
|
|
|
|
|
|
|
if (TickCount.HighPart == (ULONG)SharedUserData->TickCount.High2Time)
|
|
|
|
break;
|
|
|
|
|
|
|
|
YieldProcessor();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return (ULONG)((UInt32x32To64(TickCount.LowPart,
|
|
|
|
SharedUserData->TickCountMultiplier) >> 24) +
|
|
|
|
UInt32x32To64((TickCount.HighPart << 8) & 0xFFFFFFFF,
|
|
|
|
SharedUserData->TickCountMultiplier));
|
|
|
|
}
|
|
|
|
|
2011-11-07 00:18:13 +00:00
|
|
|
/* EOF */
|