Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/kernel32/tests/volume.c | 79 ++++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 16 deletions(-)
diff --git a/dlls/kernel32/tests/volume.c b/dlls/kernel32/tests/volume.c index 348ce1a76c5..5fa8a9f05de 100644 --- a/dlls/kernel32/tests/volume.c +++ b/dlls/kernel32/tests/volume.c @@ -24,6 +24,7 @@ #include "ntddstor.h" #include <stdio.h> #include "ddk/ntddcdvd.h" +#include "ddk/mountmgr.h"
#include <pshpack1.h> struct COMPLETE_DVD_LAYER_DESCRIPTOR @@ -105,11 +106,12 @@ static void test_query_dos_deviceA(void) HeapFree( GetProcessHeap(), 0, buffer ); }
-static void test_define_dos_deviceA(void) +static void test_dos_devices(void) { + char buf[MAX_PATH], buf2[400]; char drivestr[3]; - char buf[MAX_PATH]; - DWORD ret; + HANDLE file; + BOOL ret;
/* Find an unused drive letter */ drivestr[1] = ':'; @@ -123,20 +125,65 @@ static void test_define_dos_deviceA(void) return; }
- /* Map it to point to the current directory */ - ret = GetCurrentDirectoryA(sizeof(buf), buf); - ok(ret, "GetCurrentDir\n"); + ret = DefineDosDeviceA( 0, drivestr, "C:/windows/" ); + todo_wine ok(ret, "failed to define drive %s, error %u\n", drivestr, GetLastError());
- ret = DefineDosDeviceA(0, drivestr, buf); - todo_wine - ok(ret, "Could not make drive %s point to %s!\n", drivestr, buf); + ret = QueryDosDeviceA( drivestr, buf, sizeof(buf) ); + todo_wine ok(ret, "failed to query drive %s, error %u\n", drivestr, GetLastError()); + todo_wine ok(!strcmp(buf, "\??\C:\windows\"), "got path %s\n", debugstr_a(buf));
- if (!ret) { - skip("can't test removing fake drive\n"); - } else { - ret = DefineDosDeviceA(DDD_REMOVE_DEFINITION, drivestr, NULL); - ok(ret, "Could not remove fake drive %s!\n", drivestr); - } + sprintf(buf, "%s/system32", drivestr); + file = CreateFileA( buf, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL ); + todo_wine ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError()); + CloseHandle( file ); + + /* but it's not a volume mount point */ + + sprintf(buf, "%s\", drivestr); + ret = GetVolumeNameForVolumeMountPointA( buf, buf2, sizeof(buf2) ); + ok(!ret, "expected failure\n"); + todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError()); + + ret = DefineDosDeviceA(DDD_REMOVE_DEFINITION, drivestr, NULL); + todo_wine ok(ret, "failed to remove drive %s, error %u\n", drivestr, GetLastError()); + + ret = QueryDosDeviceA( drivestr, buf, sizeof(buf) ); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_FILE_NOT_FOUND, "got error %u\n", GetLastError()); + + sprintf(buf, "%s/system32", drivestr); + file = CreateFileA( buf, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL ); + ok(file == INVALID_HANDLE_VALUE, "expected failure\n"); + todo_wine ok(GetLastError() == ERROR_PATH_NOT_FOUND, "got error %u\n", GetLastError()); + + /* try with DDD_RAW_TARGET_PATH */ + + ret = DefineDosDeviceA( DDD_RAW_TARGET_PATH, drivestr, "\??\C:\windows\" ); + ok(ret, "failed to define drive %s, error %u\n", drivestr, GetLastError()); + + ret = QueryDosDeviceA( drivestr, buf, sizeof(buf) ); + todo_wine ok(ret, "failed to query drive %s, error %u\n", drivestr, GetLastError()); + todo_wine ok(!strcmp(buf, "\??\C:\windows\"), "got path %s\n", debugstr_a(buf)); + + sprintf(buf, "%s/system32", drivestr); + file = CreateFileA( buf, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL ); + todo_wine ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError()); + CloseHandle( file ); + + sprintf(buf, "%s\", drivestr); + ret = GetVolumeNameForVolumeMountPointA( buf, buf2, sizeof(buf2) ); + ok(!ret, "expected failure\n"); + todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError()); + + ret = DefineDosDeviceA(DDD_REMOVE_DEFINITION, drivestr, NULL); + ok(ret, "failed to remove drive %s, error %u\n", drivestr, GetLastError()); + + ret = QueryDosDeviceA( drivestr, buf, sizeof(buf) ); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_FILE_NOT_FOUND, "got error %u\n", GetLastError()); }
static void test_FindFirstVolume(void) @@ -1272,7 +1319,7 @@ START_TEST(volume) pGetVolumePathNamesForVolumeNameW = (void *) GetProcAddress(hdll, "GetVolumePathNamesForVolumeNameW");
test_query_dos_deviceA(); - test_define_dos_deviceA(); + test_dos_devices(); test_FindFirstVolume(); test_GetVolumePathNameA(); test_GetVolumePathNameW();
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- Note that opening files is currently broken, but, as tests show, it never worked in the first place.
dlls/kernel32/tests/volume.c | 12 ++-- dlls/kernel32/volume.c | 105 ++++++++++------------------------- 2 files changed, 36 insertions(+), 81 deletions(-)
diff --git a/dlls/kernel32/tests/volume.c b/dlls/kernel32/tests/volume.c index 5fa8a9f05de..b9121a4af4c 100644 --- a/dlls/kernel32/tests/volume.c +++ b/dlls/kernel32/tests/volume.c @@ -126,11 +126,11 @@ static void test_dos_devices(void) }
ret = DefineDosDeviceA( 0, drivestr, "C:/windows/" ); - todo_wine ok(ret, "failed to define drive %s, error %u\n", drivestr, GetLastError()); + ok(ret, "failed to define drive %s, error %u\n", drivestr, GetLastError());
ret = QueryDosDeviceA( drivestr, buf, sizeof(buf) ); - todo_wine ok(ret, "failed to query drive %s, error %u\n", drivestr, GetLastError()); - todo_wine ok(!strcmp(buf, "\??\C:\windows\"), "got path %s\n", debugstr_a(buf)); + ok(ret, "failed to query drive %s, error %u\n", drivestr, GetLastError()); + ok(!strcmp(buf, "\??\C:\windows\"), "got path %s\n", debugstr_a(buf));
sprintf(buf, "%s/system32", drivestr); file = CreateFileA( buf, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, @@ -146,7 +146,7 @@ static void test_dos_devices(void) todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError());
ret = DefineDosDeviceA(DDD_REMOVE_DEFINITION, drivestr, NULL); - todo_wine ok(ret, "failed to remove drive %s, error %u\n", drivestr, GetLastError()); + ok(ret, "failed to remove drive %s, error %u\n", drivestr, GetLastError());
ret = QueryDosDeviceA( drivestr, buf, sizeof(buf) ); ok(!ret, "expected failure\n"); @@ -164,8 +164,8 @@ static void test_dos_devices(void) ok(ret, "failed to define drive %s, error %u\n", drivestr, GetLastError());
ret = QueryDosDeviceA( drivestr, buf, sizeof(buf) ); - todo_wine ok(ret, "failed to query drive %s, error %u\n", drivestr, GetLastError()); - todo_wine ok(!strcmp(buf, "\??\C:\windows\"), "got path %s\n", debugstr_a(buf)); + ok(ret, "failed to query drive %s, error %u\n", drivestr, GetLastError()); + ok(!strcmp(buf, "\??\C:\windows\"), "got path %s\n", debugstr_a(buf));
sprintf(buf, "%s/system32", drivestr); file = CreateFileA( buf, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, diff --git a/dlls/kernel32/volume.c b/dlls/kernel32/volume.c index 02d14cdcc9d..5bfebf60570 100644 --- a/dlls/kernel32/volume.c +++ b/dlls/kernel32/volume.c @@ -39,6 +39,7 @@ #include "ntddcdrm.h" #define WINE_MOUNTMGR_EXTENSIONS #include "ddk/mountmgr.h" +#include "ddk/wdm.h" #include "kernel_private.h" #include "wine/library.h" #include "wine/unicode.h" @@ -68,29 +69,6 @@ enum fs_type FS_UDF /* For reference [E] = Ecma-167.pdf, [U] = udf260.pdf */ };
-/* get the path of a dos device symlink in the $WINEPREFIX/dosdevices directory */ -static char *get_dos_device_path( LPCWSTR name ) -{ - const char *config_dir = wine_get_config_dir(); - char *buffer, *dev; - int i; - - if (!(buffer = HeapAlloc( GetProcessHeap(), 0, - strlen(config_dir) + sizeof("/dosdevices/") + 5 ))) - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return NULL; - } - strcpy( buffer, config_dir ); - strcat( buffer, "/dosdevices/" ); - dev = buffer + strlen(buffer); - /* no codepage conversion, DOS device names are ASCII anyway */ - for (i = 0; i < 5; i++) - if (!(dev[i] = (char)tolowerW(name[i]))) break; - dev[5] = 0; - return buffer; -} - /* read the contents of an NT symlink object */ static NTSTATUS read_nt_symlink( const WCHAR *name, WCHAR *target, DWORD size ) { @@ -1128,73 +1106,50 @@ err_ret: /*********************************************************************** * DefineDosDeviceW (KERNEL32.@) */ -BOOL WINAPI DefineDosDeviceW( DWORD flags, LPCWSTR devname, LPCWSTR targetpath ) +BOOL WINAPI DefineDosDeviceW( DWORD flags, const WCHAR *device, const WCHAR *target ) { - DWORD len, dosdev; - BOOL ret = FALSE; - char *path = NULL, *target, *p; + WCHAR link_name[15] = {'\','D','o','s','D','e','v','i','c','e','s','\',0}; + UNICODE_STRING nt_name, nt_target; + OBJECT_ATTRIBUTES attr; + NTSTATUS status; + HANDLE handle;
- TRACE("%x, %s, %s\n", flags, debugstr_w(devname), debugstr_w(targetpath)); + TRACE("%#x, %s, %s\n", flags, debugstr_w(device), debugstr_w(target));
- if (!(flags & DDD_REMOVE_DEFINITION)) + if (flags & ~(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION)) + FIXME("Ignoring flags %#x.\n", flags & ~(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION)); + + strcatW( link_name, device ); + RtlInitUnicodeString( &nt_name, link_name ); + InitializeObjectAttributes( &attr, &nt_name, OBJ_CASE_INSENSITIVE, 0, NULL ); + if (flags & DDD_REMOVE_DEFINITION) { - if (!(flags & DDD_RAW_TARGET_PATH)) - { - FIXME( "(0x%08x,%s,%s) DDD_RAW_TARGET_PATH flag not set, not supported yet\n", - flags, debugstr_w(devname), debugstr_w(targetpath) ); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + if (!set_ntstatus( NtOpenSymbolicLinkObject( &handle, 0, &attr ) )) return FALSE; - }
- len = WideCharToMultiByte( CP_UNIXCP, 0, targetpath, -1, NULL, 0, NULL, NULL ); - if ((target = HeapAlloc( GetProcessHeap(), 0, len ))) + SERVER_START_REQ( unlink_object ) { - WideCharToMultiByte( CP_UNIXCP, 0, targetpath, -1, target, len, NULL, NULL ); - for (p = target; *p; p++) if (*p == '\') *p = '/'; + req->handle = wine_server_obj_handle( handle ); + status = wine_server_call( req ); } - else - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return FALSE; - } - } - else target = NULL; - - /* first check for a DOS device */ - - if ((dosdev = RtlIsDosDeviceName_U( devname ))) - { - WCHAR name[5]; + SERVER_END_REQ; + NtClose( handle );
- memcpy( name, devname + HIWORD(dosdev)/sizeof(WCHAR), LOWORD(dosdev) ); - name[LOWORD(dosdev)/sizeof(WCHAR)] = 0; - path = get_dos_device_path( name ); - } - else if (isalphaW(devname[0]) && devname[1] == ':' && !devname[2]) /* drive mapping */ - { - path = get_dos_device_path( devname ); + return set_ntstatus( status ); } - else SetLastError( ERROR_FILE_NOT_FOUND );
- if (path) + if (!(flags & DDD_RAW_TARGET_PATH)) { - if (target) + if (!RtlDosPathNameToNtPathName_U( target, &nt_target, NULL, NULL)) { - TRACE( "creating symlink %s -> %s\n", path, target ); - unlink( path ); - if (!symlink( target, path )) ret = TRUE; - else FILE_SetDosError(); - } - else - { - TRACE( "removing symlink %s\n", path ); - if (!unlink( path )) ret = TRUE; - else FILE_SetDosError(); + SetLastError( ERROR_PATH_NOT_FOUND ); + return FALSE; } - HeapFree( GetProcessHeap(), 0, path ); } - HeapFree( GetProcessHeap(), 0, target ); - return ret; + else + RtlInitUnicodeString( &nt_target, target ); + + return set_ntstatus( NtCreateSymbolicLinkObject( &handle, SYMBOLIC_LINK_ALL_ACCESS, &attr, &nt_target ) ); }