From 797dd942ecfc4d405e5e9c3cb528b9698cd79fb3 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 19 Jul 2007 17:07:48 +0200 Subject: [PATCH] ntdll: Implemented handling of the per-thread activation context stack. --- dlls/kernel32/actctx.c | 46 +++++++----------- dlls/kernel32/thread.c | 6 ++- dlls/ntdll/actctx.c | 105 +++++++++++++++++++++++++++++++++++++++++ dlls/ntdll/ntdll.spec | 10 ++-- include/winternl.h | 5 ++ 5 files changed, 137 insertions(+), 35 deletions(-) diff --git a/dlls/kernel32/actctx.c b/dlls/kernel32/actctx.c index 1847bda502e..84c29cdf7e6 100644 --- a/dlls/kernel32/actctx.c +++ b/dlls/kernel32/actctx.c @@ -35,7 +35,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(actctx); #define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa) -#define ACTCTX_FAKE_COOKIE ((ULONG_PTR) 0xf00bad) /*********************************************************************** * CreateActCtxA (KERNEL32.@) @@ -140,19 +139,14 @@ HANDLE WINAPI CreateActCtxW(PCACTCTXW pActCtx) */ BOOL WINAPI ActivateActCtx(HANDLE hActCtx, ULONG_PTR *ulCookie) { - static BOOL reported = FALSE; + NTSTATUS status; - if (reported) - TRACE("%p %p\n", hActCtx, ulCookie); - else - { - FIXME("%p %p\n", hActCtx, ulCookie); - reported = TRUE; - } - - if (ulCookie) - *ulCookie = ACTCTX_FAKE_COOKIE; - return TRUE; + if ((status = RtlActivateActivationContext( 0, hActCtx, ulCookie ))) + { + SetLastError(RtlNtStatusToDosError(status)); + return FALSE; + } + return TRUE; } /*********************************************************************** @@ -162,19 +156,8 @@ BOOL WINAPI ActivateActCtx(HANDLE hActCtx, ULONG_PTR *ulCookie) */ BOOL WINAPI DeactivateActCtx(DWORD dwFlags, ULONG_PTR ulCookie) { - static BOOL reported = FALSE; - - if (reported) - TRACE("%08x %08lx\n", dwFlags, ulCookie); - else - { - FIXME("%08x %08lx\n", dwFlags, ulCookie); - reported = TRUE; - } - - if (ulCookie != ACTCTX_FAKE_COOKIE) - return FALSE; - return TRUE; + RtlDeactivateActivationContext( dwFlags, ulCookie ); + return TRUE; } /*********************************************************************** @@ -184,9 +167,14 @@ BOOL WINAPI DeactivateActCtx(DWORD dwFlags, ULONG_PTR ulCookie) */ BOOL WINAPI GetCurrentActCtx(HANDLE* phActCtx) { - FIXME("%p\n", phActCtx); - *phActCtx = ACTCTX_FAKE_HANDLE; - return TRUE; + NTSTATUS status; + + if ((status = RtlGetActiveActivationContext(phActCtx))) + { + SetLastError(RtlNtStatusToDosError(status)); + return FALSE; + } + return TRUE; } /*********************************************************************** diff --git a/dlls/kernel32/thread.c b/dlls/kernel32/thread.c index 27fe5e27c5b..e96ca2d8541 100644 --- a/dlls/kernel32/thread.c +++ b/dlls/kernel32/thread.c @@ -168,7 +168,11 @@ void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */ LdrShutdownProcess(); exit( code ); } - else RtlExitUserThread( code ); + else + { + RtlFreeThreadActivationContextStack(); + RtlExitUserThread( code ); + } } diff --git a/dlls/ntdll/actctx.c b/dlls/ntdll/actctx.c index 3d14015579a..25950616f83 100644 --- a/dlls/ntdll/actctx.c +++ b/dlls/ntdll/actctx.c @@ -135,3 +135,108 @@ void WINAPI RtlReleaseActivationContext( HANDLE handle ) if ((actctx = check_actctx( handle ))) actctx_release( actctx ); } + + +/****************************************************************** + * RtlActivateActivationContext (NTDLL.@) + */ +NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, ULONG_PTR *cookie ) +{ + RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; + + TRACE( "%p %p\n", handle, cookie ); + + if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) ))) + return STATUS_NO_MEMORY; + + frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame; + frame->ActivationContext = handle; + frame->Flags = 0; + NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame; + RtlAddRefActivationContext( handle ); + + *cookie = (ULONG_PTR)frame; + return STATUS_SUCCESS; +} + + +/*********************************************************************** + * RtlDeactivateActivationContext (NTDLL.@) + */ +void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie ) +{ + RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top; + + TRACE( "%x %lx\n", flags, cookie ); + + /* find the right frame */ + top = NtCurrentTeb()->ActivationContextStack.ActiveFrame; + for (frame = top; frame; frame = frame->Previous) + if ((ULONG_PTR)frame == cookie) break; + + if (!frame) + RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION ); + + if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION)) + RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION ); + + /* pop everything up to and including frame */ + NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous; + + while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame) + { + frame = top->Previous; + RtlReleaseActivationContext( top->ActivationContext ); + RtlFreeHeap( GetProcessHeap(), 0, top ); + top = frame; + } +} + + +/****************************************************************** + * RtlFreeThreadActivationContextStack (NTDLL.@) + */ +void WINAPI RtlFreeThreadActivationContextStack(void) +{ + RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; + + frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; + while (frame) + { + RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous; + RtlReleaseActivationContext( frame->ActivationContext ); + RtlFreeHeap( GetProcessHeap(), 0, frame ); + frame = prev; + } + NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL; +} + + +/****************************************************************** + * RtlGetActiveActivationContext (NTDLL.@) + */ +NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle ) +{ + if (NtCurrentTeb()->ActivationContextStack.ActiveFrame) + { + *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext; + RtlAddRefActivationContext( *handle ); + } + else + *handle = 0; + + return STATUS_SUCCESS; +} + + +/****************************************************************** + * RtlIsActivationContextActive (NTDLL.@) + */ +BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle ) +{ + RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; + + for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous) + if (frame->ActivationContext == handle) return TRUE; + return FALSE; +} diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 79c74483686..62e89c7f5e3 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -389,7 +389,7 @@ @ stdcall RtlAcquirePebLock() @ stdcall RtlAcquireResourceExclusive(ptr long) @ stdcall RtlAcquireResourceShared(ptr long) -@ stub RtlActivateActivationContext +@ stdcall RtlActivateActivationContext(long ptr ptr) @ stub RtlActivateActivationContextEx @ stub RtlActivateActivationContextUnsafeFast @ stdcall RtlAddAccessAllowedAce(ptr long long ptr) @@ -498,7 +498,7 @@ @ stub RtlCustomCPToUnicodeN @ stub RtlCutoverTimeToSystemTime @ stdcall RtlDeNormalizeProcessParams(ptr) -@ stub RtlDeactivateActivationContext +@ stdcall RtlDeactivateActivationContext(long long) @ stub RtlDeactivateActivationContextUnsafeFast @ stub RtlDebugPrintTimes @ stdcall RtlDecodePointer(ptr) @@ -604,13 +604,13 @@ @ stdcall RtlFreeOemString(ptr) # @ stub RtlFreeRangeList @ stdcall RtlFreeSid (long) -# @ stub RtlFreeThreadActivationContextStack +@ stdcall RtlFreeThreadActivationContextStack() @ stdcall RtlFreeUnicodeString(ptr) @ stub RtlFreeUserThreadStack @ stdcall RtlGUIDFromString(ptr ptr) @ stub RtlGenerate8dot3Name @ stdcall RtlGetAce(ptr long ptr) -# @ stub RtlGetActiveActivationContext +@ stdcall RtlGetActiveActivationContext(ptr) @ stub RtlGetCallersAddress @ stub RtlGetCompressionWorkSpaceSize @ stdcall RtlGetControlSecurityDescriptor(ptr ptr ptr) @@ -699,7 +699,7 @@ # @ stub RtlIpv6StringToAddressExA # @ stub RtlIpv6StringToAddressExW # @ stub RtlIpv6StringToAddressW -# @ stub RtlIsActivationContextActive +@ stdcall RtlIsActivationContextActive(ptr) @ stdcall RtlIsDosDeviceName_U(wstr) @ stub RtlIsGenericTableEmpty # @ stub RtlIsGenericTableEmptyAvl diff --git a/include/winternl.h b/include/winternl.h index 59bfaf661df..bd9508f08ef 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -1979,6 +1979,7 @@ NTSTATUS WINAPI NtYieldExecution(void); void WINAPI RtlAcquirePebLock(void); BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK,BYTE); BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK,BYTE); +NTSTATUS WINAPI RtlActivateActivationContext(DWORD,HANDLE,ULONG_PTR*); NTSTATUS WINAPI RtlAddAce(PACL,DWORD,DWORD,PACE_HEADER,DWORD); NTSTATUS WINAPI RtlAddAccessAllowedAce(PACL,DWORD,DWORD,PSID); NTSTATUS WINAPI RtlAddAccessAllowedAceEx(PACL,DWORD,DWORD,DWORD,PSID); @@ -2037,6 +2038,7 @@ BOOLEAN WINAPI RtlCreateUnicodeString(PUNICODE_STRING,LPCWSTR); BOOLEAN WINAPI RtlCreateUnicodeStringFromAsciiz(PUNICODE_STRING,LPCSTR); NTSTATUS WINAPI RtlCreateUserThread(HANDLE,const SECURITY_DESCRIPTOR*,BOOLEAN,PVOID,SIZE_T,SIZE_T,PRTL_THREAD_START_ROUTINE,void*,HANDLE*,CLIENT_ID*); +void WINAPI RtlDeactivateActivationContext(DWORD,ULONG_PTR); NTSTATUS WINAPI RtlDeleteAce(PACL,DWORD); NTSTATUS WINAPI RtlDeleteAtomFromAtomTable(RTL_ATOM_TABLE,RTL_ATOM); NTSTATUS WINAPI RtlDeleteCriticalSection(RTL_CRITICAL_SECTION *); @@ -2103,9 +2105,11 @@ BOOLEAN WINAPI RtlFreeHandle(RTL_HANDLE_TABLE *,RTL_HANDLE *); BOOLEAN WINAPI RtlFreeHeap(HANDLE,ULONG,PVOID); void WINAPI RtlFreeOemString(POEM_STRING); DWORD WINAPI RtlFreeSid(PSID); +void WINAPI RtlFreeThreadActivationContextStack(void); void WINAPI RtlFreeUnicodeString(PUNICODE_STRING); NTSTATUS WINAPI RtlGetAce(PACL,DWORD,LPVOID *); +NTSTATUS WINAPI RtlGetActiveActivationContext(HANDLE*); NTSTATUS WINAPI RtlGetControlSecurityDescriptor(PSECURITY_DESCRIPTOR, PSECURITY_DESCRIPTOR_CONTROL,LPDWORD); NTSTATUS WINAPI RtlGetCurrentDirectory_U(ULONG, LPWSTR); PEB * WINAPI RtlGetCurrentPeb(void); @@ -2143,6 +2147,7 @@ BOOL WINAPI RtlInitializeSid(PSID,PSID_IDENTIFIER_AUTHORITY,BYTE); NTSTATUS WINAPI RtlInt64ToUnicodeString(ULONGLONG,ULONG,UNICODE_STRING *); NTSTATUS WINAPI RtlIntegerToChar(ULONG,ULONG,ULONG,PCHAR); NTSTATUS WINAPI RtlIntegerToUnicodeString(ULONG,ULONG,UNICODE_STRING *); +BOOLEAN WINAPI RtlIsActivationContextActive(HANDLE); ULONG WINAPI RtlIsDosDeviceName_U(PCWSTR); BOOLEAN WINAPI RtlIsNameLegalDOS8Dot3(const UNICODE_STRING*,POEM_STRING,PBOOLEAN); BOOLEAN WINAPI RtlIsTextUnicode(LPCVOID,INT,INT *);