From 94ecf74c5f1f3a078d6d658a5c2f74f15d428ddb Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Mon, 4 Sep 2023 11:41:35 +0100 Subject: [PATCH] [misc] use FORMAT_MESSAGE_FROM_HMODULE where possible and drop our custom message tables --- src/net.c | 201 ++-------------------- src/rufus.rc | 10 +- src/stdio.c | 468 +++------------------------------------------------ 3 files changed, 41 insertions(+), 638 deletions(-) diff --git a/src/net.c b/src/net.c index bdbb9c7a..43f96d94 100644 --- a/src/net.c +++ b/src/net.c @@ -62,177 +62,6 @@ static const char* request_headers = "Accept-Encoding: gzip, deflate"; #define INetworkListManager_get_IsConnectedToInternet INetworkListManager_IsConnectedToInternet #endif -/* - * FormatMessage does not handle internet errors - * https://docs.microsoft.com/en-us/windows/desktop/wininet/wininet-errors - */ -const char* WinInetErrorString(void) -{ - static char error_string[256]; - DWORD size = sizeof(error_string); - PF_TYPE_DECL(WINAPI, BOOL, InternetGetLastResponseInfoA, (LPDWORD, LPSTR, LPDWORD)); - PF_INIT(InternetGetLastResponseInfoA, WinInet); - - error_code = HRESULT_CODE(GetLastError()); - - if ((error_code < INTERNET_ERROR_BASE) || (error_code > INTERNET_ERROR_LAST)) - return WindowsErrorString(); - - switch(error_code) { - case ERROR_INTERNET_OUT_OF_HANDLES: - return "No more handles could be generated at this time."; - case ERROR_INTERNET_TIMEOUT: - return "The request has timed out."; - case ERROR_INTERNET_INTERNAL_ERROR: - return "An internal error has occurred."; - case ERROR_INTERNET_INVALID_URL: - return "The URL is invalid."; - case ERROR_INTERNET_UNRECOGNIZED_SCHEME: - return "The URL scheme could not be recognized or is not supported."; - case ERROR_INTERNET_NAME_NOT_RESOLVED: - return "The server name could not be resolved."; - case ERROR_INTERNET_PROTOCOL_NOT_FOUND: - return "The requested protocol could not be located."; - case ERROR_INTERNET_INVALID_OPTION: - return "A request specified an invalid option value."; - case ERROR_INTERNET_BAD_OPTION_LENGTH: - return "The length of an option supplied is incorrect for the type of option specified."; - case ERROR_INTERNET_OPTION_NOT_SETTABLE: - return "The request option cannot be set, only queried."; - case ERROR_INTERNET_SHUTDOWN: - return "The Win32 Internet function support is being shut down or unloaded."; - case ERROR_INTERNET_INCORRECT_USER_NAME: - return "The request to connect and log on to an FTP server could not be completed because the supplied user name is incorrect."; - case ERROR_INTERNET_INCORRECT_PASSWORD: - return "The request to connect and log on to an FTP server could not be completed because the supplied password is incorrect."; - case ERROR_INTERNET_LOGIN_FAILURE: - return "The request to connect to and log on to an FTP server failed."; - case ERROR_INTERNET_INVALID_OPERATION: - return "The requested operation is invalid."; - case ERROR_INTERNET_OPERATION_CANCELLED: - return "The operation was cancelled, usually because the handle on which the request was operating was closed before the operation completed."; - case ERROR_INTERNET_INCORRECT_HANDLE_TYPE: - return "The type of handle supplied is incorrect for this operation."; - case ERROR_INTERNET_INCORRECT_HANDLE_STATE: - return "The requested operation cannot be carried out because the handle supplied is not in the correct state."; - case ERROR_INTERNET_NOT_PROXY_REQUEST: - return "The request cannot be made via a proxy."; - case ERROR_INTERNET_REGISTRY_VALUE_NOT_FOUND: - return "A required registry value could not be located."; - case ERROR_INTERNET_BAD_REGISTRY_PARAMETER: - return "A required registry value was located but is an incorrect type or has an invalid value."; - case ERROR_INTERNET_NO_DIRECT_ACCESS: - return "Direct network access cannot be made at this time."; - case ERROR_INTERNET_NO_CONTEXT: - return "An asynchronous request could not be made because a zero context value was supplied."; - case ERROR_INTERNET_NO_CALLBACK: - return "An asynchronous request could not be made because a callback function has not been set."; - case ERROR_INTERNET_REQUEST_PENDING: - return "The required operation could not be completed because one or more requests are pending."; - case ERROR_INTERNET_INCORRECT_FORMAT: - return "The format of the request is invalid."; - case ERROR_INTERNET_ITEM_NOT_FOUND: - return "The requested item could not be located."; - case ERROR_INTERNET_CANNOT_CONNECT: - return "The attempt to connect to the server failed."; - case ERROR_INTERNET_CONNECTION_ABORTED: - return "The connection with the server has been terminated."; - case ERROR_INTERNET_CONNECTION_RESET: - return "The connection with the server has been reset."; - case ERROR_INTERNET_FORCE_RETRY: - return "Calls for the Win32 Internet function to redo the request."; - case ERROR_INTERNET_INVALID_PROXY_REQUEST: - return "The request to the proxy was invalid."; - case ERROR_INTERNET_HANDLE_EXISTS: - return "The request failed because the handle already exists."; - case ERROR_INTERNET_SEC_INVALID_CERT: - return "The SSL certificate is invalid."; - case ERROR_INTERNET_SEC_CERT_DATE_INVALID: - return "SSL certificate date that was received from the server is bad. The certificate is expired."; - case ERROR_INTERNET_SEC_CERT_CN_INVALID: - return "SSL certificate common name (host name field) is incorrect."; - case ERROR_INTERNET_SEC_CERT_ERRORS: - return "The SSL certificate contains errors."; - case ERROR_INTERNET_SEC_CERT_NO_REV: - return "The SSL certificate was not revoked."; - case ERROR_INTERNET_SEC_CERT_REV_FAILED: - return "The revocation check of the SSL certificate failed."; - case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR: - return "The application is moving from a non-SSL to an SSL connection because of a redirect."; - case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR: - return "The application is moving from an SSL to an non-SSL connection because of a redirect."; - case ERROR_INTERNET_MIXED_SECURITY: - return "Some of the content being viewed may have come from unsecured servers."; - case ERROR_INTERNET_CHG_POST_IS_NON_SECURE: - return "The application is posting and attempting to change multiple lines of text on a server that is not secure."; - case ERROR_INTERNET_POST_IS_NON_SECURE: - return "The application is posting data to a server that is not secure."; - case ERROR_FTP_TRANSFER_IN_PROGRESS: - return "The requested operation cannot be made on the FTP session handle because an operation is already in progress."; - case ERROR_FTP_DROPPED: - return "The FTP operation was not completed because the session was aborted."; - case ERROR_GOPHER_PROTOCOL_ERROR: - case ERROR_GOPHER_NOT_FILE: - case ERROR_GOPHER_DATA_ERROR: - case ERROR_GOPHER_END_OF_DATA: - case ERROR_GOPHER_INVALID_LOCATOR: - case ERROR_GOPHER_INCORRECT_LOCATOR_TYPE: - case ERROR_GOPHER_NOT_GOPHER_PLUS: - case ERROR_GOPHER_ATTRIBUTE_NOT_FOUND: - case ERROR_GOPHER_UNKNOWN_LOCATOR: - return "Gopher? Really??? What is this, 1994?"; - case ERROR_HTTP_HEADER_NOT_FOUND: - return "The requested header could not be located."; - case ERROR_HTTP_DOWNLEVEL_SERVER: - return "The server did not return any headers."; - case ERROR_HTTP_INVALID_SERVER_RESPONSE: - return "The server response could not be parsed."; - case ERROR_HTTP_INVALID_HEADER: - return "The supplied header is invalid."; - case ERROR_HTTP_INVALID_QUERY_REQUEST: - return "The request made to HttpQueryInfo is invalid."; - case ERROR_HTTP_HEADER_ALREADY_EXISTS: - return "The header could not be added because it already exists."; - case ERROR_HTTP_REDIRECT_FAILED: - return "The redirection failed because either the scheme changed or all attempts made to redirect failed."; - case ERROR_INTERNET_SECURITY_CHANNEL_ERROR: - return "This system's SSL library is too old to be able to access this website."; - case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED: - return "Client Authentication certificate needed"; - case ERROR_INTERNET_BAD_AUTO_PROXY_SCRIPT: - return "Bad auto proxy script."; - case ERROR_INTERNET_UNABLE_TO_DOWNLOAD_SCRIPT: - return "Unable to download script."; - case ERROR_INTERNET_NOT_INITIALIZED: - return "Internet has not be initialized."; - case ERROR_INTERNET_UNABLE_TO_CACHE_FILE: - return "Unable to cache the file."; - case ERROR_INTERNET_TCPIP_NOT_INSTALLED: - return "TPC/IP not installed."; - case ERROR_INTERNET_DISCONNECTED: - return "Internet is disconnected."; - case ERROR_INTERNET_SERVER_UNREACHABLE: - return "Server could not be reached."; - case ERROR_INTERNET_PROXY_SERVER_UNREACHABLE: - return "Proxy server could not be reached."; - case ERROR_INTERNET_FAILED_DUETOSECURITYCHECK: - return "A security check prevented internet connection."; - case ERROR_INTERNET_NEED_MSN_SSPI_PKG: - return "This connection requires an MSN Security Support Provider Interface package."; - case ERROR_INTERNET_LOGIN_FAILURE_DISPLAY_ENTITY_BODY: - return "Please ask Microsoft about that one!"; - case ERROR_INTERNET_EXTENDED_ERROR: - if (pfInternetGetLastResponseInfoA != NULL) { - pfInternetGetLastResponseInfoA(&error_code, error_string, &size); - return error_string; - } - // fall through - default: - static_sprintf(error_string, "Unknown internet error 0x%08lX", error_code); - return error_string; - } -} - static char* GetShortName(const char* url) { static char short_name[128]; @@ -393,34 +222,34 @@ uint64_t DownloadToFileOrBufferEx(const char* url, const char* file, const char* if ( (!pfInternetCrackUrlA(url, (DWORD)safe_strlen(url), 0, &UrlParts)) || (UrlParts.lpszHostName == NULL) || (UrlParts.lpszUrlPath == NULL)) { - uprintf("Unable to decode URL: %s", WinInetErrorString()); + uprintf("Unable to decode URL: %s", WindowsErrorString()); goto out; } hostname[sizeof(hostname)-1] = 0; hSession = GetInternetSession(user_agent, TRUE); if (hSession == NULL) { - uprintf("Could not open Internet session: %s", WinInetErrorString()); + uprintf("Could not open Internet session: %s", WindowsErrorString()); goto out; } hConnection = pfInternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL); if (hConnection == NULL) { - uprintf("Could not connect to server %s:%d: %s", UrlParts.lpszHostName, UrlParts.nPort, WinInetErrorString()); + uprintf("Could not connect to server %s:%d: %s", UrlParts.lpszHostName, UrlParts.nPort, WindowsErrorString()); goto out; } hRequest = pfHttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, accept_types, - INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS| - INTERNET_FLAG_NO_COOKIES|INTERNET_FLAG_NO_UI|INTERNET_FLAG_NO_CACHE_WRITE|INTERNET_FLAG_HYPERLINK| + INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | + INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_UI | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_HYPERLINK | ((UrlParts.nScheme==INTERNET_SCHEME_HTTPS)?INTERNET_FLAG_SECURE:0), (DWORD_PTR)NULL); if (hRequest == NULL) { - uprintf("Could not open URL %s: %s", url, WinInetErrorString()); + uprintf("Could not open URL %s: %s", url, WindowsErrorString()); goto out; } if (!pfHttpSendRequestA(hRequest, request_headers, -1L, NULL, 0)) { - uprintf("Unable to send request: %s", WinInetErrorString()); + uprintf("Unable to send request: %s", WindowsErrorString()); goto out; } @@ -435,7 +264,7 @@ uint64_t DownloadToFileOrBufferEx(const char* url, const char* file, const char* } dwSize = sizeof(strsize); if (!pfHttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH, (LPVOID)strsize, &dwSize, NULL)) { - uprintf("Unable to retrieve file length: %s", WinInetErrorString()); + uprintf("Unable to retrieve file length: %s", WindowsErrorString()); goto out; } total_size = strtoull(strsize, NULL, 10); @@ -452,7 +281,7 @@ uint64_t DownloadToFileOrBufferEx(const char* url, const char* file, const char* if (file != NULL) { hFile = CreateFileU(file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { - uprintf("Unable to create file '%s': %s", short_name, WinInetErrorString()); + uprintf("Unable to create file '%s': %s", short_name, WindowsErrorString()); goto out; } } else { @@ -479,7 +308,7 @@ uint64_t DownloadToFileOrBufferEx(const char* url, const char* file, const char* UpdateProgressWithInfo(OP_NOOP, MSG_241, size, total_size); if (file != NULL) { if (!WriteFile(hFile, buf, dwDownloaded, &dwWritten, NULL)) { - uprintf("Error writing file '%s': %s", short_name, WinInetErrorString()); + uprintf("Error writing file '%s': %s", short_name, WindowsErrorString()); goto out; } else if (dwDownloaded != dwWritten) { uprintf("Error writing file '%s': Only %d/%d bytes written", short_name, dwWritten, dwDownloaded); @@ -564,11 +393,11 @@ DWORD DownloadSignedFile(const char* url, const char* file, HWND hProgressDialog DownloadStatus = 206; // Partial content hFile = CreateFileU(file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { - uprintf("Unable to create file '%s': %s", PathFindFileNameU(file), WinInetErrorString()); + uprintf("Unable to create file '%s': %s", PathFindFileNameU(file), WindowsErrorString()); goto out; } if (!WriteFile(hFile, buf, buf_len, &ret, NULL)) { - uprintf("Error writing file '%s': %s", PathFindFileNameU(file), WinInetErrorString()); + uprintf("Error writing file '%s': %s", PathFindFileNameU(file), WindowsErrorString()); ret = 0; goto out; } else if (ret != buf_len) { @@ -584,7 +413,7 @@ out: if ((bPromptOnError) && (DownloadStatus != 200)) { PrintInfo(0, MSG_242); SetLastError(error_code); - MessageBoxExU(hMainDialog, IS_ERROR(FormatStatus) ? StrError(FormatStatus, FALSE) : WinInetErrorString(), + MessageBoxExU(hMainDialog, IS_ERROR(FormatStatus) ? StrError(FormatStatus, FALSE) : WindowsErrorString(), lmprintf(MSG_044), MB_OK | MB_ICONERROR | MB_IS_RTL, selected_langid); } safe_closehandle(hFile); @@ -758,7 +587,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) INTERNET_FLAG_NO_COOKIES|INTERNET_FLAG_NO_UI|INTERNET_FLAG_NO_CACHE_WRITE|INTERNET_FLAG_HYPERLINK| ((UrlParts.nScheme == INTERNET_SCHEME_HTTPS)?INTERNET_FLAG_SECURE:0), (DWORD_PTR)NULL); if ((hRequest == NULL) || (!pfHttpSendRequestA(hRequest, request_headers, -1L, NULL, 0))) { - uprintf("Unable to send request: %s", WinInetErrorString()); + uprintf("Unable to send request: %s", WindowsErrorString()); goto out; } @@ -1055,7 +884,7 @@ static DWORD WINAPI DownloadISOThread(LPVOID param) Notification(MSG_INFO, NULL, NULL, lmprintf(MSG_211), lmprintf(MSG_041)); PrintInfo(0, MSG_211); } else { - Notification(MSG_ERROR, NULL, NULL, lmprintf(MSG_194, GetShortName(url)), lmprintf(MSG_043, WinInetErrorString())); + Notification(MSG_ERROR, NULL, NULL, lmprintf(MSG_194, GetShortName(url)), lmprintf(MSG_043, WindowsErrorString())); PrintInfo(0, MSG_212); } } else { diff --git a/src/rufus.rc b/src/rufus.rc index 67e260e7..133e3e0f 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 232, 326 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES -CAPTION "Rufus 4.3.2079" +CAPTION "Rufus 4.3.2080" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -392,8 +392,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,3,2079,0 - PRODUCTVERSION 4,3,2079,0 + FILEVERSION 4,3,2080,0 + PRODUCTVERSION 4,3,2080,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -411,13 +411,13 @@ BEGIN VALUE "Comments", "https://rufus.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "4.3.2079" + VALUE "FileVersion", "4.3.2080" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" VALUE "OriginalFilename", "rufus-4.3.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "4.3.2079" + VALUE "ProductVersion", "4.3.2080" END END BLOCK "VarFileInfo" diff --git a/src/stdio.c b/src/stdio.c index eaef1810..fe80dc0f 100644 --- a/src/stdio.c +++ b/src/stdio.c @@ -219,472 +219,46 @@ void DumpBufferHex(void *buf, size_t size) uprintf("%s\n", line); } -// Count on Microsoft to add a new API while not bothering updating the existing error facilities, -// so that the new error messages have to be handled manually. Now, since I don't have all day: -// 1. Copy text from https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-vds/5102cc53-3143-4268-ba4c-6ea39e999ab4 -// 2. awk '{l[NR%7]=$0} {if (NR%7==0) printf "\tcase %s:\t// %s\n\t\treturn \"%s\";\n", l[1], l[3], l[6]}' vds.txt -// 3. Filter out the crap we don't need. -static const char *GetVdsError(DWORD error_code) -{ - switch (error_code) { - case 0x80042400: // VDS_E_NOT_SUPPORTED - return "The operation is not supported by the object."; - case 0x80042401: // VDS_E_INITIALIZED_FAILED - return "VDS or the provider failed to initialize."; - case 0x80042402: // VDS_E_INITIALIZE_NOT_CALLED - return "VDS did not call the hardware provider's initialization method."; - case 0x80042403: // VDS_E_ALREADY_REGISTERED - return "The provider is already registered."; - case 0x80042404: // VDS_E_ANOTHER_CALL_IN_PROGRESS - return "A concurrent second call is made on an object before the first call is completed."; - case 0x80042405: // VDS_E_OBJECT_NOT_FOUND - return "The specified object was not found."; - case 0x80042406: // VDS_E_INVALID_SPACE - return "The specified space is neither free nor valid."; - case 0x80042407: // VDS_E_PARTITION_LIMIT_REACHED - return "No more partitions can be created on the specified disk."; - case 0x80042408: // VDS_E_PARTITION_NOT_EMPTY - return "The extended partition is not empty."; - case 0x80042409: // VDS_E_OPERATION_PENDING - return "The operation is still in progress."; - case 0x8004240A: // VDS_E_OPERATION_DENIED - return "The operation is not permitted on the specified disk, partition, or volume."; - case 0x8004240B: // VDS_E_OBJECT_DELETED - return "The object no longer exists."; - case 0x8004240C: // VDS_E_CANCEL_TOO_LATE - return "The operation can no longer be canceled."; - case 0x8004240D: // VDS_E_OPERATION_CANCELED - return "The operation has already been canceled."; - case 0x8004240E: // VDS_E_CANNOT_EXTEND - return "The file system does not support extending this volume."; - case 0x8004240F: // VDS_E_NOT_ENOUGH_SPACE - return "There is not enough space to complete the operation."; - case 0x80042410: // VDS_E_NOT_ENOUGH_DRIVE - return "There are not enough free disk drives in the subsystem to complete the operation."; - case 0x80042411: // VDS_E_BAD_COOKIE - return "The cookie was not found."; - case 0x80042412: // VDS_E_NO_MEDIA - return "There is no removable media in the drive."; - case 0x80042413: // VDS_E_DEVICE_IN_USE - return "The device is currently in use."; - case 0x80042414: // VDS_E_DISK_NOT_EMPTY - return "The disk contains partitions or volumes."; - case 0x80042415: // VDS_E_INVALID_OPERATION - return "The specified operation is not valid."; - case 0x80042416: // VDS_E_PATH_NOT_FOUND - return "The specified path was not found."; - case 0x80042417: // VDS_E_DISK_NOT_INITIALIZED - return "The specified disk has not been initialized."; - case 0x80042418: // VDS_E_NOT_AN_UNALLOCATED_DISK - return "The specified disk is not an unallocated disk."; - case 0x80042419: // VDS_E_UNRECOVERABLE_ERROR - return "An unrecoverable error occurred. The service MUST shut down."; - case 0x0004241A: // VDS_S_DISK_PARTIALLY_CLEANED - return "The clean operation was not a full clean or was canceled before it could be completed."; - case 0x8004241B: // VDS_E_DMADMIN_SERVICE_CONNECTION_FAILED - return "The provider failed to connect to the LDMA service."; - case 0x8004241C: // VDS_E_PROVIDER_INITIALIZATION_FAILED - return "The provider failed to initialize."; - case 0x8004241D: // VDS_E_OBJECT_EXISTS - return "The object already exists."; - case 0x8004241E: // VDS_E_NO_DISKS_FOUND - return "No disks were found on the target machine."; - case 0x8004241F: // VDS_E_PROVIDER_CACHE_CORRUPT - return "The cache for a provider is corrupt."; - case 0x80042420: // VDS_E_DMADMIN_METHOD_CALL_FAILED - return "A method call to the LDMA service failed."; - case 0x00042421: // VDS_S_PROVIDER_ERROR_LOADING_CACHE - return "The provider encountered errors while loading the cache."; - case 0x80042422: // VDS_E_PROVIDER_VOL_DEVICE_NAME_NOT_FOUND - return "The device form of the volume pathname could not be retrieved."; - case 0x80042423: // VDS_E_PROVIDER_VOL_OPEN - return "Failed to open the volume device"; - case 0x80042424: // VDS_E_DMADMIN_CORRUPT_NOTIFICATION - return "A corrupt notification was sent from the LDMA service."; - case 0x80042425: // VDS_E_INCOMPATIBLE_FILE_SYSTEM - return "The file system is incompatible with the specified operation."; - case 0x80042426: // VDS_E_INCOMPATIBLE_MEDIA - return "The media is incompatible with the specified operation."; - case 0x80042427: // VDS_E_ACCESS_DENIED - return "Access is denied. A VDS operation MUST run elevated."; - case 0x80042428: // VDS_E_MEDIA_WRITE_PROTECTED - return "The media is write-protected."; - case 0x80042429: // VDS_E_BAD_LABEL - return "The volume label is not valid."; - case 0x8004242A: // VDS_E_CANT_QUICK_FORMAT - return "The volume cannot be quick-formatted."; - case 0x8004242B: // VDS_E_IO_ERROR - return "An I/O error occurred during the operation."; - case 0x8004242C: // VDS_E_VOLUME_TOO_SMALL - return "The volume size is too small."; - case 0x8004242D: // VDS_E_VOLUME_TOO_BIG - return "The volume size is too large."; - case 0x8004242E: // VDS_E_CLUSTER_SIZE_TOO_SMALL - return "The cluster size is too small."; - case 0x8004242F: // VDS_E_CLUSTER_SIZE_TOO_BIG - return "The cluster size is too large."; - case 0x80042430: // VDS_E_CLUSTER_COUNT_BEYOND_32BITS - return "The number of clusters is too large to be represented as a 32-bit integer."; - case 0x80042431: // VDS_E_OBJECT_STATUS_FAILED - return "The component that the object represents has failed."; - case 0x80042432: // VDS_E_VOLUME_INCOMPLETE - return "The volume is incomplete."; - case 0x80042433: // VDS_E_EXTENT_SIZE_LESS_THAN_MIN - return "The specified extent size is too small."; - case 0x00042434: // VDS_S_UPDATE_BOOTFILE_FAILED - return "The operation was successful, but VDS failed to update the boot options."; - case 0x00042436: // VDS_S_BOOT_PARTITION_NUMBER_CHANGE - case 0x80042436: // VDS_E_BOOT_PARTITION_NUMBER_CHANGE - return "The boot partition's partition number will change as a result of the operation."; - case 0x80042437: // VDS_E_NO_FREE_SPACE - return "The specified disk does not have enough free space to complete the operation."; - case 0x80042438: // VDS_E_ACTIVE_PARTITION - return "An active partition was detected on the selected disk."; - case 0x80042439: // VDS_E_PARTITION_OF_UNKNOWN_TYPE - return "The partition information cannot be read."; - case 0x8004243A: // VDS_E_LEGACY_VOLUME_FORMAT - return "A partition with an unknown type was detected on the specified disk."; - case 0x8004243C: // VDS_E_MIGRATE_OPEN_VOLUME - return "A volume on the specified disk could not be opened."; - case 0x8004243D: // VDS_E_VOLUME_NOT_ONLINE - return "The volume is not online."; - case 0x8004243E: // VDS_E_VOLUME_NOT_HEALTHY - return "The volume is failing or has failed."; - case 0x8004243F: // VDS_E_VOLUME_SPANS_DISKS - return "The volume spans multiple disks."; - case 0x80042440: // VDS_E_REQUIRES_CONTIGUOUS_DISK_SPACE - return "The volume does not consist of a single disk extent."; - case 0x80042441: // VDS_E_BAD_PROVIDER_DATA - return "A provider returned bad data."; - case 0x80042442: // VDS_E_PROVIDER_FAILURE - return "A provider failed to complete an operation."; - case 0x00042443: // VDS_S_VOLUME_COMPRESS_FAILED - return "The file system was formatted successfully but could not be compressed."; - case 0x80042444: // VDS_E_PACK_OFFLINE - return "The pack is offline."; - case 0x80042445: // VDS_E_VOLUME_NOT_A_MIRROR - return "The volume is not a mirror."; - case 0x80042446: // VDS_E_NO_EXTENTS_FOR_VOLUME - return "No extents were found for the volume."; - case 0x80042447: // VDS_E_DISK_NOT_LOADED_TO_CACHE - return "The migrated disk failed to load to the cache."; - case 0x80042448: // VDS_E_INTERNAL_ERROR - return "VDS encountered an internal error."; - case 0x8004244A: // VDS_E_PROVIDER_TYPE_NOT_SUPPORTED - return "The method call is not supported for the specified provider type."; - case 0x8004244B: // VDS_E_DISK_NOT_ONLINE - return "One or more of the specified disks are not online."; - case 0x8004244C: // VDS_E_DISK_IN_USE_BY_VOLUME - return "One or more extents of the disk are already being used by the volume."; - case 0x0004244D: // VDS_S_IN_PROGRESS - return "The asynchronous operation is in progress."; - case 0x8004244E: // VDS_E_ASYNC_OBJECT_FAILURE - return "Failure initializing the asynchronous object."; - case 0x8004244F: // VDS_E_VOLUME_NOT_MOUNTED - return "The volume is not mounted."; - case 0x80042450: // VDS_E_PACK_NOT_FOUND - return "The pack was not found."; - case 0x80042453: // VDS_E_OBJECT_OUT_OF_SYNC - return "The reference to the object might be stale."; - case 0x80042454: // VDS_E_MISSING_DISK - return "The specified disk could not be found."; - case 0x80042455: // VDS_E_DISK_PNP_REG_CORRUPT - return "The provider's list of PnP registered disks has become corrupted."; - case 0x80042457: // VDS_E_NO_DRIVELETTER_FLAG - return "The provider does not support the VDS_VF_NO DRIVELETTER volume flag."; - case 0x80042459: // VDS_E_REVERT_ON_CLOSE_SET - return "Some volume flags are already set."; - case 0x0004245B: // VDS_S_UNABLE_TO_GET_GPT_ATTRIBUTES - return "Unable to retrieve the GPT attributes for this volume."; - case 0x8004245C: // VDS_E_VOLUME_TEMPORARILY_DISMOUNTED - return "The volume is already dismounted temporarily."; - case 0x8004245D: // VDS_E_VOLUME_PERMANENTLY_DISMOUNTED - return "The volume is already permanently dismounted."; - case 0x8004245E: // VDS_E_VOLUME_HAS_PATH - return "The volume cannot be dismounted permanently because it still has an access path."; - case 0x8004245F: // VDS_E_TIMEOUT - return "The operation timed out."; - case 0x80042461: // VDS_E_LDM_TIMEOUT - return "The operation timed out in the LDMA service. Retry the operation."; - case 0x80042462: // VDS_E_REVERT_ON_CLOSE_MISMATCH - return "The flags to be cleared do not match the flags that were set previously."; - case 0x80042463: // VDS_E_RETRY - return "The operation failed. Retry the operation."; - case 0x80042464: // VDS_E_ONLINE_PACK_EXISTS - return "The operation failed, because an online pack object already exists."; - case 0x80042468: // VDS_E_MAX_USABLE_MBR - return "Only the first 2TB are usable on large MBR disks."; - case 0x80042500: // VDS_E_NO_SOFTWARE_PROVIDERS_LOADED - return "There are no software providers loaded."; - case 0x80042501: // VDS_E_DISK_NOT_MISSING - return "The disk is not missing."; - case 0x80042502: // VDS_E_NO_VOLUME_LAYOUT - return "The volume's layout could not be retrieved."; - case 0x80042503: // VDS_E_CORRUPT_VOLUME_INFO - return "The volume's driver information is corrupted."; - case 0x80042504: // VDS_E_INVALID_ENUMERATOR - return "The enumerator is corrupted"; - case 0x80042505: // VDS_E_DRIVER_INTERNAL_ERROR - return "An internal error occurred in the volume management driver."; - case 0x80042507: // VDS_E_VOLUME_INVALID_NAME - return "The volume name is not valid."; - case 0x00042508: // VDS_S_DISK_IS_MISSING - return "The disk is missing and not all information could be returned."; - case 0x80042509: // VDS_E_CORRUPT_PARTITION_INFO - return "The disk's partition information is corrupted."; - case 0x0004250A: // VDS_S_NONCONFORMANT_PARTITION_INFO - return "The disk's partition information does not conform to what is expected on a dynamic disk."; - case 0x8004250B: // VDS_E_CORRUPT_EXTENT_INFO - return "The disk's extent information is corrupted."; - case 0x0004250E: // VDS_S_SYSTEM_PARTITION - return "Warning: There was a failure while checking for the system partition."; - case 0x8004250F: // VDS_E_BAD_PNP_MESSAGE - return "The PNP service sent a corrupted notification to the provider."; - case 0x80042510: // VDS_E_NO_PNP_DISK_ARRIVE - case 0x80042511: // VDS_E_NO_PNP_VOLUME_ARRIVE - return "No disk/volume arrival notification was received."; - case 0x80042512: // VDS_E_NO_PNP_DISK_REMOVE - case 0x80042513: // VDS_E_NO_PNP_VOLUME_REMOVE - return "No disk/volume removal notification was received."; - case 0x80042514: // VDS_E_PROVIDER_EXITING - return "The provider is exiting."; - case 0x00042517: // VDS_S_NO_NOTIFICATION - return "No volume arrival notification was received."; - case 0x80042519: // VDS_E_INVALID_DISK - return "The specified disk is not valid."; - case 0x8004251A: // VDS_E_INVALID_PACK - return "The specified disk pack is not valid."; - case 0x8004251B: // VDS_E_VOLUME_ON_DISK - return "This operation is not allowed on disks with volumes."; - case 0x8004251C: // VDS_E_DRIVER_INVALID_PARAM - return "The driver returned an invalid parameter error."; - case 0x8004253D: // VDS_E_DRIVER_OBJECT_NOT_FOUND - return "The object was not found in the driver cache."; - case 0x8004253E: // VDS_E_PARTITION_NOT_CYLINDER_ALIGNED - return "The disk layout contains partitions which are not cylinder aligned."; - case 0x8004253F: // VDS_E_DISK_LAYOUT_PARTITIONS_TOO_SMALL - return "The disk layout contains partitions which are less than the minimum required size."; - case 0x80042540: // VDS_E_DISK_IO_FAILING - return "The I/O to the disk is failing."; - case 0x80042543: // VDS_E_GPT_ATTRIBUTES_INVALID - return "Invalid GPT attributes were specified."; - case 0x8004254D: // VDS_E_UNEXPECTED_DISK_LAYOUT_CHANGE - return "An unexpected layout change occurred external to the volume manager."; - case 0x8004254E: // VDS_E_INVALID_VOLUME_LENGTH - return "The volume length is invalid."; - case 0x8004254F: // VDS_E_VOLUME_LENGTH_NOT_SECTOR_SIZE_MULTIPLE - return "The volume length is not a multiple of the sector size."; - case 0x80042550: // VDS_E_VOLUME_NOT_RETAINED - return "The volume does not have a retained partition association."; - case 0x80042551: // VDS_E_VOLUME_RETAINED - return "The volume already has a retained partition association."; - case 0x80042553: // VDS_E_ALIGN_BEYOND_FIRST_CYLINDER - return "The specified alignment is beyond the first cylinder."; - case 0x80042554: // VDS_E_ALIGN_NOT_SECTOR_SIZE_MULTIPLE - return "The specified alignment is not a multiple of the sector size."; - case 0x80042555: // VDS_E_ALIGN_NOT_ZERO - return "The specified partition type cannot be created with a non-zero alignment."; - case 0x80042556: // VDS_E_CACHE_CORRUPT - return "The service's cache has become corrupt."; - case 0x80042557: // VDS_E_CANNOT_CLEAR_VOLUME_FLAG - return "The specified volume flag cannot be cleared."; - case 0x80042558: // VDS_E_DISK_BEING_CLEANED - return "The operation is not allowed on a disk that is in the process of being cleaned."; - case 0x8004255A: // VDS_E_DISK_REMOVEABLE - return "The operation is not supported on removable media."; - case 0x8004255B: // VDS_E_DISK_REMOVEABLE_NOT_EMPTY - return "The operation is not supported on a non-empty removable disk."; - case 0x8004255C: // VDS_E_DRIVE_LETTER_NOT_FREE - return "The specified drive letter is not free to be assigned."; - case 0x8004255E: // VDS_E_INVALID_DRIVE_LETTER - return "The specified drive letter is not valid."; - case 0x8004255F: // VDS_E_INVALID_DRIVE_LETTER_COUNT - return "The specified number of drive letters to retrieve is not valid."; - case 0x80042560: // VDS_E_INVALID_FS_FLAG - return "The specified file system flag is not valid."; - case 0x80042561: // VDS_E_INVALID_FS_TYPE - return "The specified file system is not valid."; - case 0x80042562: // VDS_E_INVALID_OBJECT_TYPE - return "The specified object type is not valid."; - case 0x80042563: // VDS_E_INVALID_PARTITION_LAYOUT - return "The specified partition layout is invalid."; - case 0x80042564: // VDS_E_INVALID_PARTITION_STYLE - return "VDS only supports MBR or GPT partition style disks."; - case 0x80042565: // VDS_E_INVALID_PARTITION_TYPE - return "The specified partition type is not valid for this operation."; - case 0x80042566: // VDS_E_INVALID_PROVIDER_CLSID - case 0x80042567: // VDS_E_INVALID_PROVIDER_ID - case 0x8004256A: // VDS_E_INVALID_PROVIDER_VERSION_GUID - return "A NULL GUID was passed to the provider."; - case 0x80042568: // VDS_E_INVALID_PROVIDER_NAME - return "The specified provider name is invalid."; - case 0x80042569: // VDS_E_INVALID_PROVIDER_TYPE - return "The specified provider type is invalid."; - case 0x8004256B: // VDS_E_INVALID_PROVIDER_VERSION_STRING - return "The specified provider version string is invalid."; - case 0x8004256C: // VDS_E_INVALID_QUERY_PROVIDER_FLAG - return "The specified query provider flag is invalid."; - case 0x8004256D: // VDS_E_INVALID_SERVICE_FLAG - return "The specified service flag is invalid."; - case 0x8004256E: // VDS_E_INVALID_VOLUME_FLAG - return "The specified volume flag is invalid."; - case 0x8004256F: // VDS_E_PARTITION_NOT_OEM - return "The operation is only supported on an OEM, ESP, or unknown partition."; - case 0x80042570: // VDS_E_PARTITION_PROTECTED - return "Cannot delete a protected partition without the force protected parameter set."; - case 0x80042571: // VDS_E_PARTITION_STYLE_MISMATCH - return "The specified partition style is not the same as the disk's partition style."; - case 0x80042572: // VDS_E_PROVIDER_INTERNAL_ERROR - return "An internal error has occurred in the provider."; - case 0x80042575: // VDS_E_UNRECOVERABLE_PROVIDER_ERROR - return "An unrecoverable error occurred in the provider."; - case 0x80042576: // VDS_E_VOLUME_HIDDEN - return "Cannot assign a mount point to a hidden volume."; - case 0x00042577: // VDS_S_DISMOUNT_FAILED - case 0x00042578: // VDS_S_REMOUNT_FAILED - return "Failed to dismount/remount the volume after setting the volume flags."; - case 0x80042579: // VDS_E_FLAG_ALREADY_SET - return "Cannot set the specified flag as revert-on-close because it is already set."; - case 0x8004257B: // VDS_E_DISTINCT_VOLUME - return "The input volume id cannot be the id of the volume that is the target of the operation."; - case 0x00042583: // VDS_S_FS_LOCK - return "Failed to obtain a file system lock."; - case 0x80042584: // VDS_E_READONLY - return "The volume is read only."; - case 0x80042585: // VDS_E_INVALID_VOLUME_TYPE - return "The volume type is invalid for this operation."; - case 0x80042588: // VDS_E_VOLUME_MIRRORED - return "This operation is not supported on a mirrored volume."; - case 0x80042589: // VDS_E_VOLUME_SIMPLE_SPANNED - return "The operation is only supported on simple or spanned volumes."; - case 0x8004258C: // VDS_E_PARTITION_MSR - case 0x8004258D: // VDS_E_PARTITION_LDM - return "The operation is not supported on this type of partitions."; - case 0x0004258E: // VDS_S_WINPE_BOOTENTRY - return "The boot entries cannot be updated automatically on WinPE."; - case 0x8004258F: // VDS_E_ALIGN_NOT_A_POWER_OF_TWO - return "The alignment is not a power of two."; - case 0x80042590: // VDS_E_ALIGN_IS_ZERO - return "The alignment is zero."; - case 0x80042593: // VDS_E_FS_NOT_DETERMINED - return "The default file system could not be determined."; - case 0x80042595: // VDS_E_DISK_NOT_OFFLINE - return "This disk is already online."; - case 0x80042596: // VDS_E_FAILED_TO_ONLINE_DISK - return "The online operation failed."; - case 0x80042597: // VDS_E_FAILED_TO_OFFLINE_DISK - return "The offline operation failed."; - case 0x80042598: // VDS_E_BAD_REVISION_NUMBER - return "The operation could not be completed because the specified revision number is not supported."; - case 0x00042700: // VDS_S_NAME_TRUNCATED - return "The name was set successfully but had to be truncated."; - case 0x80042701: // VDS_E_NAME_NOT_UNIQUE - return "The specified name is not unique."; - case 0x8004270F: // VDS_E_NO_DISK_PATHNAME - return "The disk's path could not be retrieved. Some operations on the disk might fail."; - case 0x80042711: // VDS_E_NO_VOLUME_PATHNAME - return "The path could not be retrieved for one or more volumes."; - case 0x80042712: // VDS_E_PROVIDER_CACHE_OUTOFSYNC - return "The provider's cache is not in sync with the driver cache."; - case 0x80042713: // VDS_E_NO_IMPORT_TARGET - return "No import target was set for the subsystem."; - case 0x00042714: // VDS_S_ALREADY_EXISTS - return "The object already exists."; - case 0x00042715: // VDS_S_PROPERTIES_INCOMPLETE - return "Some, but not all, of the properties were successfully retrieved."; - case 0x80042803: // VDS_E_UNABLE_TO_FIND_BOOT_DISK - return "Volume disk extent information could not be retrieved for the boot volume."; - case 0x80042807: // VDS_E_BOOT_DISK - return "Disk attributes cannot be changed on the boot disk."; - case 0x00042808: // VDS_S_DISK_MOUNT_FAILED - case 0x00042809: // VDS_S_DISK_DISMOUNT_FAILED - return "One or more of the volumes on the disk could not be mounted/dismounted."; - case 0x8004280A: // VDS_E_DISK_IS_OFFLINE - case 0x8004280B: // VDS_E_DISK_IS_READ_ONLY - return "The operation cannot be performed on a disk that is offline or read-only."; - case 0x8004280C: // VDS_E_PAGEFILE_DISK - case 0x8004280D: // VDS_E_HIBERNATION_FILE_DISK - case 0x8004280E: // VDS_E_CRASHDUMP_DISK - return "The operation cannot be performed on a disk that contains a pagefile, hibernation or crashdump volume."; - case 0x8004280F: // VDS_E_UNABLE_TO_FIND_SYSTEM_DISK - return "A system error occurred while retrieving the system disk information."; - case 0x80042810: // VDS_E_INCORRECT_SYSTEM_VOLUME_EXTENT_INFO - return "Multiple disk extents reported for the system volume - system error."; - case 0x80042811: // VDS_E_SYSTEM_DISK - return "Disk attributes cannot be changed on the current system disk or BIOS disk 0."; - case 0x80042823: // VDS_E_SECTOR_SIZE_ERROR - return "The sector size MUST be non-zero, a power of 2, and less than the maximum sector size."; - case 0x80042907: // VDS_E_SUBSYSTEM_ID_IS_NULL - return "The provider returned a NULL subsystem identification string."; - case 0x8004290C: // VDS_E_REBOOT_REQUIRED - return "A reboot is required before any further operations are initiated."; - case 0x8004290D: // VDS_E_VOLUME_GUID_PATHNAME_NOT_ALLOWED - return "Volume GUID pathnames are not valid input to this method."; - case 0x8004290E: // VDS_E_BOOT_PAGEFILE_DRIVE_LETTER - return "Assigning or removing drive letters on the current boot or pagefile volume is not allowed."; - case 0x8004290F: // VDS_E_DELETE_WITH_CRITICAL - return "Delete is not allowed on a critical volume."; - case 0x80042910: // VDS_E_CLEAN_WITH_DATA - case 0x80042911: // VDS_E_CLEAN_WITH_OEM - return "The FORCE parameter MUST be set to TRUE in order to clean a disk that contains a data or OEM volume."; - case 0x80042912: // VDS_E_CLEAN_WITH_CRITICAL - return "Clean is not allowed on a critical disk."; - case 0x80042913: // VDS_E_FORMAT_CRITICAL - return "Format is not allowed on a critical volume."; - case 0x80042914: // VDS_E_NTFS_FORMAT_NOT_SUPPORTED - case 0x80042915: // VDS_E_FAT32_FORMAT_NOT_SUPPORTED - case 0x80042916: // VDS_E_FAT_FORMAT_NOT_SUPPORTED - return "The requested file system format is not supported on this volume."; - case 0x80042917: // VDS_E_FORMAT_NOT_SUPPORTED - return "The volume is not formattable."; - case 0x80042918: // VDS_E_COMPRESSION_NOT_SUPPORTED - return "The specified file system does not support compression."; - default: - return NULL; - } -} - -static const char* GetVimError(DWORD error_code) -{ - switch (error_code) { - case 0xC1420127: - return "The specified image in the specified wim is already mounted for read and write access."; - default: - return NULL; - } -} - -// Convert a windows error to human readable string +// Convert a Windows error to human readable string +// One really has to wonder why the hell FormatMessage() was designed not to +// handle FORMAT_MESSAGE_FROM_HMODULE automatically according to the facility... const char *WindowsErrorString(void) { static char err_string[256] = { 0 }; DWORD size, presize; DWORD error_code, format_error; + HANDLE hModule = NULL; error_code = GetLastError(); - // Check for VDS error codes - if ((HRESULT_FACILITY(error_code) == FACILITY_ITF) && (GetVdsError(error_code) != NULL)) { - static_sprintf(err_string, "[0x%08lX] %s", error_code, GetVdsError(error_code)); - return err_string; - } - if ((HRESULT_FACILITY(error_code) == FACILITY_WIM) && (GetVimError(error_code) != NULL)) { - static_sprintf(err_string, "[0x%08lX] %s", error_code, GetVimError(error_code)); - return err_string; + // Check for specific facility error codes + switch (HRESULT_FACILITY(error_code)) { + case FACILITY_HTTP: + hModule = GetModuleHandleA("wininet.dll"); + break; + case FACILITY_ITF: + hModule = GetModuleHandleA("vdsutil.dll"); + break; + case FACILITY_WIM: + hModule = GetModuleHandleA("wimgapi.dll"); + break; + default: + break; } static_sprintf(err_string, "[0x%08lX] ", error_code); presize = (DWORD)strlen(err_string); - size = FormatMessageU(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, + size = FormatMessageU(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | + ((hModule != NULL) ? FORMAT_MESSAGE_FROM_HMODULE : 0), hModule, HRESULT_CODE(error_code), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &err_string[presize], (DWORD)(sizeof(err_string)-strlen(err_string)), NULL); if (size == 0) { format_error = GetLastError(); if ((format_error) && (format_error != ERROR_MR_MID_NOT_FOUND) && (format_error != ERROR_MUI_FILE_NOT_LOADED)) - static_sprintf(err_string, "Windows error code 0x%08lX (FormatMessage error code 0x%08lX)", + static_sprintf(err_string, "[0x%08lX] (FormatMessage error code 0x%08lX)", error_code, format_error); else - static_sprintf(err_string, "Windows error code 0x%08lX", error_code); + static_sprintf(err_string, "[0x%08lX] (No Windows Error String)", error_code); } else { // Microsoft may suffix CRLF to error messages, which we need to remove... assert(presize > 2);