2 * win32_common.c - Windows code common to applying and capturing images.
6 * Copyright (C) 2013 Eric Biggers
8 * This file is part of wimlib, a library for working with WIM files.
10 * wimlib is free software; you can redistribute it and/or modify it under the
11 * terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 3 of the License, or (at your option)
15 * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
16 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17 * A PARTICULAR PURPOSE. See the GNU General Public License for more
20 * You should have received a copy of the GNU General Public License
21 * along with wimlib; if not, see http://www.gnu.org/licenses/.
32 #include "wimlib/win32_common.h"
34 #include "wimlib/assert.h"
35 #include "wimlib/error.h"
37 #ifdef ENABLE_ERROR_MESSAGES
39 win32_error(DWORD err_code)
43 nchars = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
44 FORMAT_MESSAGE_ALLOCATE_BUFFER,
46 (wchar_t*)&buffer, 0, NULL);
48 ERROR("Error printing error message! "
49 "Computer will self-destruct in 3 seconds.");
51 ERROR("Win32 error: %ls", buffer);
55 #endif /* ENABLE_ERROR_MESSAGES */
58 win32_error_to_errno(DWORD err_code)
60 /* This mapping is that used in Cygwin.
61 * Some of these choices are arbitrary. */
63 case ERROR_ACCESS_DENIED:
65 case ERROR_ACTIVE_CONNECTIONS:
67 case ERROR_ALREADY_EXISTS:
69 case ERROR_BAD_DEVICE:
71 case ERROR_BAD_EXE_FORMAT:
73 case ERROR_BAD_NETPATH:
75 case ERROR_BAD_NET_NAME:
77 case ERROR_BAD_NET_RESP:
79 case ERROR_BAD_PATHNAME:
85 case ERROR_BAD_USERNAME:
87 case ERROR_BEGINNING_OF_MEDIA:
89 case ERROR_BROKEN_PIPE:
95 case ERROR_CALL_NOT_IMPLEMENTED:
97 case ERROR_CANNOT_MAKE:
99 case ERROR_CHILD_NOT_COMPLETE:
101 case ERROR_COMMITMENT_LIMIT:
105 case ERROR_DEVICE_DOOR_OPEN:
107 case ERROR_DEVICE_IN_USE:
109 case ERROR_DEVICE_REQUIRES_CLEANING:
111 case ERROR_DIRECTORY:
113 case ERROR_DIR_NOT_EMPTY:
115 case ERROR_DISK_CORRUPT:
117 case ERROR_DISK_FULL:
123 case ERROR_EAS_DIDNT_FIT:
126 case ERROR_EAS_NOT_SUPPORTED:
129 case ERROR_EA_LIST_INCONSISTENT:
131 case ERROR_EA_TABLE_FULL:
133 case ERROR_END_OF_MEDIA:
135 case ERROR_EOM_OVERFLOW:
137 case ERROR_EXE_MACHINE_TYPE_MISMATCH:
139 case ERROR_EXE_MARKED_INVALID:
141 case ERROR_FILEMARK_DETECTED:
143 case ERROR_FILENAME_EXCED_RANGE:
145 case ERROR_FILE_CORRUPT:
147 case ERROR_FILE_EXISTS:
149 case ERROR_FILE_INVALID:
151 case ERROR_FILE_NOT_FOUND:
153 case ERROR_HANDLE_DISK_FULL:
156 case ERROR_HANDLE_EOF:
159 case ERROR_INVALID_ADDRESS:
161 case ERROR_INVALID_AT_INTERRUPT_TIME:
163 case ERROR_INVALID_BLOCK_LENGTH:
165 case ERROR_INVALID_DATA:
167 case ERROR_INVALID_DRIVE:
169 case ERROR_INVALID_EA_NAME:
171 case ERROR_INVALID_EXE_SIGNATURE:
174 case ERROR_INVALID_FUNCTION:
177 case ERROR_INVALID_HANDLE:
179 case ERROR_INVALID_NAME:
181 case ERROR_INVALID_PARAMETER:
183 case ERROR_INVALID_SIGNAL_NUMBER:
185 case ERROR_IOPL_NOT_ENABLED:
187 case ERROR_IO_DEVICE:
189 case ERROR_IO_INCOMPLETE:
191 case ERROR_IO_PENDING:
193 case ERROR_LOCK_VIOLATION:
195 case ERROR_MAX_THRDS_REACHED:
197 case ERROR_META_EXPANSION_TOO_LONG:
199 case ERROR_MOD_NOT_FOUND:
202 case ERROR_MORE_DATA:
205 case ERROR_NEGATIVE_SEEK:
207 case ERROR_NETNAME_DELETED:
211 case ERROR_NONE_MAPPED:
213 case ERROR_NONPAGED_SYSTEM_RESOURCES:
216 case ERROR_NOT_CONNECTED:
219 case ERROR_NOT_ENOUGH_MEMORY:
221 case ERROR_NOT_OWNER:
224 case ERROR_NOT_READY:
227 case ERROR_NOT_SAME_DEVICE:
229 case ERROR_NOT_SUPPORTED:
233 case ERROR_NO_DATA_DETECTED:
236 case ERROR_NO_MEDIA_IN_DRIVE:
240 case ERROR_NO_MORE_FILES:
244 case ERROR_NO_MORE_ITEMS:
247 case ERROR_NO_MORE_SEARCH_HANDLES:
249 case ERROR_NO_PROC_SLOTS:
251 case ERROR_NO_SIGNAL_SENT:
253 case ERROR_NO_SYSTEM_RESOURCES:
257 case ERROR_OPEN_FAILED:
259 case ERROR_OPEN_FILES:
261 case ERROR_OUTOFMEMORY:
263 case ERROR_PAGED_SYSTEM_RESOURCES:
265 case ERROR_PAGEFILE_QUOTA:
267 case ERROR_PATH_NOT_FOUND:
269 case ERROR_PIPE_BUSY:
271 case ERROR_PIPE_CONNECTED:
274 case ERROR_PIPE_LISTENING:
276 case ERROR_PIPE_NOT_CONNECTED:
279 case ERROR_POSSIBLE_DEADLOCK:
281 case ERROR_PRIVILEGE_NOT_HELD:
283 case ERROR_PROCESS_ABORTED:
285 case ERROR_PROC_NOT_FOUND:
288 case ERROR_REM_NOT_LIST:
291 case ERROR_SECTOR_NOT_FOUND:
295 case ERROR_SETMARK_DETECTED:
297 case ERROR_SHARING_BUFFER_EXCEEDED:
299 case ERROR_SHARING_VIOLATION:
301 case ERROR_SIGNAL_PENDING:
303 case ERROR_SIGNAL_REFUSED:
306 case ERROR_SXS_CANT_GEN_ACTCTX:
309 case ERROR_THREAD_1_INACTIVE:
311 case ERROR_TOO_MANY_LINKS:
313 case ERROR_TOO_MANY_OPEN_FILES:
315 case ERROR_WAIT_NO_CHILDREN:
317 case ERROR_WORKING_SET_QUOTA:
319 case ERROR_WRITE_PROTECT:
327 set_errno_from_GetLastError(void)
329 errno = win32_error_to_errno(GetLastError());
332 /* Given a path, which may not yet exist, get a set of flags that describe the
333 * features of the volume the path is on. */
335 win32_get_vol_flags(const wchar_t *path, unsigned *vol_flags_ret)
341 if (path[0] != L'\0' && path[0] != L'\\' &&
342 path[0] != L'/' && path[1] == L':')
344 /* Path starts with a drive letter; use it. */
345 volume = alloca(4 * sizeof(wchar_t));
351 /* Path does not start with a drive letter; use the volume of
352 * the current working directory. */
355 bret = GetVolumeInformationW(volume, /* lpRootPathName */
356 NULL, /* lpVolumeNameBuffer */
357 0, /* nVolumeNameSize */
358 NULL, /* lpVolumeSerialNumber */
359 NULL, /* lpMaximumComponentLength */
360 &vol_flags, /* lpFileSystemFlags */
361 NULL, /* lpFileSystemNameBuffer */
362 0); /* nFileSystemNameSize */
364 DWORD err = GetLastError();
365 WARNING("Failed to get volume information for path \"%ls\"", path);
367 vol_flags = 0xffffffff;
370 DEBUG("using vol_flags = %x", vol_flags);
371 *vol_flags_ret = vol_flags;
376 win32_open_existing_file(const wchar_t *path, DWORD dwDesiredAccess)
378 return CreateFileW(path,
381 NULL, /* lpSecurityAttributes */
383 FILE_FLAG_BACKUP_SEMANTICS |
384 FILE_FLAG_OPEN_REPARSE_POINT,
385 NULL /* hTemplateFile */);
389 win32_open_file_data_only(const wchar_t *path)
391 return win32_open_existing_file(path, FILE_READ_DATA);
394 /* Pointers to functions that are not available on all targetted versions of
395 * Windows (XP and later). NOTE: The WINAPI annotations seem to be important; I
396 * assume it specifies a certain calling convention. */
398 /* Vista and later */
399 HANDLE (WINAPI *win32func_FindFirstStreamW)(LPCWSTR lpFileName,
400 STREAM_INFO_LEVELS InfoLevel,
401 LPVOID lpFindStreamData,
402 DWORD dwFlags) = NULL;
404 /* Vista and later */
405 BOOL (WINAPI *win32func_FindNextStreamW)(HANDLE hFindStream,
406 LPVOID lpFindStreamData) = NULL;
408 static OSVERSIONINFO windows_version_info = {
409 .dwOSVersionInfoSize = sizeof(OSVERSIONINFO),
412 static HMODULE hKernel32 = NULL;
415 windows_version_is_at_least(unsigned major, unsigned minor)
417 return windows_version_info.dwMajorVersion > major ||
418 (windows_version_info.dwMajorVersion == major &&
419 windows_version_info.dwMinorVersion >= minor);
422 /* Try to dynamically load some functions */
424 win32_global_init(void)
428 if (hKernel32 == NULL) {
429 DEBUG("Loading Kernel32.dll");
430 hKernel32 = LoadLibraryW(L"Kernel32.dll");
431 if (hKernel32 == NULL) {
432 err = GetLastError();
433 WARNING("Can't load Kernel32.dll");
439 win32func_FindFirstStreamW = (void*)GetProcAddress(hKernel32,
441 if (win32func_FindFirstStreamW) {
442 win32func_FindNextStreamW = (void*)GetProcAddress(hKernel32,
444 if (!win32func_FindNextStreamW)
445 win32func_FindFirstStreamW = NULL;
449 GetVersionEx(&windows_version_info);
453 win32_global_cleanup(void)
455 if (hKernel32 != NULL) {
456 DEBUG("Closing Kernel32.dll");
457 FreeLibrary(hKernel32);
462 #endif /* __WIN32__ */