diff --git a/reactos/include/rosrtl/priv.h b/reactos/include/rosrtl/priv.h new file mode 100644 index 00000000000..5d83fa5cc4b --- /dev/null +++ b/reactos/include/rosrtl/priv.h @@ -0,0 +1,23 @@ +/* $Id: priv.h,v 1.1 2004/08/11 08:28:13 weiden Exp $ + */ + +#ifndef ROSRTL_SEC_H__ +#define ROSRTL_SEC_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +BOOL +RosEnableThreadPrivileges(HANDLE *hToken, DWORD *Privileges, DWORD PrivilegeCount); +BOOL +RosResetThreadPrivileges(HANDLE hToken); + +#ifdef __cplusplus +} +#endif + +#endif + +/* EOF */ diff --git a/reactos/lib/rosrtl/makefile b/reactos/lib/rosrtl/makefile index 9db46aeade8..aff44ff197c 100644 --- a/reactos/lib/rosrtl/makefile +++ b/reactos/lib/rosrtl/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.13 2004/08/10 10:57:54 weiden Exp $ +# $Id: makefile,v 1.14 2004/08/11 08:28:13 weiden Exp $ PATH_TO_TOP = ../.. @@ -13,7 +13,8 @@ TARGET_SDKLIBS = ntdll.a kernel32.a advapi32.a THREAD_OBJECTS = \ thread/create.o \ thread/exit.o \ - thread/stack.o + thread/stack.o \ + thread/priv.o STRING_OBJECTS = \ string/append.o \ diff --git a/reactos/lib/rosrtl/thread/priv.c b/reactos/lib/rosrtl/thread/priv.c new file mode 100644 index 00000000000..e7306cac02d --- /dev/null +++ b/reactos/lib/rosrtl/thread/priv.c @@ -0,0 +1,117 @@ +#include +#include +#include + +/* + * Utility to copy and enable thread privileges + * + * OUT HANDLE *hPreviousToken -> Pointer to a variable that receives the previous token handle + * IN DWORD *Privileges -> Points to an array of privileges to be enabled + * IN DWORD PrivilegeCount -> Number of the privileges in the array + * + * Returns TRUE on success and copies the thread token (if any) handle that was active before impersonation. + */ +BOOL +RosEnableThreadPrivileges(HANDLE *hPreviousToken, + DWORD *Privileges, + DWORD PrivilegeCount) +{ + HANDLE hToken; + + if(hPreviousToken == NULL || + Privileges == NULL || PrivilegeCount == 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + /* Just open the thread token, we'll duplicate the handle later */ + if(OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE, FALSE, &hToken)) + { + PTOKEN_PRIVILEGES privs; + PLUID_AND_ATTRIBUTES la; + HANDLE hNewToken; + BOOL Ret; + + /* duplicate the token handle */ + if(!DuplicateTokenEx(hToken, TOKEN_IMPERSONATE, NULL, SecurityImpersonation, + TokenImpersonation, &hNewToken)) + { + CloseHandle(hToken); + return FALSE; + } + + /* Allocate the required space for the privilege list */ + privs = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, sizeof(TOKEN_PRIVILEGES) + + ((PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES))); + if(privs == NULL) + { + CloseHandle(hNewToken); + CloseHandle(hToken); + return FALSE; + } + + /* Build the privilege list */ + privs->PrivilegeCount = PrivilegeCount; + for(la = privs->Privileges; PrivilegeCount-- > 0; la++) + { + la->Luid.LowPart = *(Privileges++); + la->Luid.HighPart = 0; + la->Attributes = SE_PRIVILEGE_ENABLED; + } + + /* Enable the token privileges */ + if(!AdjustTokenPrivileges(hNewToken, FALSE, privs, 0, NULL, NULL)) + { + LocalFree((HLOCAL)privs); + CloseHandle(hNewToken); + CloseHandle(hToken); + return FALSE; + } + + /* we don't need the privileges list anymore */ + LocalFree((HLOCAL)privs); + + /* Perform the impersonation */ + Ret = SetThreadToken(NULL, hToken); + + if(Ret) + { + /* only copy the previous token handle on success */ + *hPreviousToken = hToken; + } + + /* We don't need the handle to the new token anymore */ + CloseHandle(hNewToken); + + return Ret; + } + + return FALSE; +} + + +/* + * Utility to reset the thread privileges previously changed with RosEnableThreadPrivileges() + * + * IN HANDLE hToken -> Handle of the thread token to be restored + * + * Returns TRUE on success. + */ +BOOL +RosResetThreadPrivileges(HANDLE hToken) +{ + if(hToken != INVALID_HANDLE_VALUE) + { + BOOL Ret; + + /* Set the previous token handle */ + Ret = SetThreadToken(NULL, hToken); + + /* We don't need the handle anymore, close it */ + CloseHandle(hToken); + return Ret; + } + return FALSE; +} +