]> wimlib.net Git - wimlib/blobdiff - src/add_image.c
Win32 apply
[wimlib] / src / add_image.c
index fa3e77b04d33224c906af258a7d8b1a69c32f3e9..9d88916e638357517c1abf4cbcecadc0c267eed6 100644 (file)
@@ -21,6 +21,7 @@
  * along with wimlib; if not, see http://www.gnu.org/licenses/.
  */
 
+#include "config.h"
 
 #if defined(__CYGWIN__) || defined(__WIN32__)
 #      include <windows.h>
 #include <errno.h>
 #include <unistd.h>
 
-#if defined(__CYGWIN__) || defined(__WIN32__)
-/*#define ERROR_WIN32_SAFE(format, ...)                \*/
-/*{(                                           \*/
-          /*DWORD err = GetLastError();                \*/
-       /*ERROR(format, ##__VA_ARGS__);         \*/
-       /*SetLastError(err);                    \*/
-/*)}*/
-#define DEBUG_WIN32_SAFE(format, ...)          \
-({                                             \
-       DWORD err = GetLastError();             \
-       DEBUG(format, ##__VA_ARGS__);           \
-       SetLastError(err);                      \
-})
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#else
+#include <stdlib.h>
 #endif
 
 #define WIMLIB_ADD_IMAGE_FLAG_ROOT     0x80000000
@@ -118,71 +110,12 @@ err:
 }
 
 #if defined(__CYGWIN__) || defined(__WIN32__)
+
 static u64 FILETIME_to_u64(const FILETIME *ft)
 {
        return ((u64)ft->dwHighDateTime << 32) | (u64)ft->dwLowDateTime;
 }
 
-#ifdef ENABLE_ERROR_MESSAGES
-static void win32_error(DWORD err_code)
-{
-       char *buffer;
-       DWORD nchars;
-       nchars = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
-                               NULL, err_code, 0,
-                               (char*)&buffer, 0, NULL);
-       if (nchars == 0) {
-               ERROR("Error printing error message! "
-                     "Computer will self-destruct in 3 seconds.");
-       } else {
-               ERROR("Win32 error: %s", buffer);
-               LocalFree(buffer);
-       }
-}
-#else
-#define win32_error(err_code)
-#endif
-
-static HANDLE win32_open_file(const wchar_t *path)
-{
-       return CreateFileW(path,
-                          GENERIC_READ | READ_CONTROL,
-                          FILE_SHARE_READ,
-                          NULL, /* lpSecurityAttributes */
-                          OPEN_EXISTING,
-                          FILE_FLAG_BACKUP_SEMANTICS |
-                                  FILE_FLAG_OPEN_REPARSE_POINT,
-                          NULL /* hTemplateFile */);
-}
-
-int win32_read_file(const char *filename,
-                   void *handle, u64 offset, size_t size, u8 *buf)
-{
-       HANDLE h = handle;
-       DWORD err;
-       DWORD bytesRead;
-       LARGE_INTEGER liOffset = {.QuadPart = offset};
-
-       wimlib_assert(size <= 0xffffffff);
-
-       if (SetFilePointerEx(h, liOffset, NULL, FILE_BEGIN))
-               if (ReadFile(h, buf, size, &bytesRead, NULL) && bytesRead == size)
-                       return 0;
-       err = GetLastError();
-       ERROR("Error reading \"%s\"", filename);
-       win32_error(err);
-       return WIMLIB_ERR_READ;
-}
-
-void win32_close_handle(void *handle)
-{
-       CloseHandle((HANDLE)handle);
-}
-
-void *win32_open_handle(const char *path_utf16)
-{
-       return (void*)win32_open_file((const wchar_t*)path_utf16);
-}
 
 static int build_dentry_tree(struct wim_dentry **root_ret,
                             const char *root_disk_path,
@@ -221,14 +154,10 @@ static int win32_get_security_descriptor(struct wim_dentry *dentry,
        BOOL status;
        DWORD err;
 
-#ifdef BACKUP_SECURITY_INFORMATION
-       requestedInformation = BACKUP_SECURITY_INFORMATION;
-#else
        requestedInformation = DACL_SECURITY_INFORMATION |
                               SACL_SECURITY_INFORMATION |
                               OWNER_SECURITY_INFORMATION |
                               GROUP_SECURITY_INFORMATION;
-#endif
        /* Request length of security descriptor */
        status = GetFileSecurityW(path_utf16, requestedInformation,
                                  NULL, 0, &lenNeeded);
@@ -425,12 +354,11 @@ static int win32_capture_stream(const char *path,
                char *utf8_stream_name;
                size_t utf8_stream_name_len;
                ret = utf16_to_utf8((const char *)p,
-                                   colon - p,
+                                   (colon - p) * sizeof(wchar_t),
                                    &utf8_stream_name,
                                    &utf8_stream_name_len);
                if (ret)
                        goto out;
-               DEBUG_WIN32_SAFE("Add alternate data stream %s:%s", path, utf8_stream_name);
                ads_entry = inode_add_ads(inode, utf8_stream_name);
                FREE(utf8_stream_name);
                if (!ads_entry) {
@@ -500,9 +428,21 @@ static int win32_capture_streams(const char *path,
 
        hFind = FindFirstStreamW(path_utf16, FindStreamInfoStandard, &dat, 0);
        if (hFind == INVALID_HANDLE_VALUE) {
-               ERROR("Win32 API: Failed to look up data streams of \"%s\"",
-                     path);
-               return WIMLIB_ERR_READ;
+               err = GetLastError();
+
+               /* Seems legal for this to return ERROR_HANDLE_EOF on reparse
+                * points and directories */
+               if ((inode->i_attributes &
+                   (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY))
+                   && err == ERROR_HANDLE_EOF)
+               {
+                       return 0;
+               } else {
+                       ERROR("Win32 API: Failed to look up data streams of \"%s\"",
+                             path);
+                       win32_error(err);
+                       return WIMLIB_ERR_READ;
+               }
        }
        do {
                ret = win32_capture_stream(path, path_utf16,
@@ -829,14 +769,12 @@ static int build_dentry_tree(struct wim_dentry **root_ret,
                sd_set = extra_arg;
        }
 
-       DEBUG_WIN32_SAFE("root_disk_path=\"%s\"", root_disk_path);
        ret = utf8_to_utf16(root_disk_path, strlen(root_disk_path),
                            (char**)&path_utf16, &path_utf16_nchars);
        if (ret)
                goto out_destroy_sd_set;
        path_utf16_nchars /= sizeof(wchar_t);
 
-       DEBUG_WIN32_SAFE("Win32: Opening file `%s'", root_disk_path);
        HANDLE hFile = win32_open_file(path_utf16);
        if (hFile == INVALID_HANDLE_VALUE) {
                err = GetLastError();
@@ -892,7 +830,16 @@ static int build_dentry_tree(struct wim_dentry **root_ret,
 
        if (inode_is_directory(inode)) {
                /* Directory (not a reparse point) --- recurse to children */
-               DEBUG_WIN32_SAFE("Recursing to directory \"%s\"", root_disk_path);
+
+               /* But first... directories may have alternate data streams that
+                * need to be captured (maybe?) */
+               ret = win32_capture_streams(root_disk_path,
+                                           path_utf16,
+                                           path_utf16_nchars,
+                                           inode,
+                                           lookup_table);
+               if (ret)
+                       goto out_close_handle;
                ret = win32_recurse_directory(root,
                                              root_disk_path,
                                              lookup_table,
@@ -906,14 +853,12 @@ static int build_dentry_tree(struct wim_dentry **root_ret,
        } else if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
                /* Reparse point: save the reparse tag and data */
 
-               DEBUG_WIN32_SAFE("Capturing reparse point `%s'", root_disk_path);
                ret = win32_capture_reparse_point(root_disk_path,
                                                  hFile,
                                                  inode,
                                                  lookup_table);
 
        } else {
-               DEBUG_WIN32_SAFE("Capturing streams of \"%s\"", root_disk_path);
                /* Not a directory, not a reparse point */
                ret = win32_capture_streams(root_disk_path,
                                            path_utf16,
@@ -1442,6 +1387,17 @@ WIMLIBAPI int wimlib_add_image_multisource(WIMStruct *w,
                extra_arg = NULL;
        }
 
+#if defined(__CYGWIN__) || defined(__WIN32__)
+       if (add_image_flags & WIMLIB_ADD_IMAGE_FLAG_UNIX_DATA) {
+               ERROR("Capturing UNIX-specific data is not supported on Windows");
+               return WIMLIB_ERR_INVALID_PARAM;
+       }
+       if (add_image_flags & WIMLIB_ADD_IMAGE_FLAG_DEREFERENCE) {
+               ERROR("Dereferencing symbolic links is not supported on Windows");
+               return WIMLIB_ERR_INVALID_PARAM;
+       }
+#endif
+
        if (!name || !*name) {
                ERROR("Must specify a non-empty string for the image name");
                return WIMLIB_ERR_INVALID_PARAM;