Unicodify the create_file server call

Mike McCormack mikem at codeweavers.com
Wed Jun 19 20:48:24 CDT 2002


This patch makes the server interface for opening files unicode. It also 
intentionally breaks NtOpenFile, since the implemenation was a bad hack.

Mike


License: LGPL

ChangeLog:
* unicodify the create_file server call
* use unicode for filenames inside the server

-------------- next part --------------
Index: dlls/ntdll/file.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/file.c,v
retrieving revision 1.14
diff -u -r1.14 file.c
--- dlls/ntdll/file.c	14 Jun 2002 00:36:20 -0000	1.14
+++ dlls/ntdll/file.c	19 Jun 2002 17:23:09 -0000
@@ -30,7 +30,6 @@
 #include "wine/debug.h"
 #include "wine/server.h"
 #include "ntdll_misc.h"
-#include "file.h" /* FIXME */
 
 #include "ntddk.h"
 #include "winioctl.h"
@@ -58,12 +57,8 @@
 	ULONG ShareAccess,
 	ULONG OpenOptions)
 {
-	ULONG len = 0;
-	PSTR filename;
-	CHAR szDosDevices[] = "\\DosDevices\\";
-	DOS_FULL_NAME full_name;
 	NTSTATUS r;
-
+	
 	FIXME("(%p,0x%08lx,%p,%p,0x%08lx,0x%08lx) partial stub\n",
 		FileHandle, DesiredAccess, ObjectAttributes,
 		IoStatusBlock, ShareAccess, OpenOptions);
@@ -77,24 +72,7 @@
 		return STATUS_OBJECT_NAME_NOT_FOUND;
 	}
 
-	/* create an ascii string from the unicode filename */
-	RtlUnicodeToMultiByteSize( &len, ObjectAttributes->ObjectName->Buffer,
-				ObjectAttributes->ObjectName->Length );
-	filename = RtlAllocateHeap( GetProcessHeap(), 0, len + 1);
-	RtlUnicodeToMultiByteN(filename, len, NULL, ObjectAttributes->ObjectName->Buffer,
-				ObjectAttributes->ObjectName->Length );
-	filename[len]=0;
-
-	/* FIXME: DOSFS stuff should call here, not vice-versa */
-	if(strncmp(filename, szDosDevices, strlen(szDosDevices)))
-		return STATUS_OBJECT_NAME_NOT_FOUND;
-
-	/* FIXME: this calls SetLastError() -> bad */
-	if(!DOSFS_GetFullName(&filename[strlen(szDosDevices)], TRUE,
-				&full_name))
-		return STATUS_OBJECT_NAME_NOT_FOUND;
-
-	/* FIXME: modify server protocol so
+	/* FIXME: modify server protocol so 
                   create file takes an OBJECT_ATTRIBUTES structure */
         SERVER_START_REQ( create_file )
         {
@@ -103,9 +81,8 @@
             req->sharing    = ShareAccess;
             req->create     = OPEN_EXISTING;
             req->attrs      = 0;
-            req->drive_type = GetDriveTypeA( full_name.short_name );
-            wine_server_add_data( req, full_name.long_name, strlen(full_name.long_name) );
-            SetLastError(0);
+            req->drive_type = -1;
+            wine_server_add_data( req, ObjectAttributes->ObjectName->Buffer, ObjectAttributes->ObjectName->Length );
             r = wine_server_call( req );
             *FileHandle = reply->handle;
         }
Index: files/file.c
===================================================================
RCS file: /home/wine/wine/files/file.c,v
retrieving revision 1.149
diff -u -r1.149 file.c
--- files/file.c	5 Jun 2002 00:47:38 -0000	1.149
+++ files/file.c	19 Jun 2002 17:23:11 -0000
@@ -378,6 +378,8 @@
 {
     unsigned int err;
     HANDLE ret;
+    WCHAR name[MAX_PATH];
+    int len = MultiByteToWideChar(CP_ACP,0,filename,-1,name,MAX_PATH);
 
     for (;;)
     {
@@ -389,7 +391,7 @@
             req->create     = creation;
             req->attrs      = attributes;
             req->drive_type = drive_type;
-            wine_server_add_data( req, filename, strlen(filename) );
+            wine_server_add_data( req, name, len*sizeof(WCHAR) );
             SetLastError(0);
             err = wine_server_call( req );
             ret = reply->handle;
@@ -403,7 +405,7 @@
             if ((err == STATUS_MEDIA_WRITE_PROTECTED) || (err == STATUS_ACCESS_DENIED))
             {
                 TRACE("Write access failed for file '%s', trying without "
-                      "write access\n", filename);
+                      "write access\n", debugstr_w(name));
                 access &= ~GENERIC_WRITE;
                 continue;
             }
@@ -411,7 +413,7 @@
 
         if (err) SetLastError( RtlNtStatusToDosError(err) );
 
-        if (!ret) WARN("Unable to create file '%s' (GLE %ld)\n", filename, GetLastError());
+        if (!ret) WARN("Unable to create file '%s' (GLE %ld)\n", debugstr_wn(name,len), GetLastError());
         return ret;
     }
 }
Index: server/file.c
===================================================================
RCS file: /home/wine/wine/server/file.c,v
retrieving revision 1.58
diff -u -r1.58 file.c
--- server/file.c	30 May 2002 20:12:58 -0000	1.58
+++ server/file.c	19 Jun 2002 17:23:11 -0000
@@ -44,12 +44,13 @@
 #include "thread.h"
 #include "request.h"
 #include "async.h"
+#include "unicode.h"
 
 struct file
 {
     struct object       obj;        /* object header */
     struct file        *next;       /* next file in hashing list */
-    char               *name;       /* file name */
+    WCHAR              *name;       /* file name */
     unsigned int        access;     /* file access (GENERIC_READ/WRITE) */
     unsigned int        flags;      /* flags (FILE_FLAG_*) */
     unsigned int        sharing;    /* file sharing mode */
@@ -89,16 +90,16 @@
 };
 
 
-static int get_name_hash( const char *name )
+static int get_name_hash( const WCHAR *name )
 {
     int hash = 0;
-    while (*name) hash ^= (unsigned char)*name++;
+    while (*name) hash ^= (unsigned short)*name++;
     return hash % NAME_HASH_SIZE;
 }
 
 /* check if the desired access is possible without violating */
 /* the sharing mode of other opens of the same file */
-static int check_sharing( const char *name, int hash, unsigned int access,
+static int check_sharing( const WCHAR *name, int hash, unsigned int access,
                           unsigned int sharing )
 {
     struct file *file;
@@ -107,7 +108,7 @@
 
     for (file = file_hash[hash]; file; file = file->next)
     {
-        if (strcmp( file->name, name )) continue;
+        if (strcmpW( file->name, name )) continue;
         existing_sharing &= file->sharing;
         existing_access |= file->access;
     }
@@ -144,20 +145,19 @@
     return file;
 }
 
-
-static struct file *create_file( const char *nameptr, size_t len, unsigned int access,
+struct object *create_file( const WCHAR *nameptr, size_t len, unsigned int access,
                                  unsigned int sharing, int create, unsigned int attrs,
                                  int drive_type )
 {
     struct file *file;
     int hash, flags;
     struct stat st;
-    char *name;
+    WCHAR *name, szwCom[] = {'.','c','o','m',0 }, szwExe[] = {'.','e','x','e',0 };
     int fd = -1;
     mode_t mode;
 
-    if (!(name = mem_alloc( len + 1 ))) return NULL;
-    memcpy( name, nameptr, len );
+    if (!(name = mem_alloc( (len+1)*sizeof (WCHAR) ))) return NULL;
+    memcpy( name, nameptr, len*sizeof (WCHAR) );
     name[len] = 0;
 
     /* check sharing mode */
@@ -183,11 +183,11 @@
     mode = (attrs & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666;
 
     if (len >= 4 &&
-        (!strcasecmp( name + len - 4, ".exe" ) || !strcasecmp( name + len - 4, ".com" )))
+        (!strcmpiW( name + len - 4, szwExe ) || !strcmpiW( name + len - 4, szwCom )))
         mode |= 0111;
 
     /* FIXME: should set error to STATUS_OBJECT_NAME_COLLISION if file existed before */
-    if ((fd = open( name, flags | O_NONBLOCK | O_LARGEFILE, mode )) == -1 )
+    if ((fd = openw( name, flags | O_NONBLOCK | O_LARGEFILE, mode )) == -1 )
         goto file_error;
     /* refuse to open a directory */
     if (fstat( fd, &st ) == -1) goto file_error;
@@ -205,7 +205,7 @@
     file->name = name;
     file->next = file_hash[hash];
     file_hash[hash] = file;
-    return file;
+    return &file->obj;
 
  file_error:
     file_set_error();
@@ -218,7 +218,7 @@
 /* check if two file objects point to the same file */
 int is_same_file( struct file *file1, struct file *file2 )
 {
-    return !strcmp( file1->name, file2->name );
+    return !strcmpW( file1->name, file2->name );
 }
 
 /* get the type of drive the file is on */
@@ -264,7 +264,9 @@
 {
     struct file *file = (struct file *)obj;
     assert( obj->ops == &file_ops );
-    fprintf( stderr, "File fd=%d flags=%08x name='%s'\n", file->obj.fd, file->flags, file->name );
+    fprintf( stderr, "File fd=%d flags=%08x name=", file->obj.fd, file->flags );
+    dump_strW(file->name,strlenW(file->name),stderr,"[]");
+    fprintf( stderr, "\n" );
 }
 
 static int file_get_poll_events( struct object *obj )
@@ -427,7 +429,7 @@
         while (*pptr && *pptr != file) pptr = &(*pptr)->next;
         assert( *pptr );
         *pptr = (*pptr)->next;
-        if (file->flags & FILE_FLAG_DELETE_ON_CLOSE) unlink( file->name );
+        if (file->flags & FILE_FLAG_DELETE_ON_CLOSE) unlinkw( file->name );
         free( file->name );
     }
     if (file->flags & FILE_FLAG_OVERLAPPED)
@@ -564,13 +566,13 @@
     if (!access_time || !write_time)
     {
         struct stat st;
-        if (stat( file->name, &st ) == -1) goto error;
+        if (statw( file->name, &st ) == -1) goto error;
         if (!access_time) access_time = st.st_atime;
         if (!write_time) write_time = st.st_mtime;
     }
     utimbuf.actime  = access_time;
     utimbuf.modtime = write_time;
-    if (utime( file->name, &utimbuf ) == -1) goto error;
+    if (utimew( file->name, &utimbuf ) == -1) goto error;
     release_object( file );
     return 1;
  error:
@@ -596,11 +598,24 @@
 /* create a file */
 DECL_HANDLER(create_file)
 {
-    struct file *file;
+    struct object *file = NULL;
+    const WCHAR *name = get_req_data();
+    int len = get_req_data_size()/sizeof (WCHAR);
 
     reply->handle = 0;
-    if ((file = create_file( get_req_data(), get_req_data_size(), req->access,
-                             req->sharing, req->create, req->attrs, req->drive_type )))
+
+    if(len && (name[0]!='/')) /* nt path name */
+    {
+        /* FIXME: open an NT path here */
+        set_error(STATUS_ACCESS_DENIED);
+    }
+    else
+    {
+        file = create_file( name, len, req->access,
+                            req->sharing, req->create, req->attrs, req->drive_type );
+    }
+
+    if (file)
     {
         reply->handle = alloc_handle( current->process, file, req->access, req->inherit );
         release_object( file );
Index: server/protocol.def
===================================================================
RCS file: /home/wine/wine/server/protocol.def,v
retrieving revision 1.39
diff -u -r1.39 protocol.def
--- server/protocol.def	2 Jun 2002 21:22:22 -0000	1.39
+++ server/protocol.def	19 Jun 2002 17:23:12 -0000
@@ -572,7 +572,7 @@
     int          create;        /* file create action */
     unsigned int attrs;         /* file attributes for creation */
     int          drive_type;    /* type of drive the file is on */
-    VARARG(filename,string);    /* file name */
+    VARARG(filename,unicode_str); /* file name */
 @REPLY
     obj_handle_t handle;        /* handle to the file */
 @END
Index: server/unicode.c
===================================================================
RCS file: /home/wine/wine/server/unicode.c,v
retrieving revision 1.4
diff -u -r1.4 unicode.c
--- server/unicode.c	26 Apr 2002 19:05:18 -0000	1.4
+++ server/unicode.c	19 Jun 2002 17:23:12 -0000
@@ -24,8 +24,18 @@
 #include <ctype.h>
 #include <stdio.h>
 
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
+
+#include "thread.h"
 #include "unicode.h"
 
+static const union cptable *ansi_cptable;
+
+
 /* dump a Unicode string with proper escaping */
 int dump_strW( const WCHAR *str, size_t len, FILE *f, char escape[2] )
 {
@@ -68,3 +78,85 @@
     count += pos - buffer;
     return count;
 }
+
+int strcasecmpnW(const WCHAR *x, const WCHAR *y, int n)
+{
+    int i;
+    for(i=0; i<n; i++)
+    {
+        if((x[i]&~0x20)>(y[i]&~0x20))
+            return 1;
+        if((x[i]&~0x20)<(y[i]&~0x20))
+            return -1;
+    }
+    return 0;
+}
+
+/* FIXME: hardcoded to ANSI for the time being */
+
+int file_unicode_to_apath(const WCHAR *path_w, char *path_a, int len)
+{
+    if(!ansi_cptable)
+        ansi_cptable = cp_get_table( 1252 );
+    return cp_wcstombs( ansi_cptable, 0, path_w, -1, path_a, len, NULL, NULL);
+}
+
+int file_apath_to_unicode(const char *path_a, WCHAR *path_w, int len)
+{
+    if(!ansi_cptable)
+        ansi_cptable = cp_get_table( 1252 );
+    return cp_mbstowcs( ansi_cptable, 0, path_a, -1, path_w, len);
+}
+
+int openw(const WCHAR *name, int access, int mode)
+{
+    char name_a[MAX_PATH];
+    name_a[0]=0;
+    file_unicode_to_apath(name,name_a,MAX_PATH);
+    return open(name_a,access,mode);
+}
+
+int unlinkw(const WCHAR *name)
+{
+    char name_a[MAX_PATH];
+    name_a[0]=0;
+    file_unicode_to_apath(name,name_a,MAX_PATH);
+    return unlink(name_a);
+}
+
+int statw(const WCHAR *name, struct stat *st)
+{
+    char name_a[MAX_PATH];
+    name_a[0]=0;
+    file_unicode_to_apath(name,name_a,MAX_PATH);
+    return stat(name_a,st);
+}
+
+int utimew(const WCHAR *name, struct utimbuf *utimbuf)
+{
+    char name_a[MAX_PATH];
+    name_a[0]=0;
+    file_unicode_to_apath(name,name_a,MAX_PATH);
+    return utime(name_a,utimbuf);
+}
+
+DIR *opendirw(const WCHAR *name)
+{
+    char name_a[MAX_PATH];
+    name_a[0]=0;
+    file_unicode_to_apath(name,name_a,MAX_PATH);
+    return opendir(name_a);
+}
+
+static struct direntw g_de;
+
+struct direntw *readdirw(DIR *dir)
+{
+    struct dirent *de = readdir(dir);
+    if(!de)
+        return NULL;
+    g_de.d_name[0]=0;
+    file_apath_to_unicode(de->d_name, g_de.d_name, sizeof(g_de.d_name)/sizeof(WCHAR));
+    return &g_de;
+}
+
Index: server/unicode.h
===================================================================
RCS file: /home/wine/wine/server/unicode.h,v
retrieving revision 1.8
diff -u -r1.8 unicode.h
--- server/unicode.h	10 Mar 2002 00:18:36 -0000	1.8
+++ server/unicode.h	19 Jun 2002 17:23:12 -0000
@@ -22,6 +22,9 @@
 #define __WINE_SERVER_UNICODE_H
 
 #include <stdio.h>
+#include <dirent.h>
+#include <sys/time.h>
+#include <utime.h>
 
 #include "windef.h"
 #include "wine/unicode.h"
@@ -35,4 +38,20 @@
 
 extern int dump_strW( const WCHAR *str, size_t len, FILE *f, char escape[2] );
 
+extern int strcasecmpnW(const WCHAR *x, const WCHAR *y, int n);
+
+extern int openw(const WCHAR *name, int access, int mode);
+extern int unlinkw(const WCHAR *name);
+extern int statw(const WCHAR *name, struct stat *st);
+extern int utimew(const WCHAR *name, struct utimbuf *utimbuf);
+
+struct direntw 
+{
+    WCHAR d_name[NAME_MAX+1];
+};
+
+extern DIR *opendirw(const WCHAR *name);
+extern struct direntw *readdirw(DIR *dir);
+
 #endif  /* __WINE_SERVER_UNICODE_H */
+


More information about the wine-patches mailing list