From bcbf72ea9951cc0b0928a2e2b81e702a01f5aa94 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 4 Jun 2025 14:05:55 +0200 Subject: [PATCH 1/6] [winpr,path] fix windows unicode paths --- winpr/libwinpr/path/shell.c | 48 +++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/winpr/libwinpr/path/shell.c b/winpr/libwinpr/path/shell.c index 3f0422143..2a659f140 100644 --- a/winpr/libwinpr/path/shell.c +++ b/winpr/libwinpr/path/shell.c @@ -58,6 +58,24 @@ static char* GetPath_XDG_RUNTIME_DIR(void); * http://msdn.microsoft.com/en-us/library/windows/desktop/bb762188/ */ +#if defined(WIN32) && !defined(_UWP) + +static char* win_get_known_folder(REFKNOWNFOLDERID id, BOOL currentUser) +{ + WCHAR* wpath = NULL; + HANDLE handle = currentUser ? NULL : (HANDLE)-1; + if (FAILED(SHGetKnownFolderPath(id, 0, handle, &wpath))) + return NULL; + + if (!wpath) + return NULL; + + char* path = ConvertWCharToUtf8Alloc(wpath, NULL); + CoTaskMemFree(wpath); + return path; +} +#endif + /** * XDG Base Directory Specification: * http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html @@ -165,16 +183,8 @@ static char* GetPath_XDG_CONFIG_HOME(void) { char* path = NULL; #if defined(WIN32) && !defined(_UWP) - path = calloc(MAX_PATH, sizeof(char)); - if (!path) - return NULL; - - if (FAILED(SHGetFolderPathA(0, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, path))) - { - free(path); - return NULL; - } + path = win_get_known_folder(&FOLDERID_RoamingAppData, TRUE); #elif defined(__IOS__) path = ios_get_data(); @@ -222,13 +232,7 @@ static char* GetPath_SYSTEM_CONFIG_HOME(void) char* path = NULL; #if defined(WIN32) && !defined(_UWP) - WCHAR* wpath = NULL; - if (FAILED(SHGetKnownFolderPath(&FOLDERID_ProgramData, 0, (HANDLE)-1, &wpath))) - return NULL; - - if (wpath) - path = ConvertWCharToUtf8Alloc(wpath, NULL); - CoTaskMemFree(wpath); + path = win_get_known_folder(&FOLDERID_ProgramData, FALSE); #elif defined(__IOS__) path = ios_get_data(); @@ -250,7 +254,7 @@ static char* GetPath_XDG_CACHE_HOME(void) path = GetCombinedPath(home, "cache"); if (!winpr_PathFileExists(path)) - if (!CreateDirectoryA(path, NULL)) + if (!winpr_PathMakePath(path, NULL)) path = NULL; } @@ -297,16 +301,8 @@ char* GetPath_XDG_RUNTIME_DIR(void) { char* path = NULL; #if defined(WIN32) && !defined(_UWP) - path = calloc(MAX_PATH, sizeof(char)); - if (!path) - return NULL; - - if (FAILED(SHGetFolderPathA(0, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, path))) - { - free(path); - return NULL; - } + path = win_get_known_folder(&FOLDERID_LocalAppData, TRUE); #else /** From f1fa7b56c21134ac7f209c6903d947d44719693e Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 4 Jun 2025 13:35:28 +0200 Subject: [PATCH 2/6] [winpr,file] add GetLogicalDriveStrings[A|W] --- winpr/include/winpr/file.h | 10 ++++++---- winpr/libwinpr/file/file.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/winpr/include/winpr/file.h b/winpr/include/winpr/file.h index 3c7466c81..ec6dd4b5c 100644 --- a/winpr/include/winpr/file.h +++ b/winpr/include/winpr/file.h @@ -461,6 +461,12 @@ typedef struct WINPR_API BOOL ValidFileNameComponent(LPCWSTR lpFileName); +#if defined(_UWP) || !defined(_WIN32) +WINPR_API DWORD GetLogicalDriveStringsA(DWORD nBufferLength, LPSTR lpBuffer); + +WINPR_API DWORD GetLogicalDriveStringsW(DWORD nBufferLength, LPWSTR lpBuffer); +#endif + #ifdef _UWP #ifdef __cplusplus @@ -497,10 +503,6 @@ extern "C" LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters); - WINPR_API DWORD GetLogicalDriveStringsA(DWORD nBufferLength, LPSTR lpBuffer); - - WINPR_API DWORD GetLogicalDriveStringsW(DWORD nBufferLength, LPWSTR lpBuffer); - WINPR_API BOOL PathIsDirectoryEmptyA(LPCSTR pszPath); WINPR_API UINT GetACP(void); diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c index 755ecce87..7fc3da5e9 100644 --- a/winpr/libwinpr/file/file.c +++ b/winpr/libwinpr/file/file.c @@ -1585,3 +1585,37 @@ cleanup: return result; #endif } + +#if !defined(_UWP) && !defined(_WIN32) +DWORD GetLogicalDriveStringsW(DWORD nBufferLength, LPWSTR lpBuffer) +{ + char* buffer = NULL; + if (nBufferLength > 0) + { + buffer = calloc(nBufferLength, sizeof(char)); + if (!buffer) + return 0; + } + + const DWORD rc = GetLogicalDriveStringsA(nBufferLength, buffer); + if (buffer) + ConvertMszUtf8NToWChar(buffer, rc, lpBuffer, nBufferLength); + free(buffer); + return rc; +} + +DWORD GetLogicalDriveStringsA(DWORD nBufferLength, LPSTR lpBuffer) +{ + /* format is '\0\0...\0\0' + * for details see + * https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getlogicaldrivestringsa + */ + const char path[] = "/\0"; + const size_t len = sizeof(path); + if (nBufferLength < len) + return WINPR_ASSERTING_INT_CAST(DWORD, len); + + memcpy(lpBuffer, path, len); + return len - 1; +} +#endif From abbb998dca04766360c8301bb4867116b8ede36a Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 4 Jun 2025 13:35:55 +0200 Subject: [PATCH 3/6] [channels,drive] unify drive redirection handling --- channels/drive/client/drive_main.c | 154 ++++++++++++++--------------- 1 file changed, 75 insertions(+), 79 deletions(-) diff --git a/channels/drive/client/drive_main.c b/channels/drive/client/drive_main.c index d3f3f9940..6b2467199 100644 --- a/channels/drive/client/drive_main.c +++ b/channels/drive/client/drive_main.c @@ -1060,6 +1060,76 @@ out_error: return error; } +static BOOL drive_filtered(const WCHAR* drive) +{ + const WCHAR a[] = { 'A', '\0' }; + const WCHAR b[] = { 'B', '\0' }; + const WCHAR la[] = { 'a', '\0' }; + const WCHAR lb[] = { 'b', '\0' }; + const WCHAR* list[] = { a, b, la, lb }; + + for (size_t x = 0; x < ARRAYSIZE(list); x++) + { + const WCHAR* cur = list[x]; + if (_wcsncmp(drive, cur, 2) == 0) + return TRUE; + } + return FALSE; +} + +static UINT handle_all_drives(RDPDR_DRIVE* drive, PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) +{ + UINT error = ERROR_INTERNAL_ERROR; + + WINPR_ASSERT(drive); + WINPR_ASSERT(pEntryPoints); + + /* Enumerate all devices: */ + const DWORD dlen = GetLogicalDriveStringsW(0, NULL); + + WCHAR* devlist = calloc(dlen, sizeof(WCHAR)); + if (!devlist) + return ERROR_OUTOFMEMORY; + + const DWORD rc = GetLogicalDriveStringsW(dlen, devlist); + if (rc >= dlen) + goto fail; + + size_t len = 0; + for (size_t offset = 0; offset < rc; offset += len + 1) + { + len = _wcsnlen(&devlist[offset], rc - offset); + + const WCHAR* dev = &devlist[offset]; + if (!drive_filtered(dev)) + { + char* bufdup = NULL; + char* devdup = ConvertWCharNToUtf8Alloc(dev, len, NULL); + if (!devdup) + { + error = ERROR_OUTOFMEMORY; + goto fail; + } + size_t size = 0; + winpr_asprintf(&bufdup, &size, "%s_%s", drive->device.Name, devdup); + + error = + drive_register_drive_path(pEntryPoints, bufdup, devdup, TRUE, &drive->device.Id); + free(devdup); + free(bufdup); + if (error != CHANNEL_RC_OK) + goto fail; + } + } + + error = CHANNEL_RC_OK; + +fail: + free(devlist); + + return error; +} + /** * Function description * @@ -1069,32 +1139,19 @@ FREERDP_ENTRY_POINT( UINT VCAPITYPE drive_DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)) { UINT error = 0; -#ifdef WIN32 - int len; - char devlist[512], buf[512]; - char* bufdup; - char* devdup; -#endif WINPR_ASSERT(pEntryPoints); RDPDR_DRIVE* drive = (RDPDR_DRIVE*)pEntryPoints->device; WINPR_ASSERT(drive); -#ifndef WIN32 - if (strcmp(drive->Path, "*") == 0) + const char all[] = "*"; + const char home[] = "%"; + if (strncmp(drive->Path, all, sizeof(all)) == 0) { - /* all drives */ - free(drive->Path); - drive->Path = _strdup("/"); - - if (!drive->Path) - { - WLog_ERR(TAG, "_strdup failed!"); - return CHANNEL_RC_NO_MEMORY; - } + error = handle_all_drives(drive, pEntryPoints); } - else if (strcmp(drive->Path, "%") == 0) + else if (strncmp(drive->Path, home, sizeof(home)) == 0) { free(drive->Path); drive->Path = GetKnownPath(KNOWN_PATH_HOME); @@ -1104,74 +1161,13 @@ FREERDP_ENTRY_POINT( WLog_ERR(TAG, "_strdup failed!"); return CHANNEL_RC_NO_MEMORY; } - } - - error = drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path, - drive->automount, &drive->device.Id); -#else - /* Special case: path[0] == '*' -> export all drives */ - /* Special case: path[0] == '%' -> user home dir */ - if (strcmp(drive->Path, "%") == 0) - { - GetEnvironmentVariableA("USERPROFILE", buf, sizeof(buf)); - PathCchAddBackslashA(buf, sizeof(buf)); - free(drive->Path); - drive->Path = _strdup(buf); - - if (!drive->Path) - { - WLog_ERR(TAG, "_strdup failed!"); - return CHANNEL_RC_NO_MEMORY; - } - error = drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path, drive->automount, &drive->device.Id); } - else if (strcmp(drive->Path, "*") == 0) - { - /* Enumerate all devices: */ - GetLogicalDriveStringsA(sizeof(devlist) - 1, devlist); - - for (size_t i = 0;; i++) - { - char* dev = &devlist[i * 4]; - if (!*dev) - break; - if (*dev > 'B') - { - /* Suppress disk drives A and B to avoid pesty messages */ - len = sprintf_s(buf, sizeof(buf) - 4, "%s", drive->device.Name); - buf[len] = '_'; - buf[len + 1] = dev[0]; - buf[len + 2] = 0; - buf[len + 3] = 0; - - if (!(bufdup = _strdup(buf))) - { - WLog_ERR(TAG, "_strdup failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - if (!(devdup = _strdup(dev))) - { - WLog_ERR(TAG, "_strdup failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - if ((error = drive_register_drive_path(pEntryPoints, bufdup, devdup, TRUE, - &drive->device.Id))) - { - break; - } - } - } - } else { error = drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path, drive->automount, &drive->device.Id); } - -#endif return error; } From b5b258c9f424673d6670e05add63d84430bcb461 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 4 Jun 2025 14:20:37 +0200 Subject: [PATCH 4/6] [winpr,path] fix NULL arguments for DeleteFile --- server/shadow/shadow_server.c | 2 +- winpr/libwinpr/path/shell.c | 14 ++++++-------- winpr/tools/makecert/makecert.c | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/server/shadow/shadow_server.c b/server/shadow/shadow_server.c index 9cbddb017..29765737b 100644 --- a/server/shadow/shadow_server.c +++ b/server/shadow/shadow_server.c @@ -914,7 +914,7 @@ static BOOL shadow_server_init_certificate(rdpShadowServer* server) if (!winpr_PathFileExists(filepath) && !winpr_PathMakePath(filepath, 0)) { - if (!CreateDirectoryA(filepath, 0)) + if (!winpr_PathMakePath(filepath, NULL)) { WLog_ERR(TAG, "Failed to create directory '%s'", filepath); goto out_fail; diff --git a/winpr/libwinpr/path/shell.c b/winpr/libwinpr/path/shell.c index 2a659f140..db8aeccc4 100644 --- a/winpr/libwinpr/path/shell.c +++ b/winpr/libwinpr/path/shell.c @@ -760,11 +760,10 @@ BOOL winpr_DeleteFile(const char* lpFileName) BOOL result = FALSE; if (lpFileName) - { lpFileNameW = ConvertUtf8ToWCharAlloc(lpFileName, NULL); - if (!lpFileNameW) - goto cleanup; - } + + if (!lpFileNameW) + goto cleanup; result = DeleteFileW(lpFileNameW); @@ -783,11 +782,10 @@ BOOL winpr_RemoveDirectory(LPCSTR lpPathName) BOOL result = FALSE; if (lpPathName) - { lpPathNameW = ConvertUtf8ToWCharAlloc(lpPathName, NULL); - if (!lpPathNameW) - goto cleanup; - } + + if (!lpPathNameW) + goto cleanup; result = RemoveDirectoryW(lpPathNameW); diff --git a/winpr/tools/makecert/makecert.c b/winpr/tools/makecert/makecert.c index ac3555d76..15a2d16c8 100644 --- a/winpr/tools/makecert/makecert.c +++ b/winpr/tools/makecert/makecert.c @@ -1102,7 +1102,7 @@ int makecert_context_process(MAKECERT_CONTEXT* context, int argc, char** argv) { if (!winpr_PathFileExists(context->output_path)) { - if (!CreateDirectoryA(context->output_path, NULL)) + if (!winpr_PathMakePath(context->output_path, NULL)) return -1; } From 84691cf8810dcabd72a18ae24016e885bc9d5e0b Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 4 Jun 2025 14:31:08 +0200 Subject: [PATCH 5/6] [cmake] set MSVC utf-8 source encoding --- cmake/CompilerFlags.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmake/CompilerFlags.cmake b/cmake/CompilerFlags.cmake index af814c2fd..e9f2cd0a7 100644 --- a/cmake/CompilerFlags.cmake +++ b/cmake/CompilerFlags.cmake @@ -41,6 +41,10 @@ if(ANDROID) endif() endif() +# Assume source files are utf-8 when compiling with MSVC +add_compile_options("$<$:/utf-8>") +add_compile_options("$<$:/utf-8>") + set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} CACHE STRING "default CFLAGS") message("Using CFLAGS ${CMAKE_C_FLAGS}") message("Using CFLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE}") From 07e39ede20bb10185351a980fda7019645ddd038 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 4 Jun 2025 15:56:01 +0200 Subject: [PATCH 6/6] [winpr,file] Add winpr_CreateFile wrapper Allows creation of a file HANDLE from a utf-8 name --- channels/printer/client/printer_main.c | 5 +- channels/serial/client/serial_main.c | 8 +- libfreerdp/core/test/TestStreamDump.c | 2 +- winpr/include/winpr/file.h | 29 +++++-- winpr/libwinpr/file/generic.c | 83 ++++++++----------- winpr/libwinpr/file/test/TestFileDeleteFile.c | 5 +- .../file/test/TestFileFindFirstFile.c | 2 +- .../file/test/TestSetFileAttributes.c | 2 +- winpr/libwinpr/path/shell.c | 70 ++++++++++------ 9 files changed, 110 insertions(+), 96 deletions(-) diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c index a98ea2655..3449e7818 100644 --- a/channels/printer/client/printer_main.c +++ b/channels/printer/client/printer_main.c @@ -113,7 +113,8 @@ static BOOL printer_write_setting(const char* path, prn_conf_t type, const void* return FALSE; } - file = CreateFileA(abs, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + file = + winpr_CreateFile(abs, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); free(abs); if (file == INVALID_HANDLE_VALUE) @@ -177,7 +178,7 @@ static BOOL printer_read_setting(const char* path, prn_conf_t type, void** data, return FALSE; HANDLE file = - CreateFileA(abs, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + winpr_CreateFile(abs, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); free(abs); if (file == INVALID_HANDLE_VALUE) diff --git a/channels/serial/client/serial_main.c b/channels/serial/client/serial_main.c index da82ae025..b3012c620 100644 --- a/channels/serial/client/serial_main.c +++ b/channels/serial/client/serial_main.c @@ -165,10 +165,10 @@ static UINT serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp) SharedAccess = 0; CreateDisposition = OPEN_EXISTING; #endif - serial->hComm = - CreateFile(serial->device.name, DesiredAccess, SharedAccess, NULL, /* SecurityAttributes */ - CreateDisposition, 0, /* FlagsAndAttributes */ - NULL); /* TemplateFile */ + serial->hComm = winpr_CreateFile(serial->device.name, DesiredAccess, SharedAccess, + NULL, /* SecurityAttributes */ + CreateDisposition, 0, /* FlagsAndAttributes */ + NULL); /* TemplateFile */ if (!serial->hComm || (serial->hComm == INVALID_HANDLE_VALUE)) { diff --git a/libfreerdp/core/test/TestStreamDump.c b/libfreerdp/core/test/TestStreamDump.c index b54cae9e3..047cca2a1 100644 --- a/libfreerdp/core/test/TestStreamDump.c +++ b/libfreerdp/core/test/TestStreamDump.c @@ -87,7 +87,7 @@ fail: if (fp) (void)fclose(fp); if (name) - DeleteFileA(name); + winpr_DeleteFile(name); free(name); (void)fprintf(stderr, "xxxxxxxxxxxxx %d\n", rc); return rc; diff --git a/winpr/include/winpr/file.h b/winpr/include/winpr/file.h index ec6dd4b5c..53100e447 100644 --- a/winpr/include/winpr/file.h +++ b/winpr/include/winpr/file.h @@ -264,10 +264,17 @@ extern "C" #endif WINPR_ATTR_MALLOC(CloseHandle, 1) - WINPR_API HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, - DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, - HANDLE hTemplateFile); + WINPR_API HANDLE winpr_CreateFile(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile); + + WINPR_DEPRECATED_VAR("since 3.16.0, Use winpr_CreateFile", + WINPR_ATTR_MALLOC(CloseHandle, 1) WINPR_API HANDLE CreateFileA( + LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile)); WINPR_ATTR_MALLOC(CloseHandle, 1) WINPR_API HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, @@ -275,7 +282,8 @@ extern "C" DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); - WINPR_API BOOL DeleteFileA(LPCSTR lpFileName); + WINPR_DEPRECATED_VAR("since 3.16.0, Use winpr_DeleteFile", + WINPR_API BOOL DeleteFileA(LPCSTR lpFileName)); WINPR_API BOOL DeleteFileW(LPCWSTR lpFileName); @@ -386,7 +394,9 @@ extern "C" WINPR_API BOOL CreateDirectoryA(LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes); WINPR_API BOOL CreateDirectoryW(LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes); - WINPR_API BOOL RemoveDirectoryA(LPCSTR lpPathName); + WINPR_DEPRECATED_VAR("since 3.16.0, Use winpr_RemoveDirectory", + WINPR_API BOOL RemoveDirectoryA(LPCSTR lpPathName)); + WINPR_API BOOL RemoveDirectoryW(LPCWSTR lpPathName); WINPR_API HANDLE GetStdHandle(DWORD nStdHandle); @@ -401,11 +411,14 @@ extern "C" LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters); - WINPR_API BOOL MoveFileExA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags); + WINPR_DEPRECATED_VAR("since 3.16.0, Use winpr_MoveFileEx", + WINPR_API BOOL MoveFileExA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, + DWORD dwFlags)); WINPR_API BOOL MoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags); - WINPR_API BOOL MoveFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName); + WINPR_DEPRECATED_VAR("since 3.16.0, Use winpr_MoveFile", + WINPR_API BOOL MoveFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName)); WINPR_API BOOL MoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName); diff --git a/winpr/libwinpr/file/generic.c b/winpr/libwinpr/file/generic.c index 7c730b84f..03f360810 100644 --- a/winpr/libwinpr/file/generic.c +++ b/winpr/libwinpr/file/generic.c @@ -230,6 +230,14 @@ int InstallAioSignalHandler() HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) +{ + return winpr_CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, + dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); +} + +HANDLE winpr_CreateFile(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { if (!lpFileName) return INVALID_HANDLE_VALUE; @@ -281,8 +289,8 @@ HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, goto fail; } - hdl = CreateFileA(lpFileNameA, dwDesiredAccess, dwShareMode, lpSecurityAttributes, - dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); + hdl = winpr_CreateFile(lpFileNameA, dwDesiredAccess, dwShareMode, lpSecurityAttributes, + dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); fail: free(lpFileNameA); return hdl; @@ -290,9 +298,7 @@ fail: BOOL DeleteFileA(LPCSTR lpFileName) { - int status = 0; - status = unlink(lpFileName); - return (status != -1) ? TRUE : FALSE; + return winpr_DeleteFile(lpFileName); } BOOL DeleteFileW(LPCWSTR lpFileName) @@ -300,13 +306,7 @@ BOOL DeleteFileW(LPCWSTR lpFileName) if (!lpFileName) return FALSE; LPSTR lpFileNameA = ConvertWCharToUtf8Alloc(lpFileName, NULL); - BOOL rc = FALSE; - - if (!lpFileNameA) - goto fail; - - rc = DeleteFileA(lpFileNameA); -fail: + BOOL rc = winpr_DeleteFile(lpFileNameA); free(lpFileNameA); return rc; } @@ -1254,14 +1254,7 @@ fail: BOOL RemoveDirectoryA(LPCSTR lpPathName) { - int ret = rmdir(lpPathName); - - if (ret != 0) - SetLastError(map_posix_err(errno)); - else - SetLastError(STATUS_SUCCESS); - - return ret == 0; + return winpr_RemoveDirectory(lpPathName); } BOOL RemoveDirectoryW(LPCWSTR lpPathName) @@ -1277,7 +1270,7 @@ BOOL RemoveDirectoryW(LPCWSTR lpPathName) goto fail; } - ret = RemoveDirectoryA(utfPathName); + ret = winpr_RemoveDirectory(utfPathName); fail: free(utfPathName); return ret; @@ -1285,33 +1278,7 @@ fail: BOOL MoveFileExA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags) { - struct stat st; - int ret = 0; - ret = stat(lpNewFileName, &st); - - if ((dwFlags & MOVEFILE_REPLACE_EXISTING) == 0) - { - if (ret == 0) - { - SetLastError(ERROR_ALREADY_EXISTS); - return FALSE; - } - } - else - { - if (ret == 0 && (st.st_mode & S_IWUSR) == 0) - { - SetLastError(ERROR_ACCESS_DENIED); - return FALSE; - } - } - - ret = rename(lpExistingFileName, lpNewFileName); - - if (ret != 0) - SetLastError(map_posix_err(errno)); - - return ret == 0; + return winpr_MoveFileEx(lpExistingFileName, lpNewFileName, dwFlags); } BOOL MoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags) @@ -1329,7 +1296,7 @@ BOOL MoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlag goto fail; } - ret = MoveFileExA(lpCExistingFileName, lpCNewFileName, dwFlags); + ret = winpr_MoveFileEx(lpCExistingFileName, lpCNewFileName, dwFlags); fail: free(lpCNewFileName); free(lpCExistingFileName); @@ -1338,7 +1305,7 @@ fail: BOOL MoveFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName) { - return MoveFileExA(lpExistingFileName, lpNewFileName, 0); + return winpr_MoveFileEx(lpExistingFileName, lpNewFileName, 0); } BOOL MoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName) @@ -1385,3 +1352,19 @@ int UnixChangeFileMode(const char* filename, int flags) return rc; #endif } + +#if defined(_WIN32) || defined(_UWP) +HANDLE winpr_CreateFile(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) +{ + char* filename = ConvertUtf8ToWCharAlloc(lpFileName, NULL); + if (!filename) + return NULL; + + HANDLE hdl = CreateFileW(filename, dwDesiredAccess, dwShareMode, lpSecurityAttributes, + dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); + free(filename); + return hdl; +} +#endif diff --git a/winpr/libwinpr/file/test/TestFileDeleteFile.c b/winpr/libwinpr/file/test/TestFileDeleteFile.c index 40649dba5..7448ae3df 100644 --- a/winpr/libwinpr/file/test/TestFileDeleteFile.c +++ b/winpr/libwinpr/file/test/TestFileDeleteFile.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #if !defined(_WIN32) @@ -36,7 +37,7 @@ int TestFileDeleteFile(int argc, char* argv[]) WINPR_UNUSED(argc); WINPR_UNUSED(argv); - rc = DeleteFileA(invalidA); + rc = winpr_DeleteFile(invalidA); if (rc) return -1; @@ -48,7 +49,7 @@ int TestFileDeleteFile(int argc, char* argv[]) if (fd < 0) return -1; - rc = DeleteFileA(validA); + rc = winpr_DeleteFile(validA); if (!rc) return -1; diff --git a/winpr/libwinpr/file/test/TestFileFindFirstFile.c b/winpr/libwinpr/file/test/TestFileFindFirstFile.c index 2be310853..049b6ba4b 100644 --- a/winpr/libwinpr/file/test/TestFileFindFirstFile.c +++ b/winpr/libwinpr/file/test/TestFileFindFirstFile.c @@ -248,7 +248,7 @@ static int TestFileFindFirstFileA(const char* str) rc = 0; fail: - DeleteFileA(FilePath); + winpr_DeleteFile(FilePath); cleanup_layout(BasePath); ArrayList_Free(files); return rc; diff --git a/winpr/libwinpr/file/test/TestSetFileAttributes.c b/winpr/libwinpr/file/test/TestSetFileAttributes.c index b00c2ce1a..84a5b12f5 100644 --- a/winpr/libwinpr/file/test/TestSetFileAttributes.c +++ b/winpr/libwinpr/file/test/TestSetFileAttributes.c @@ -78,7 +78,7 @@ static BOOL test_SetFileAttributesA(void) rc = TRUE; fail: - DeleteFileA(name); + winpr_DeleteFile(name); free(name); return rc; } diff --git a/winpr/libwinpr/path/shell.c b/winpr/libwinpr/path/shell.c index db8aeccc4..5ea37c0fd 100644 --- a/winpr/libwinpr/path/shell.c +++ b/winpr/libwinpr/path/shell.c @@ -35,6 +35,8 @@ #include #include +#include "../file/file.h" + #include "../log.h" #define TAG WINPR_TAG("path.shell") @@ -697,36 +699,39 @@ fail: BOOL winpr_MoveFile(LPCSTR lpExistingFileName, LPCSTR lpNewFileName) { -#ifndef _WIN32 - return MoveFileA(lpExistingFileName, lpNewFileName); -#else - BOOL result = FALSE; - LPWSTR lpExistingFileNameW = NULL; - LPWSTR lpNewFileNameW = NULL; - - if (!lpExistingFileName || !lpNewFileName) - return FALSE; - - lpExistingFileNameW = ConvertUtf8ToWCharAlloc(lpExistingFileName, NULL); - if (!lpExistingFileNameW) - goto cleanup; - lpNewFileNameW = ConvertUtf8ToWCharAlloc(lpNewFileName, NULL); - if (!lpNewFileNameW) - goto cleanup; - - result = MoveFileW(lpExistingFileNameW, lpNewFileNameW); - -cleanup: - free(lpExistingFileNameW); - free(lpNewFileNameW); - return result; -#endif + return winpr_MoveFileEx(lpExistingFileName, lpNewFileName, 0); } BOOL winpr_MoveFileEx(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags) { #ifndef _WIN32 - return MoveFileExA(lpExistingFileName, lpNewFileName, dwFlags); + struct stat st; + int ret = 0; + ret = stat(lpNewFileName, &st); + + if ((dwFlags & MOVEFILE_REPLACE_EXISTING) == 0) + { + if (ret == 0) + { + SetLastError(ERROR_ALREADY_EXISTS); + return FALSE; + } + } + else + { + if (ret == 0 && (st.st_mode & S_IWUSR) == 0) + { + SetLastError(ERROR_ACCESS_DENIED); + return FALSE; + } + } + + ret = rename(lpExistingFileName, lpNewFileName); + + if (ret != 0) + SetLastError(map_posix_err(errno)); + + return ret == 0; #else BOOL result = FALSE; LPWSTR lpExistingFileNameW = NULL; @@ -754,7 +759,11 @@ cleanup: BOOL winpr_DeleteFile(const char* lpFileName) { #ifndef _WIN32 - return DeleteFileA(lpFileName); + if (!lpFileName) + return FALSE; + + const int status = unlink(lpFileName); + return (status != -1) ? TRUE : FALSE; #else LPWSTR lpFileNameW = NULL; BOOL result = FALSE; @@ -776,7 +785,14 @@ cleanup: BOOL winpr_RemoveDirectory(LPCSTR lpPathName) { #ifndef _WIN32 - return RemoveDirectoryA(lpPathName); + int ret = rmdir(lpPathName); + + if (ret != 0) + SetLastError(map_posix_err(errno)); + else + SetLastError(STATUS_SUCCESS); + + return ret == 0; #else LPWSTR lpPathNameW = NULL; BOOL result = FALSE;