A few changes were made to the error codes returned by library routines.
+ To make wimlib easier to use on Windows, wimlib_global_init() now
+ automatically attempts to acquire additional privileges on Windows, so
+ library clients need not do this (although they can provide a flag to
+ get the old behavior and manage privileges themselves).
+
This update bumps the shared library version number up to 9, since it
- doesn't quite not maintain binary compatibility with previous releases.
+ doesn't quite maintain binary compatibility with previous releases.
Version 1.4.2:
Fixed bug in `wimlib-imagex export' that made it impossible to export an
******************************/
/** Assume that strings are represented in UTF-8, even if this is not the
- * locale's character encoding. */
+ * locale's character encoding. Not used on Windows. */
#define WIMLIB_INIT_FLAG_ASSUME_UTF8 0x00000001
+/** Windows-only: do not attempt to acquire additional privileges (currently
+ * SeBackupPrivilege, SeRestorePrivilege, SeSecurityPrivilege, and
+ * SeTakeOwnershipPrivilege) when initializing the library. This is intended
+ * for the case where the calling program manages these privileges itself.
+ * Note: no error is issued if privileges cannot be acquired, although related
+ * errors may be reported later, depending on if the operations performed
+ * actually require additional privileges or not. */
+#define WIMLIB_INIT_FLAG_DONT_ACQUIRE_PRIVILEGES 0x00000002
+
/** Specification of an update to perform on a WIM image. */
struct wimlib_update_command {
* but you should not rely on this behavior.)
*
* @param init_flags
- * On UNIX, specify ::WIMLIB_INIT_FLAG_ASSUME_UTF8 if wimlib should assume
- * that all input data, including filenames, are in UTF-8 rather than the
- * locale-dependent character encoding which may or may not be UTF-8, and
- * that UTF-8 data can be directly printed to the console. On Windows, use
- * 0 for this parameter.
+ * Bitwise OR of ::WIMLIB_INIT_FLAG_ASSUME_UTF8 and/or
+ * ::WIMLIB_INIT_FLAG_DONT_ACQUIRE_PRIVILEGES.
*
* @return 0; other error codes may be returned in future releases.
*/
extern void
-win32_global_init(void);
+win32_global_init(int init_flags);
extern void
win32_global_cleanup(void);
extern int
win32_get_file_and_vol_ids(const wchar_t *path, u64 *ino_ret, u64 *dev_ret);
-
extern ssize_t
pread(int fd, void *buf, size_t count, off_t offset);
free(pglob->gl_pathv);
}
-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:
- if (!ret && enable) {
- fwprintf(stderr,
- L"WARNING: Failed to enable %ls!\n"
- " The program will continue, but if "
- "permission issues are\n"
- " encountered, you may need to run "
- "this program as the Administrator.\n",
- privilege);
- }
- return ret;
-}
-
-static void
-win32_modify_capture_privileges(bool enable)
-{
- win32_modify_privilege(SE_BACKUP_NAME, enable);
- win32_modify_privilege(SE_SECURITY_NAME, enable);
-}
-
-static void
-win32_modify_restore_privileges(bool enable)
-{
- win32_modify_privilege(SE_RESTORE_NAME, enable);
- win32_modify_privilege(SE_SECURITY_NAME, enable);
- win32_modify_privilege(SE_TAKE_OWNERSHIP_NAME, enable);
-}
-
-void
-win32_acquire_capture_privileges(void)
-{
- win32_modify_capture_privileges(true);
-}
-
-void
-win32_release_capture_privileges(void)
-{
- win32_modify_capture_privileges(false);
-}
-
-void
-win32_acquire_restore_privileges(void)
-{
- win32_modify_restore_privileges(true);
-}
-
-void
-win32_release_restore_privileges(void)
-{
- win32_modify_restore_privileges(false);
-}
-
/* Convert a string from the "current Windows codepage" to UTF-16LE. */
wchar_t *
win32_mbs_to_wcs(const char *mbs, size_t mbs_nbytes, size_t *num_wchars_ret)
}
#endif
-#ifdef __WIN32__
- win32_acquire_restore_privileges();
-#endif
if (wim) {
ret = wimlib_extract_image(wim, image, target, extract_flags,
additional_swms, num_additional_swms,
}
if (ret == 0)
imagex_printf(T("Done applying WIM image.\n"));
-#ifdef __WIN32__
- win32_release_restore_privileges();
-#endif
out_free_swms:
for (unsigned i = 0; i < num_additional_swms; i++)
wimlib_free(additional_swms[i]);
tsprintf(name_end, T(" (%lu)"), conflict_idx);
}
}
-#ifdef __WIN32__
- win32_acquire_capture_privileges();
-#endif
-
ret = wimlib_add_image_multisource(wim,
capture_sources,
num_sources,
add_image_flags,
imagex_progress_func);
if (ret)
- goto out_release_privs;
+ goto out_wimlib_free;
if (desc || flags_element) {
/* User provided <DESCRIPTION> or <FLAGS> element. Get the
info.image_count,
desc);
if (ret)
- goto out_release_privs;
+ goto out_wimlib_free;
}
if (flags_element) {
ret = wimlib_set_image_flags(wim, info.image_count,
flags_element);
if (ret)
- goto out_release_privs;
+ goto out_wimlib_free;
}
}
write_flags, num_threads,
imagex_progress_func);
}
-out_release_privs:
-#ifdef __WIN32__
- win32_release_capture_privileges();
-#endif
out_wimlib_free:
wimlib_free(wim);
out_free_config:
num_additional_swms = 0;
}
-#ifdef __WIN32__
- win32_acquire_restore_privileges();
-#endif
-
ret = wimlib_extract_files(wim, image, cmds, num_cmds, 0,
additional_swms, num_additional_swms,
imagex_progress_func);
" are in the WIM image.\n"),
get_cmd_string(CMD_INFO, false));
}
-#ifdef __WIN32__
- win32_release_restore_privileges();
-#endif
for (unsigned i = 0; i < num_additional_swms; i++)
wimlib_free(additional_swms[i]);
free(additional_swms);
}
}
-#ifdef __WIN32__
- if (have_add_command)
- win32_acquire_capture_privileges();
-#endif
-
/* Execute the update commands */
ret = wimlib_update_image(wim, image, cmds, num_cmds, update_flags,
imagex_progress_func);
if (ret)
- goto out_release_privs;
+ goto out_free_cmds;
/* Overwrite the updated WIM */
ret = wimlib_overwrite(wim, write_flags, num_threads,
imagex_progress_func);
-out_release_privs:
-#ifdef __WIN32__
- if (have_add_command)
- win32_release_capture_privileges();
-#endif
+out_free_cmds:
free(cmds);
out_free_cmd_file_contents:
free(cmd_file_contents);
if (!filename) {
pipe_str = alloca(40);
- tsprintf(pipe_str, "[fd %d]", in_fd->fd);
+ tsprintf(pipe_str, T("[fd %d]"), in_fd->fd);
filename = pipe_str;
}
#endif
}
#ifdef __WIN32__
- win32_global_init();
+ win32_global_init(init_flags);
#endif
already_inited = true;
return 0;
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 void
+win32_modify_capture_privileges(bool enable)
+{
+ win32_modify_privilege(SE_BACKUP_NAME, enable);
+ win32_modify_privilege(SE_SECURITY_NAME, enable);
+}
+
+static void
+win32_modify_apply_privileges(bool enable)
+{
+ 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_modify_capture_and_apply_privileges(bool enable)
+{
+ win32_modify_capture_privileges(enable);
+ win32_modify_apply_privileges(enable);
+}
+
+static void
+win32_acquire_capture_and_apply_privileges(void)
+{
+ win32_modify_capture_privileges(true);
+}
+
+static void
+win32_release_capture_and_apply_privileges(void)
+{
+ win32_modify_capture_privileges(false);
+}
+
HANDLE
win32_open_existing_file(const wchar_t *path, DWORD dwDesiredAccess)
{
static HMODULE hKernel32 = NULL;
+static bool acquired_privileges = false;
+
bool
windows_version_is_at_least(unsigned major, unsigned minor)
{
windows_version_info.dwMinorVersion >= minor);
}
-/* Try to dynamically load some functions */
+/* One-time initialization for Windows capture/apply code. */
void
-win32_global_init(void)
+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)) {
+ win32_acquire_capture_and_apply_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) {
win32func_FindFirstStreamW = (void*)GetProcAddress(hKernel32,
"FindFirstStreamW");
}
}
- GetVersionEx(&windows_version_info);
}
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;
}