Alexandre Julliard : kernel32: Return the Windows symlink in QueryDosDevice instead of the Unix one.
Alexandre Julliard
julliard at winehq.org
Fri Oct 24 08:12:22 CDT 2008
Module: wine
Branch: master
Commit: 6dee4c6e639b7de1d4b1aaee9263d26ecce7bbc3
URL: http://source.winehq.org/git/wine.git/?a=commit;h=6dee4c6e639b7de1d4b1aaee9263d26ecce7bbc3
Author: Alexandre Julliard <julliard at winehq.org>
Date: Thu Oct 23 20:24:49 2008 +0200
kernel32: Return the Windows symlink in QueryDosDevice instead of the Unix one.
---
dlls/kernel32/tests/volume.c | 2 +-
dlls/kernel32/volume.c | 56 ++++++++++++++++++++++++++++++++++++++---
2 files changed, 52 insertions(+), 6 deletions(-)
diff --git a/dlls/kernel32/tests/volume.c b/dlls/kernel32/tests/volume.c
index 0229a82..97e3559 100644
--- a/dlls/kernel32/tests/volume.c
+++ b/dlls/kernel32/tests/volume.c
@@ -51,7 +51,7 @@ static void test_query_dos_deviceA(void)
if (strstr(buffer, "HARDDISK") || strstr(buffer, "RAMDISK")) found = TRUE;
}
}
- todo_wine ok(found, "expected at least one devicename to contain HARDDISK or RAMDISK\n");
+ ok(found, "expected at least one devicename to contain HARDDISK or RAMDISK\n");
}
static void test_FindFirstVolume(void)
diff --git a/dlls/kernel32/volume.c b/dlls/kernel32/volume.c
index 823d163..7dc046f 100644
--- a/dlls/kernel32/volume.c
+++ b/dlls/kernel32/volume.c
@@ -46,6 +46,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(volume);
#define SUPERBLOCK_SIZE 2048
+#define SYMBOLIC_LINK_QUERY 0x0001
#define CDFRAMES_PERSEC 75
#define CDFRAMES_PERMIN (CDFRAMES_PERSEC * 60)
@@ -128,6 +129,33 @@ static char *get_dos_device_path( LPCWSTR name )
return buffer;
}
+/* read the contents of an NT symlink object */
+static NTSTATUS read_nt_symlink( const WCHAR *name, WCHAR *target, DWORD size )
+{
+ NTSTATUS status;
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING nameW;
+ HANDLE handle;
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.Attributes = OBJ_CASE_INSENSITIVE;
+ attr.ObjectName = &nameW;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+ RtlInitUnicodeString( &nameW, name );
+
+ if (!(status = NtOpenSymbolicLinkObject( &handle, SYMBOLIC_LINK_QUERY, &attr )))
+ {
+ UNICODE_STRING targetW;
+ targetW.Buffer = target;
+ targetW.MaximumLength = (size - 1) * sizeof(WCHAR);
+ status = NtQuerySymbolicLinkObject( handle, &targetW, NULL );
+ if (!status) target[targetW.Length / sizeof(WCHAR)] = 0;
+ NtClose( handle );
+ }
+ return status;
+}
/* open a handle to a device root */
static BOOL open_device_root( LPCWSTR root, HANDLE *handle )
@@ -916,6 +944,7 @@ DWORD WINAPI QueryDosDeviceW( LPCWSTR devname, LPWSTR target, DWORD bufsize )
static const WCHAR com0W[] = {'\\','?','?','\\','C','O','M','0',0};
static const WCHAR com1W[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\','C','O','M','1',0,0};
static const WCHAR lpt1W[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\','L','P','T','1',0,0};
+ static const WCHAR driveW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\','A',':',0};
UNICODE_STRING nt_name;
ANSI_STRING unix_name;
@@ -941,7 +970,19 @@ DWORD WINAPI QueryDosDeviceW( LPCWSTR devname, LPWSTR target, DWORD bufsize )
}
else if (devname[0] && devname[1] == ':' && !devname[2])
{
- memcpy( name, devname, 3 * sizeof(WCHAR) );
+ /* FIXME: should do this for all devices, not just drives */
+ NTSTATUS status;
+ WCHAR buffer[sizeof(driveW)/sizeof(WCHAR)];
+
+ memcpy( buffer, driveW, sizeof(driveW) );
+ buffer[12] = devname[0];
+ if ((status = read_nt_symlink( buffer, target, bufsize )))
+ {
+ SetLastError( RtlNtStatusToDosError(status) );
+ return 0;
+ }
+ ret = strlenW( target ) + 1;
+ goto done;
}
else
{
@@ -995,7 +1036,7 @@ DWORD WINAPI QueryDosDeviceW( LPCWSTR devname, LPWSTR target, DWORD bufsize )
RtlFreeAnsiString( &unix_name );
}
}
-
+ done:
if (ret)
{
if (ret < bufsize) target[ret++] = 0; /* add an extra null */
@@ -1064,12 +1105,17 @@ DWORD WINAPI QueryDosDeviceW( LPCWSTR devname, LPWSTR target, DWORD bufsize )
strcpyW( nt_buffer + 4, rootW );
RtlInitUnicodeString( &nt_name, nt_buffer );
+ /* FIXME: should simply enumerate the DosDevices directory instead */
for (i = 0; i < 26; i++)
{
- nt_buffer[4] = 'a' + i;
- if (!wine_nt_to_unix_file_name( &nt_name, &unix_name, FILE_OPEN, TRUE ))
+ WCHAR buffer[sizeof(driveW)/sizeof(WCHAR)], dummy[8];
+ NTSTATUS status;
+
+ memcpy( buffer, driveW, sizeof(driveW) );
+ buffer[12] = 'A' + i;
+ status = read_nt_symlink( buffer, dummy, sizeof(dummy)/sizeof(WCHAR) );
+ if (status == STATUS_SUCCESS || status == STATUS_BUFFER_TOO_SMALL)
{
- RtlFreeAnsiString( &unix_name );
if (p + 3 >= target + bufsize)
{
SetLastError( ERROR_INSUFFICIENT_BUFFER );
More information about the wine-cvs
mailing list