X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fwin32_common.c;h=e3dace38946f8f912b4ded844662c49bc8bef4ad;hp=fc55709a7a7ce42090cc219aac5302772f999323;hb=8fc9b6f370468126f775fe5d0845dd4417c15a42;hpb=61db93f82eca3fe9f7676355c709c58cc425a6ad diff --git a/src/win32_common.c b/src/win32_common.c index fc55709a..e3dace38 100644 --- a/src/win32_common.c +++ b/src/win32_common.c @@ -450,6 +450,57 @@ out: return 0; } +static bool +win32_modify_privilege(const wchar_t *privilege, bool enable) +{ + HANDLE hToken; + LUID luid; + TOKEN_PRIVILEGES newState; + bool ret = FALSE; + + if (!OpenProcessToken(GetCurrentProcess(), + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, + &hToken)) + goto out; + + if (!LookupPrivilegeValue(NULL, privilege, &luid)) + goto out_close_handle; + + newState.PrivilegeCount = 1; + newState.Privileges[0].Luid = luid; + newState.Privileges[0].Attributes = (enable ? SE_PRIVILEGE_ENABLED : 0); + SetLastError(ERROR_SUCCESS); + ret = AdjustTokenPrivileges(hToken, FALSE, &newState, 0, NULL, NULL); + if (ret && GetLastError() == ERROR_NOT_ALL_ASSIGNED) + ret = FALSE; +out_close_handle: + CloseHandle(hToken); +out: + return ret; +} + +static bool +win32_modify_capture_privileges(bool enable) +{ + return win32_modify_privilege(SE_BACKUP_NAME, enable) + && win32_modify_privilege(SE_SECURITY_NAME, enable); +} + +static bool +win32_modify_apply_privileges(bool enable) +{ + return win32_modify_privilege(SE_RESTORE_NAME, enable) + && win32_modify_privilege(SE_SECURITY_NAME, enable) + && win32_modify_privilege(SE_TAKE_OWNERSHIP_NAME, enable); +} + +static void +win32_release_capture_and_apply_privileges(void) +{ + win32_modify_capture_privileges(false); + win32_modify_apply_privileges(false); +} + HANDLE win32_open_existing_file(const wchar_t *path, DWORD dwDesiredAccess) { @@ -469,6 +520,7 @@ win32_open_file_data_only(const wchar_t *path) return win32_open_existing_file(path, FILE_READ_DATA); } +#ifndef WITH_NTDLL /* Pointers to functions that are not available on all targetted versions of * Windows (XP and later). NOTE: The WINAPI annotations seem to be important; I * assume it specifies a certain calling convention. */ @@ -482,6 +534,12 @@ HANDLE (WINAPI *win32func_FindFirstStreamW)(LPCWSTR lpFileName, /* Vista and later */ BOOL (WINAPI *win32func_FindNextStreamW)(HANDLE hFindStream, LPVOID lpFindStreamData) = NULL; +#endif /* !WITH_NTDLL */ + +/* Vista and later */ +BOOL (WINAPI *win32func_CreateSymbolicLinkW)(const wchar_t *lpSymlinkFileName, + const wchar_t *lpTargetFileName, + DWORD dwFlags) = NULL; static OSVERSIONINFO windows_version_info = { .dwOSVersionInfoSize = sizeof(OSVERSIONINFO), @@ -489,6 +547,8 @@ static OSVERSIONINFO windows_version_info = { static HMODULE hKernel32 = NULL; +static bool acquired_privileges = false; + bool windows_version_is_at_least(unsigned major, unsigned minor) { @@ -497,23 +557,30 @@ windows_version_is_at_least(unsigned major, unsigned minor) windows_version_info.dwMinorVersion >= minor); } -/* Try to dynamically load some functions */ -void -win32_global_init(void) +/* One-time initialization for Windows capture/apply code. */ +int +win32_global_init(int init_flags) { - DWORD err; - - if (hKernel32 == NULL) { - DEBUG("Loading Kernel32.dll"); - hKernel32 = LoadLibraryW(L"Kernel32.dll"); - if (hKernel32 == NULL) { - err = GetLastError(); - WARNING("Can't load Kernel32.dll"); - win32_error(err); - } + /* Try to acquire useful privileges. */ + if (!(init_flags & WIMLIB_INIT_FLAG_DONT_ACQUIRE_PRIVILEGES)) { + if (!win32_modify_capture_privileges(true)) + if (init_flags & WIMLIB_INIT_FLAG_STRICT_CAPTURE_PRIVILEGES) + goto insufficient_privileges; + if (!win32_modify_apply_privileges(true)) + if (init_flags & WIMLIB_INIT_FLAG_STRICT_APPLY_PRIVILEGES) + goto insufficient_privileges; + acquired_privileges = true; } + /* Get Windows version information. */ + GetVersionEx(&windows_version_info); + + /* Try to dynamically load some functions. */ + if (hKernel32 == NULL) + hKernel32 = LoadLibrary(L"Kernel32.dll"); + if (hKernel32) { + #ifndef WITH_NTDLL win32func_FindFirstStreamW = (void*)GetProcAddress(hKernel32, "FindFirstStreamW"); if (win32func_FindFirstStreamW) { @@ -522,16 +589,23 @@ win32_global_init(void) if (!win32func_FindNextStreamW) win32func_FindFirstStreamW = NULL; } + #endif /* !WITH_NTDLL */ + win32func_CreateSymbolicLinkW = (void*)GetProcAddress(hKernel32, + "CreateSymbolicLinkW"); } + return 0; - GetVersionEx(&windows_version_info); +insufficient_privileges: + win32_release_capture_and_apply_privileges(); + return WIMLIB_ERR_INSUFFICIENT_PRIVILEGES; } void win32_global_cleanup(void) { + if (acquired_privileges) + win32_release_capture_and_apply_privileges(); if (hKernel32 != NULL) { - DEBUG("Closing Kernel32.dll"); FreeLibrary(hKernel32); hKernel32 = NULL; }