From: Tim Clem tclem@codeweavers.com
--- dlls/win32u/winstation.c | 17 ++++++++++++++++- server/protocol.def | 8 ++++++++ server/token.c | 25 +++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index d2386fd5af5..8df1c09a7eb 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -771,6 +771,7 @@ HWND get_desktop_window(void) WCHAR desktop[MAX_PATH]; PEB *peb = NtCurrentTeb()->Peb; HANDLE process, thread; + HANDLE token; unsigned int status;
SERVER_START_REQ( set_user_object_info ) @@ -789,6 +790,19 @@ HWND get_desktop_window(void) } SERVER_END_REQ;
+ SERVER_START_REQ( create_primary_admin_token ) + { + req->elevation = TokenElevationTypeDefault; + if (!wine_server_call( req )) + token = wine_server_ptr_handle( reply->token ); + else + { + WARN( "couldn't get a default token; starting explorer with current thread's\n" ); + token = GetCurrentThreadEffectiveToken(); + } + } + SERVER_END_REQ; + params.Flags = PROCESS_PARAMS_FLAG_NORMALIZED; params.Environment = peb->ProcessParameters->Environment; params.EnvironmentSize = peb->ProcessParameters->EnvironmentSize; @@ -806,7 +820,7 @@ HWND get_desktop_window(void)
ps_attr->Attributes[1].Attribute = PS_ATTRIBUTE_TOKEN; ps_attr->Attributes[1].Size = sizeof(HANDLE); - ps_attr->Attributes[1].ValuePtr = GetCurrentThreadEffectiveToken(); + ps_attr->Attributes[1].ValuePtr = token; ps_attr->Attributes[1].ReturnLength = NULL;
ps_attr->TotalLength = offsetof( PS_ATTRIBUTE_LIST, Attributes[2] ); @@ -823,6 +837,7 @@ HWND get_desktop_window(void) status = NtCreateUserProcess( &process, &thread, PROCESS_ALL_ACCESS, THREAD_ALL_ACCESS, NULL, NULL, 0, THREAD_CREATE_FLAGS_CREATE_SUSPENDED, ¶ms, &create_info, ps_attr ); + NtClose( token ); if (!status) { NtResumeThread( thread, NULL ); diff --git a/server/protocol.def b/server/protocol.def index f2db46bd87d..74858083dcc 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3279,6 +3279,14 @@ enum caret_state @END
+/* Create a new primary token with the default admin properties. */ +@REQ(create_primary_admin_token) + int elevation; /* elevation type */ +@REPLY + obj_handle_t token; /* handle to the token */ +@END + + /* Open a security token */ @REQ(open_token) obj_handle_t handle; /* handle to the thread or process */ diff --git a/server/token.c b/server/token.c index 48ee1eca8fe..94281ff699a 100644 --- a/server/token.c +++ b/server/token.c @@ -1209,6 +1209,31 @@ DECL_HANDLER(create_token) }
+/* create a new default, primary token with the given elevation */ +DECL_HANDLER(create_primary_admin_token) +{ + struct token *token; + + if (req->elevation != TokenElevationTypeDefault && + req->elevation != TokenElevationTypeFull && + req->elevation != TokenElevationTypeLimited) + { + set_error( STATUS_INVALID_PARAMETER ); + return; + } + + token = token_create_admin( TRUE, SecurityIdentification, req->elevation, default_session_id ); + if (!token) + { + set_error( STATUS_UNSUCCESSFUL ); + return; + } + + reply->token = alloc_handle( current->process, token, TOKEN_ALL_ACCESS, 0 ); + release_object( token ); +} + + /* open a security token */ DECL_HANDLER(open_token) {