Wine-devel
Threads by month
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
September 2003
- 133 participants
- 342 discussions
Basically, please don't do them.
For starters, the GUI resources are constantly changing. Keeping the
other versions in sync would be a full time job.
Secondly, it causes problems with getting a clean diff against CVS
because of the way I'm doing it..
Right now I don't think winecfg is stable enough to be doing translation
work, especially considering the total lack of support in the win32
windowing system for non-sucky i18n.
thanks -mike
1
0
Hi there,
I tried to compile Wine-20030911 on a Solaris 9 x86 with gcc 2.95.3.
Wineinstall runs through until I get the following error when performing
make:
-------------------------------------------------------------------
./tools/makedep -I. -I. -I./include -I./include -C.
gcc -c -I. -I. -I../../include -I../../include -D_REENTRANT -fPIC
-D__WINESRC__
-Wall -mpreferred-stack-boundary=2 -fno-strict-aliasing -gstabs+
-Wpointer-ari
th -g -O2 -o ddraw.spec.o ddraw.spec.c
Assembler: ddraw.spec.c
"/var/tmp/cc0f2yLe.s", line 28 : Syntax error
"/var/tmp/cc0f2yLe.s", line 688 : Illegal mnemonic
"/var/tmp/cc0f2yLe.s", line 688 : Syntax error
"/var/tmp/cc0f2yLe.s", line 689 : Illegal mnemonic
"/var/tmp/cc0f2yLe.s", line 689 : Syntax error
"/var/tmp/cc0f2yLe.s", line 690 : Illegal mnemonic
"/var/tmp/cc0f2yLe.s", line 690 : Syntax error
"/var/tmp/cc0f2yLe.s", line 691 : Illegal mnemonic
"/var/tmp/cc0f2yLe.s", line 691 : Syntax error
"/var/tmp/cc0f2yLe.s", line 692 : Illegal mnemonic
"/var/tmp/cc0f2yLe.s", line 692 : Syntax error
"/var/tmp/cc0f2yLe.s", line 693 : Illegal mnemonic
"/var/tmp/cc0f2yLe.s", line 693 : Syntax error
"/var/tmp/cc0f2yLe.s", line 694 : Illegal mnemonic
"/var/tmp/cc0f2yLe.s", line 694 : Syntax error
"/var/tmp/cc0f2yLe.s", line 695 : Illegal mnemonic
"/var/tmp/cc0f2yLe.s", line 695 : Syntax error
"/var/tmp/cc0f2yLe.s", line 696 : Illegal mnemonic
"/var/tmp/cc0f2yLe.s", line 696 : Syntax error
"/var/tmp/cc0f2yLe.s", line 697 : Illegal mnemonic
"/var/tmp/cc0f2yLe.s", line 697 : Syntax error
"/var/tmp/cc0f2yLe.s", line 698 : Illegal mnemonic
"/var/tmp/cc0f2yLe.s", line 698 : Syntax error
"/var/tmp/cc0f2yLe.s", line 699 : Illegal mnemonic
"/var/tmp/cc0f2yLe.s", line 699 : Syntax error
"/var/tmp/cc0f2yLe.s", line 700 : Illegal mnemonic
"/var/tmp/cc0f2yLe.s", line 700 : Syntax error
"/var/tmp/cc0f2yLe.s", line 701 : Illegal mnemonic
"/var/tmp/cc0f2yLe.s", line 701 : Syntax error
"/var/tmp/cc0f2yLe.s", line 702 : Illegal mnemonic
"/var/tmp/cc0f2yLe.s", line 702 : Syntax error
Too many errors - Goodbye
*** Error code 1
make: Fatal error: Command failed for target `ddraw.spec.o'
Current working directory /export/home/ebbi/wine/wine-20030911/dlls/ddraw
*** Error code 1
make: Fatal error: Command failed for target `ddraw'
Current working directory /export/home/ebbi/wine/wine-20030911/dlls
*** Error code 1
make: Fatal error: Command failed for target `dlls'
Compilation failed, aborting install.
-----------------------------------------------------------------------
Any help will be appreciated.
Thanks,
Ebbi
--
+++ GMX - die erste Adresse für Mail, Message, More! +++
Getestet von Stiftung Warentest: GMX FreeMail (GUT), GMX ProMail (GUT)
(Heft 9/03 - 23 e-mail-Tarife: 6 gut, 12 befriedigend, 5 ausreichend)
Jetzt selbst kostenlos testen: http://www.gmx.net
1
0
resource.h:
#define ID_MCODE 1024
#define ID_MCODE_1 ID_MCODE+1
The resource file generated by MSVC contains:
/////////////////////////////////////////////////////////////////////////////
//
// Dialog Info
//
RDSrvSheet DLGINIT
BEGIN
ID_MCODE_1, 0x403, 1, 0 // parse error in this string
"\000"
0
END
but string ID_MCODE, 0x403, 1, 0 compile successfull
This section of resource is optional and i can delete it of cource.
But this is a bug.
1
0
This was fixed by revision 1.40 of scheduler/pthread.h:
date: 2003/09/18 20:52:24; author: julliard; state: Exp; lines: +5 -6
Gabriele Giorgetti <gabriele.giorgetti(a)teamfab.it>
Fix build with old libc.
Thanks!
Gerald
On Mon, 8 Sep 2003, Gerald Pfeifer wrote:
> I've been seeing the following build failures on FreeBSD 4.8 for a few
> days:
>
> /usr/bin/gcc -c -I. -I. -I../../include -I../../include -D_REENTRANT
> -fPIC -D__WINESRC__ -D_NTSYSTEM_ -DBINDIR="\"/tmp/WINE/bin\""
> -DETCDIR="\"/tmp/WINE/etc\"" -Wall -mpreferred-stack-boundary=2
> -fno-strict-aliasing -gstabs+ -Wpointer-arith -g -O2 -o
> ../../scheduler/pthread.o ../../scheduler/pthread.c
> ../../scheduler/pthread.c: In function `wine_pthread_init_process':
> ../../scheduler/pthread.c:159: `__res_state' undeclared (first use in this function)
> ../../scheduler/pthread.c:159: (Each undeclared identifier is reported only once
> ../../scheduler/pthread.c:159: for each function it appears in.)
> ../../scheduler/pthread.c: At top level:
> ../../scheduler/pthread.c:263: `__res_state' used prior to declaration
> gmake[2]: *** [../../scheduler/pthread.o] Error 1
> gmake[2]: Leaving directory
> `/.amd_mnt/nashira/files5/test/wine/dlls/ntdll'
> gmake[1]: *** [ntdll] Error 2
1
0
OK,
This should explain a bit more what I meant to say with this
silly .dsl files. First, use the standard ones when building
HTML and PS. This means that the docu will be build with
the user's L&F which is the right thing to do IMO. If we don't
do that, we might as well give up on SGML, it creates problems
for no benefits.
Once this patch is applied, we can:
-- move default.dsl and print.dsl into the tools/ module
where they belong (and where make_winehq needs them)
-- remove make_winehq from our documentation dir,
as it's been made obsolete by tools/make_winehq
This should result in no change as how we build the documentation.
BTW, this patch does not conflict with Francois' patch, in
that his changes can be applied to default.dsl before we
move it to tools/.
ChangeLog
Dimitrie O. Paun <dpaun(a)rogers.com>
Do not force our presentation for the users who want to
build their documentation.
Index: documentation/Makefile.in
===================================================================
RCS file: /var/cvs/wine/documentation/Makefile.in,v
retrieving revision 1.32
diff -u -r1.32 Makefile.in
--- documentation/Makefile.in 23 Jun 2003 19:51:21 -0000 1.32
+++ documentation/Makefile.in 12 Sep 2003 15:44:44 -0000
@@ -87,10 +87,10 @@
.SUFFIXES: .sgml /index.html .pdf .ps
.sgml/index.html:
- $(DB2HTML) -d $(SRCDIR)/default.dsl -o $* $<
+ $(DB2HTML) -o $* $<
.sgml.pdf:
- $(DB2PDF) -d $(SRCDIR)/print.dsl $< >/dev/null
+ $(DB2PDF) $< >/dev/null
.sgml.ps:
$(DB2PS) $< >/dev/null
--
Dimi.
4
7
"Dimitrie O. Paun" <dpaun(a)rogers.com> writes:
> The fact that the FAQ is now SGML does not warant
> building it in all sorts of formats, and including
> it in the docs tarball. Just because we can, does
> not mean we should.
>
> In fact, theoretically we should move this over
> to the lostwages/ modules, this is part of the
> WineHQ proper, not the wine tree.
I'm not sure I agree with that. If we make the documentation available
for download then we should have the FAQ there too, we shouldn't
require people to go to WineHQ to get it. I do agree that we don't
need all the fancy formats, in fact the download should probably be
only the plain text version.
--
Alexandre Julliard
julliard(a)winehq.com
2
1
18 Sep '03
>The patches themself seem to be okay only that the new if-statement in
>IDirect3D8Impl_CheckDeviceFormat should be #ifdef
>GL_EXT_texture_compression_s3tc because if it's not defined we don't
>have the support as you can see in IDirect3DSurface8Impl_LoadTexture
>(surface.c:468). So it will lead to white boxes on a system, when at
>compile-time the constant isn't defined and the system says it support
>it. But this isn't the case for me because the log show that it
>definitly calls glCompressedTexImage2D.
I dont understand this fully. The whole point is to eventually make all the
decisions based at run time as to the capabilities of the graphics card, to
enable distributions of wine (otherwise you are limited to the capabilities
of the machine it was compiled on). Therefore in fillglcaps, we loog for the
prescence of the compressed texture string (EXT_texture_compression_s3tc)
and if present we will call it.
In your case, it is present so it will be called. So when querying device
formats, we can return that dxt1,3,5 are available, and later on we should
call the glCompressedTexImage2D call. #ifdef'ing it either takes it out (in
which case we say we dont support dxtn and the pgm probably does its own
decompression), or you go through the same code.
So its back to why are you getting an error from that call. Can you please
send me (not wine-devel) a --debugmsg +d3d,+d3d_surface trace up to the
point the menu is displayed please (ie I should see the error on the load
texture for a dxtn format).
One final question, did the game use to play ok? I get very little feedback
on dx8 games, so I dont really know how well things are running.
FYI I am still working on it (with a lot less free time at the moment) but
getting stuck on a couple of areas we need to address at some point so
making slow progress. I want to get back to optimizing again asap.
Jason
3
3
I've been quite quiet recently on ntdll/separation.
I was working on the NtCreateFile implementation.
Even, if it's not ready for prime time, I've been running lots of apps
since once week without issues (which doesn't mean that none are left).
You'll find attached the patch for review.
(Since Alexandre has been busy lately, better to share some info)
However, it's not ready for prime time yet. Among things that remain to
be done:
- review some internal namings (that's easy) and file naming
- get Alexandre review (that's harder... I mean to get a positive review)
- cleanup the initialisation code
There are some parts I don't like. The current server scheme doesn't fit
well with the device manipulation we need.
Currently, I set, at a given point in NT pathnames (say \??\C:) a link
to a Unix pathname (say /opt/windows).
This fits well with path conversions. It doesn't work for real device
configuration, in particular CDROMs, where we need both the unix path
for data access (/mnt/cdrom) and the unix path of the associated unix
device (/dev/cdrom).
I'm still thinking of either:
- stick to current device structures, and store every bit of information
(server-side) in the 'pathgate' object.
- beef up the device server object to store this information (unix
device name, fake label, fake serial number).
The later is in fact more suited for an evolution of the current server
device object.
My final question is more on which order we go on:
Solution 1:
1/ get the NtCreateFile ready and include it in the tree
2.a/ fix the introduces bugs
2.b/ convert the file/paths related functions
3/ finish the server side objects (devices...)
Solution 1:
3/
1/
2.a/
2.b/
A+
--
Eric Pouech
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel35/process.c dlls/kernel/process.c
--- dlls/kernel35/process.c 2003-09-18 20:48:27.000000000 +0200
+++ dlls/kernel/process.c 2003-09-18 20:37:57.000000000 +0200
@@ -385,6 +388,8 @@
/* registry initialisation */
SHELL_LoadRegistry();
+ FILE_InitPathNameSpace();
+
/* global boot finished, the rest is process-local */
CLIENT_BootDone( TRACE_ON(server) );
if (TRACE_ON(relay) || TRACE_ON(snoop)) RELAY_InitDebugLists();
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll35/dos_fs.c dlls/ntdll/dos_fs.c
--- dlls/ntdll35/dos_fs.c 1970-01-01 01:00:00.000000000 +0100
+++ dlls/ntdll/dos_fs.c 2003-09-18 20:52:40.000000000 +0200
@@ -0,0 +1,743 @@
+/*
+ * DOS file system functions
+ *
+ * Copyright 1993 Erik Bos
+ * Copyright 1996 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <assert.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_SYS_ERRNO_H
+#include <sys/errno.h>
+#endif
+
+#include <dirent.h>
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "wine/unicode.h"
+#include "wine/debug.h"
+#include "wine/server.h"
+#include "async.h"
+#include "ntdll_misc.h"
+#include "../files/smb.h"
+
+#include "winternl.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dos_fs);
+
+/* Chars we don't want to see in DOS file names */
+#define INVALID_DOS_CHARS "*?<>|\"+=,;[] \345"
+
+#define IS_END_OF_NAME(ch) (!(ch) || ((ch) == '/') || ((ch) == '\\'))
+
+/***********************************************************************
+ * DOSFS_ValidDOSName
+ *
+ * Return 1 if Unix file 'name' is also a valid MS-DOS name
+ * (i.e. contains only valid DOS chars, lower-case only, fits in 8.3 format).
+ * File name can be terminated by '\0', '\\' or '/'.
+ */
+static int DOSFS_ValidDOSName(LPCWSTR name, int ignore_case)
+{
+ static const char invalid_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" INVALID_DOS_CHARS;
+ const WCHAR *p = name;
+ const char *invalid = ignore_case ? (invalid_chars + 26) : invalid_chars;
+ int len = 0;
+
+ if (*p == '.')
+ {
+ /* Check for "." and ".." */
+ p++;
+ if (*p == '.') p++;
+ /* All other names beginning with '.' are invalid */
+ return (IS_END_OF_NAME(*p));
+ }
+ while (!IS_END_OF_NAME(*p))
+ {
+ if (*p < 256 && strchr(invalid, (char)*p)) return 0; /* Invalid char */
+ if (*p == '.') break; /* Start of the extension */
+ if (++len > 8) return 0; /* Name too long */
+ p++;
+ }
+ if (*p != '.') return 1; /* End of name */
+ p++;
+ if (IS_END_OF_NAME(*p)) return 0; /* Empty extension not allowed */
+ len = 0;
+ while (!IS_END_OF_NAME(*p))
+ {
+ if (*p < 256 && strchr(invalid, (char)*p)) return 0; /* Invalid char */
+ if (*p == '.') return 0; /* Second extension not allowed */
+ if (++len > 3) return 0; /* Extension too long */
+ p++;
+ }
+ return 1;
+}
+
+/***********************************************************************
+ * DOSFS_ToDosFCBFormat
+ *
+ * Convert a file name to DOS FCB format (8+3 chars, padded with blanks),
+ * expanding wild cards and converting to upper-case in the process.
+ * File name can be terminated by '\0', '\\' or '/'.
+ * Return FALSE if the name is not a valid DOS name.
+ * 'buffer' must be at least 12 characters long.
+ */
+static BOOL DOSFS_ToDosFCBFormat(LPCWSTR name, LPWSTR buffer)
+{
+ static const char invalid_chars[] = INVALID_DOS_CHARS;
+ LPCWSTR p = name;
+ int i;
+
+ /* Check for "." and ".." */
+ if (*p == '.')
+ {
+ p++;
+ buffer[0] = '.';
+ for(i = 1; i < 11; i++) buffer[i] = ' ';
+ buffer[11] = 0;
+ if (*p == '.')
+ {
+ buffer[1] = '.';
+ p++;
+ }
+ return IS_END_OF_NAME(*p);
+ }
+
+ for (i = 0; i < 8; i++)
+ {
+ switch (*p)
+ {
+ case '\0':
+ case '\\':
+ case '/':
+ case '.':
+ buffer[i] = ' ';
+ break;
+ case '?':
+ p++;
+ /* fall through */
+ case '*':
+ buffer[i] = '?';
+ break;
+ default:
+ if (*p < 256 && strchr(invalid_chars, (char)*p)) return FALSE;
+ buffer[i] = toupperW(*p);
+ p++;
+ break;
+ }
+ }
+
+ if (*p == '*')
+ {
+ /* Skip all chars after wildcard up to first dot */
+ while (*p && (*p != '/') && (*p != '\\') && (*p != '.')) p++;
+ }
+ else
+ {
+ /* Check if name too long */
+ if (*p && (*p != '/') && (*p != '\\') && (*p != '.')) return FALSE;
+ }
+ if (*p == '.') p++; /* Skip dot */
+
+ for (i = 8; i < 11; i++)
+ {
+ switch(*p)
+ {
+ case '\0':
+ case '\\':
+ case '/':
+ buffer[i] = ' ';
+ break;
+ case '.':
+ return FALSE; /* Second extension not allowed */
+ case '?':
+ p++;
+ /* fall through */
+ case '*':
+ buffer[i] = '?';
+ break;
+ default:
+ if (*p < 256 && strchr(invalid_chars, (char)*p)) return FALSE;
+ buffer[i] = toupperW(*p);
+ p++;
+ break;
+ }
+ }
+ buffer[11] = '\0';
+
+ /* at most 3 character of the extension are processed
+ * is something behind this ?
+ */
+ while (*p == '*' || *p == ' ') p++; /* skip wildcards and spaces */
+ return IS_END_OF_NAME(*p);
+}
+
+/***********************************************************************
+ * DOSFS_ToDosDTAFormat
+ *
+ * Convert a file name from FCB to DTA format (name.ext, null-terminated)
+ * converting to upper-case in the process.
+ * File name can be terminated by '\0', '\\' or '/'.
+ * 'buffer' must be at least 13 characters long.
+ */
+static void DOSFS_ToDosDTAFormat(LPCWSTR name, UNICODE_STRING* dst)
+{
+ LPWSTR p, d;
+
+ /* FIXME: check that we can store at least (8+1+3+1) * sizeof(WCHAR) in dst */
+ d = dst->Buffer + dst->Length / sizeof(WCHAR);
+ memcpy(d, name, 8 * sizeof(WCHAR));
+ p = d + 8;
+ while ((p > d) && (p[-1] == ' ')) p--;
+ *p++ = '.';
+ memcpy(p, name + 8, 3 * sizeof(WCHAR));
+ p += 3;
+ while (p[-1] == ' ') p--;
+ if (p[-1] == '.') p--;
+ *p = '\0';
+ dst->Length += (p - d) * sizeof(WCHAR);
+}
+
+/***********************************************************************
+ * DOSFS_Hash
+ *
+ * Transform a Unix file name into a hashed DOS name. If the name is a valid
+ * DOS name, it is converted to upper-case; otherwise it is replaced by a
+ * hashed version that fits in 8.3 format.
+ * File name can be terminated by '\0', '\\' or '/'.
+ * 'buffer' must be at least 13 characters long.
+ */
+static void DOSFS_Hash(LPCWSTR name, LPWSTR buffer, BOOL dir_format,
+ BOOL ignore_case)
+{
+ static const char invalid_chars[] = INVALID_DOS_CHARS "~.";
+ static const char hash_chars[32] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
+
+ LPCWSTR p, ext;
+ LPWSTR dst;
+ unsigned short hash;
+ int i;
+
+ if (dir_format)
+ {
+ for(i = 0; i < 11; i++) buffer[i] = ' ';
+ buffer[11] = 0;
+ }
+
+ if (DOSFS_ValidDOSName(name, ignore_case))
+ {
+ /* Check for '.' and '..' */
+ if (*name == '.')
+ {
+ buffer[0] = '.';
+ if (!dir_format) buffer[1] = buffer[2] = '\0';
+ if (name[1] == '.') buffer[1] = '.';
+ return;
+ }
+
+ /* Simply copy the name, converting to uppercase */
+
+ for (dst = buffer; !IS_END_OF_NAME(*name) && (*name != '.'); name++)
+ *dst++ = toupperW(*name);
+ if (*name == '.')
+ {
+ if (dir_format) dst = buffer + 8;
+ else *dst++ = '.';
+ for (name++; !IS_END_OF_NAME(*name); name++)
+ *dst++ = toupperW(*name);
+ }
+ if (!dir_format) *dst = '\0';
+ return;
+ }
+
+ /* Compute the hash code of the file name */
+ /* If you know something about hash functions, feel free to */
+ /* insert a better algorithm here... */
+ if (ignore_case)
+ {
+ for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
+ hash = (hash<<3) ^ (hash>>5) ^ tolowerW(*p) ^ (tolowerW(p[1]) << 8);
+ hash = (hash<<3) ^ (hash>>5) ^ tolowerW(*p); /* Last character */
+ }
+ else
+ {
+ for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
+ hash = (hash << 3) ^ (hash >> 5) ^ *p ^ (p[1] << 8);
+ hash = (hash << 3) ^ (hash >> 5) ^ *p; /* Last character */
+ }
+
+ /* Find last dot for start of the extension */
+ for (p = name+1, ext = NULL; !IS_END_OF_NAME(*p); p++)
+ if (*p == '.') ext = p;
+ if (ext && IS_END_OF_NAME(ext[1]))
+ ext = NULL; /* Empty extension ignored */
+
+ /* Copy first 4 chars, replacing invalid chars with '_' */
+ for (i = 4, p = name, dst = buffer; i > 0; i--, p++)
+ {
+ if (IS_END_OF_NAME(*p) || (p == ext)) break;
+ *dst++ = (*p < 256 && strchr(invalid_chars, (char)*p)) ? '_' : toupperW(*p);
+ }
+ /* Pad to 5 chars with '~' */
+ while (i-- >= 0) *dst++ = '~';
+
+ /* Insert hash code converted to 3 ASCII chars */
+ *dst++ = hash_chars[(hash >> 10) & 0x1f];
+ *dst++ = hash_chars[(hash >> 5) & 0x1f];
+ *dst++ = hash_chars[hash & 0x1f];
+
+ /* Copy the first 3 chars of the extension (if any) */
+ if (ext)
+ {
+ if (!dir_format) *dst++ = '.';
+ for (i = 3, ext++; (i > 0) && !IS_END_OF_NAME(*ext); i--, ext++)
+ *dst++ = (*ext < 256 && strchr(invalid_chars, (char)*ext)) ? '_' : toupperW(*ext);
+ }
+ if (!dir_format) *dst = '\0';
+}
+
+/* Define the VFAT ioctl to get both short and long file names */
+/* FIXME: is it possible to get this to work on other systems? */
+#ifdef linux
+/* We want the real kernel dirent structure, not the libc one */
+typedef struct
+{
+ long d_ino;
+ long d_off;
+ unsigned short d_reclen;
+ char d_name[256];
+} KERNEL_DIRENT;
+
+#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, KERNEL_DIRENT [2])
+
+/* To avoid blocking on non-directories in DOSFS_OpenDir_VFAT*/
+#ifndef O_DIRECTORY
+# define O_DIRECTORY 0200000 /* must be directory */
+#endif
+
+#else /* linux */
+#undef VFAT_IOCTL_READDIR_BOTH /* just in case... */
+#endif /* linux */
+
+#define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
+
+/*
+ * Directory info for DOSFS_ReadDir
+ * contains the names of *all* the files in the directory
+ */
+typedef struct
+{
+ int used;
+ int size;
+ WCHAR names[1];
+} DOS_DIR;
+
+/***********************************************************************
+ * DOSFS_AddDirEntry
+ *
+ * Used to construct an array of filenames in DOSFS_OpenDir
+ */
+static NTSTATUS DOSFS_AddDirEntry(DOS_DIR **dir, LPCWSTR name, LPCWSTR dosname)
+{
+ int extra1 = strlenW(name) + 1;
+ int extra2 = strlenW(dosname) + 1;
+
+ /* if we need more, at minimum double the size */
+ if ((extra1 + extra2 + (*dir)->used) > (*dir)->size)
+ {
+ int more = (*dir)->size;
+ DOS_DIR *t;
+
+ if (more < (extra1 + extra2)) more = extra1 + extra2;
+
+ t = RtlReAllocateHeap(ntdll_get_process_heap(), 0, *dir,
+ sizeof(**dir) + ((*dir)->size + more) * sizeof(WCHAR));
+ if (!t)
+ {
+ ERR("Out of memory caching directory structure %d %d %d\n",
+ (*dir)->size, more, (*dir)->used);
+ return STATUS_NO_MEMORY;
+ }
+ (*dir) = t;
+ (*dir)->size += more;
+ }
+
+ /* at this point, the dir structure is big enough to hold these names */
+ strcpyW(&(*dir)->names[(*dir)->used], name);
+ (*dir)->used += extra1;
+ strcpyW(&(*dir)->names[(*dir)->used], dosname);
+ (*dir)->used += extra2;
+
+ return STATUS_SUCCESS;
+}
+
+
+/***********************************************************************
+ * DOSFS_OpenDir_VFAT
+ */
+static NTSTATUS DOSFS_OpenDir_VFAT(const union cptable *table, const char *unix_path, DOS_DIR **dir)
+{
+#ifdef VFAT_IOCTL_READDIR_BOTH
+ KERNEL_DIRENT de[2];
+ int fd = open(unix_path, O_RDONLY|O_DIRECTORY);
+ NTSTATUS status = STATUS_SUCCESS;
+
+ /* Check if the VFAT ioctl is supported on this directory */
+ if (fd < 0) return STATUS_OBJECT_PATH_NOT_FOUND;
+
+ do
+ {
+ WCHAR long_name[MAX_PATH];
+ WCHAR short_name[12];
+
+ if (ioctl(fd, VFAT_IOCTL_READDIR_BOTH, (long)de) == -1)
+ {
+ status = STATUS_NOT_SUPPORTED;
+ break;
+ }
+ if (!de[0].d_reclen)
+ {
+ static const WCHAR empty_strW[] = { 0 };
+ DOSFS_AddDirEntry(dir, empty_strW, empty_strW);
+ break;
+ }
+ wine_cp_mbstowcs(table, 0, de[0].d_name, strlen(de[0].d_name) + 1,
+ long_name, MAX_PATH);
+ if (!DOSFS_ToDosFCBFormat(long_name, short_name))
+ short_name[0] = '\0';
+ if (de[1].d_name[0])
+ wine_cp_mbstowcs(table, 0, de[1].d_name, strlen(de[1].d_name) + 1,
+ long_name, MAX_PATH);
+ else
+ wine_cp_mbstowcs(table, 0, de[0].d_name, strlen(de[0].d_name) + 1,
+ long_name, MAX_PATH);
+ status = DOSFS_AddDirEntry(dir, long_name, short_name);
+ } while (status == STATUS_SUCCESS);
+ close(fd);
+ return status;
+#else
+ return STATUS_NOT_SUPPORTED;
+#endif /* VFAT_IOCTL_READDIR_BOTH */
+}
+
+
+/***********************************************************************
+ * DOSFS_OpenDir_Normal
+ *
+ * Now use the standard opendir/readdir interface
+ */
+static NTSTATUS DOSFS_OpenDir_Normal(const union cptable *table, const char *unix_path, DOS_DIR **dir)
+{
+ DIR *unixdir = opendir(unix_path);
+ NTSTATUS status = STATUS_SUCCESS;
+ static const WCHAR empty_strW[] = { 0 };
+
+ if (!unixdir) return FILE_GetNtStatus();
+ do
+ {
+ WCHAR long_name[MAX_PATH];
+ struct dirent *de = readdir(unixdir);
+
+ if (!de)
+ {
+ DOSFS_AddDirEntry(dir, empty_strW, empty_strW);
+ break;
+ }
+ wine_cp_mbstowcs(table, 0, de->d_name, strlen(de->d_name) + 1,
+ long_name, MAX_PATH);
+ status = DOSFS_AddDirEntry(dir, long_name, empty_strW);
+ } while (status == STATUS_SUCCESS);
+ closedir(unixdir);
+ return status;
+}
+
+/***********************************************************************
+ * DOSFS_OpenDir
+ */
+static NTSTATUS DOSFS_OpenDir(const union cptable *table, const char *unix_path, DOS_DIR** dir)
+{
+ const int init_size = 0x100;
+ NTSTATUS status;
+
+ TRACE("%s\n", debugstr_a(unix_path));
+
+ *dir = RtlAllocateHeap(ntdll_get_process_heap(), 0,
+ sizeof(**dir) + init_size * sizeof(WCHAR));
+ if (!*dir) return STATUS_NO_MEMORY;
+ (*dir)->used = 0;
+ (*dir)->size = init_size;
+
+ status = DOSFS_OpenDir_VFAT(table, unix_path, dir);
+
+ if (status != STATUS_SUCCESS)
+ status = DOSFS_OpenDir_Normal(table, unix_path, dir);
+
+ if (status != STATUS_SUCCESS)
+ {
+ RtlFreeHeap(ntdll_get_process_heap(), 0, *dir);
+ *dir = NULL;
+ }
+ else (*dir)->used = 0;
+
+ return status;
+}
+
+
+/***********************************************************************
+ * DOSFS_CloseDir
+ */
+static void DOSFS_CloseDir(DOS_DIR *dir)
+{
+ RtlFreeHeap(ntdll_get_process_heap(), 0, dir);
+}
+
+
+/***********************************************************************
+ * DOSFS_ReadDir
+ */
+static NTSTATUS DOSFS_ReadDir(DOS_DIR *dir, LPCWSTR *long_name,
+ LPCWSTR *short_name)
+{
+ LPCWSTR sn, ln;
+
+ /* the long pathname is first */
+ ln = &dir->names[dir->used];
+ if (!ln[0]) return STATUS_NO_MORE_ENTRIES;
+ *long_name = ln;
+ dir->used += (strlenW(ln) + 1);
+
+ /* followed by the short path name */
+ sn = &dir->names[dir->used];
+ if (sn[0])
+ *short_name = sn;
+ else
+ *short_name = NULL;
+ dir->used += (strlenW(sn) + 1);
+
+ return STATUS_SUCCESS;
+}
+
+
+/******************************************************************
+ * append
+ *
+ *
+ */
+static NTSTATUS append(struct nt_to_unix_path* paths,
+ const union cptable* cptable,
+ LPCWSTR element, unsigned len,
+ BOOL last, BOOL ignore_case, BOOL check)
+{
+ static WCHAR sepW[] = {'\\', '\0'};
+
+ WCHAR dos_name[12], tmp_buf[13];
+ LPCWSTR long_name, short_name;
+ DOS_DIR* dir;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ TRACE("(%s + %s@%d last%c nocase%c check=%c)\n", debugstr_an(paths->unix_str.Buffer, paths->unix_str.Length),
+ debugstr_wn(element, len), len, last ? '+':'-', ignore_case?'+':'-',check?'+':'-');
+
+ if (check)
+ {
+ if (!DOSFS_ToDosFCBFormat(element, dos_name)) dos_name[0] = '\0';
+
+ if ((status = DOSFS_OpenDir(cptable, paths->unix_str.Buffer, &dir)) != STATUS_SUCCESS)
+ {
+ WARN("(%s,%s): can't open dir: %s\n",
+ paths->unix_str.Buffer, debugstr_w(element), strerror(errno));
+ return status;
+ }
+
+ while ((status = DOSFS_ReadDir(dir, &long_name, &short_name)) == STATUS_SUCCESS)
+ {
+ /* Check against Unix name */
+ if (len == strlenW(long_name))
+ {
+ if (!ignore_case)
+ {
+ if (!strncmpW(long_name, element, len)) break;
+ }
+ else
+ {
+ if (!strncmpiW(long_name, element, len)) break;
+ }
+ }
+ if (dos_name[0])
+ {
+ /* Check against hashed DOS name */
+ if (!short_name)
+ {
+ DOSFS_Hash(long_name, tmp_buf, TRUE, ignore_case);
+ short_name = tmp_buf;
+ }
+ if (!strcmpW(dos_name, short_name)) break;
+ }
+ }
+ }
+ else
+ {
+ long_name = element;
+ short_name = NULL;
+ }
+ if (status == STATUS_SUCCESS)
+ {
+ INT len;
+
+ len = wine_cp_wcstombs(cptable, 0, long_name,
+ strlenW(long_name) + 1,
+ &paths->unix_str.Buffer[paths->unix_str.Length],
+ paths->unix_str.MaximumLength - paths->unix_str.Length,
+ NULL, NULL);
+ if (len > 0) paths->unix_str.Length += len - 1;
+ else status = STATUS_BUFFER_TOO_SMALL;
+
+ if (status == STATUS_SUCCESS && !last)
+ {
+ paths->unix_str.Buffer[paths->unix_str.Length++] = '/';
+ paths->unix_str.Buffer[paths->unix_str.Length] = '\0';
+ }
+ if (status == STATUS_SUCCESS && paths->long_ustr.Buffer)
+ {
+ status = RtlAppendUnicodeToString(&paths->long_ustr, long_name);
+ if (!last) status = RtlAppendUnicodeToString(&paths->long_ustr, sepW);
+ }
+ if (status == STATUS_SUCCESS && paths->short_ustr.Buffer)
+ {
+ if (short_name)
+ DOSFS_ToDosDTAFormat(short_name, &paths->short_ustr);
+ else
+ {
+ DOSFS_Hash(long_name, tmp_buf, FALSE, ignore_case);
+ status = RtlAppendUnicodeToString(&paths->short_ustr, tmp_buf);
+ }
+ if (!last) status = RtlAppendUnicodeToString(&paths->short_ustr, sepW);
+ }
+ TRACE("-> %s,%s,%s (%lx)\n",
+ paths->unix_str.Buffer, debugstr_w(long_name),
+ paths->short_ustr.Buffer ? debugstr_w(paths->short_ustr.Buffer) : "***", status);
+ }
+ else
+ WARN("%s not found in '%s'\n", debugstr_wn(element, len), paths->unix_str.Buffer);
+ if (check) DOSFS_CloseDir(dir);
+ return status;
+}
+
+/******************************************************************
+ * FILE_GetUnixName
+ *
+ *
+ */
+NTSTATUS FILE_GetUnixName(const UNICODE_STRING* win_ustr, BOOL check_last,
+ struct nt_to_unix_path* paths)
+{
+ WCHAR b[2048]; /* FIXME: make it a growable string */
+ unsigned len = 0, dir_len = 0, name_ofs = 0, i, lasti;
+ NTSTATUS status;
+ const union cptable* cptable;
+ unsigned codepage;
+
+ TRACE("Lookup %s\n",
+ debugstr_wn(win_ustr->Buffer, win_ustr->Length / sizeof(WCHAR)));
+
+ SERVER_START_REQ(get_file_name)
+ {
+ wine_server_add_data(req, win_ustr->Buffer, win_ustr->Length);
+ wine_server_set_reply(req, b, sizeof(b));
+ status = wine_server_call(req);
+ if (status == STATUS_SUCCESS)
+ {
+ len = wine_server_reply_size(reply) / sizeof(WCHAR);
+ dir_len = reply->dir_len / sizeof(WCHAR);
+ name_ofs = reply->name_offset;
+ codepage = reply->codepage;
+ paths->flags = reply->flags;
+ }
+ }
+ SERVER_END_REQ;
+ if (status != STATUS_SUCCESS) return status;
+
+ /* FIXME: should we return an error here ?? */
+ if (!(cptable = wine_cp_get_table(codepage)))
+ cptable = wine_cp_get_table(1252); /* ansi */
+
+ TRACE("\t\t=> %s extra=%s name=%s\n",
+ debugstr_wn(b, dir_len),
+ debugstr_wn(&b[dir_len], len - dir_len),
+ debugstr_wn(&win_ustr->Buffer[name_ofs],
+ win_ustr->Length / sizeof(WCHAR) - name_ofs));
+ if (len > dir_len)
+ {
+ int i;
+ paths->unix_str.Length = len - dir_len;
+ /* FIXME (extra data should be ASCII, not Unicode) */
+ for (i = 0; i < len - dir_len; i++)
+ paths->unix_str.Buffer[i] = b[dir_len + i];
+ paths->unix_str.Buffer[paths->unix_str.Length++] = '/';
+ }
+ else paths->unix_str.Length = 0; /* FIXME: case of error ??? */
+ paths->unix_str.Buffer[paths->unix_str.Length] = '\0';
+
+ if (paths->short_ustr.Buffer)
+ {
+ paths->short_ustr.Length = 0;
+ paths->short_ustr.Buffer[0] = '\0';
+ }
+ if (paths->long_ustr.Buffer)
+ {
+ paths->long_ustr.Length = 0;
+ paths->long_ustr.Buffer[0] = '\0';
+ }
+ for (i = lasti = 0; i < win_ustr->Length / sizeof(WCHAR) - name_ofs; i++)
+ {
+ switch (win_ustr->Buffer[name_ofs + i])
+ {
+ case '\\':
+ case '/':
+ append(paths, cptable, &win_ustr->Buffer[name_ofs + lasti],
+ i - lasti, FALSE, !(paths->flags & PATHGATE_CASE_SENSITIVE), TRUE);
+ lasti = i + 1;
+ break;
+ }
+ }
+ if (i != lasti)
+ status = append(paths, cptable, &win_ustr->Buffer[name_ofs + lasti],
+ i - lasti, TRUE, !(paths->flags & PATHGATE_CASE_SENSITIVE),
+ check_last);
+
+ TRACE("\tunix=%s\n", debugstr_an(paths->unix_str.Buffer, paths->unix_str.Length));
+ if (paths->short_ustr.Buffer)
+ TRACE("\tshort=%s\n", debugstr_wn(paths->short_ustr.Buffer, paths->short_ustr.Length / sizeof(WCHAR)));
+ if (paths->long_ustr.Buffer)
+ TRACE("\tlong=%s\n", debugstr_wn(paths->long_ustr.Buffer, paths->long_ustr.Length / sizeof(WCHAR)));
+
+ return status;
+}
+
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll35/file.c dlls/ntdll/file.c
--- dlls/ntdll35/file.c 2003-08-24 10:15:12.000000000 +0200
+++ dlls/ntdll/file.c 2003-09-18 20:57:15.000000000 +0200
@@ -1,5 +1,6 @@
/*
* Copyright 1999, 2000 Juergen Schmied
+ * 2003, Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -38,13 +39,14 @@
#include "wine/server.h"
#include "async.h"
#include "ntdll_misc.h"
-#include "file.h" /* FIXME */
#include "../files/smb.h"
#include "winternl.h"
#include "winioctl.h"
-WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
+WINE_DEFAULT_DEBUG_CHANNEL(ntfile);
+
+static BOOL init_done;
/**************************************************************************
* NtOpenFile [NTDLL.@]
@@ -64,61 +66,11 @@
* Success: 0. FileHandle and IoStatusBlock are updated.
* Failure: An NTSTATUS error code describing the error.
*/
-NTSTATUS WINAPI NtOpenFile(
- OUT PHANDLE FileHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes,
- OUT PIO_STATUS_BLOCK IoStatusBlock,
- ULONG ShareAccess,
- ULONG OpenOptions)
+NTSTATUS WINAPI NtOpenFile(PHANDLE phndl, ACCESS_MASK access, POBJECT_ATTRIBUTES oa,
+ PIO_STATUS_BLOCK iosb, ULONG share, ULONG options)
{
- LPWSTR filename;
- static const WCHAR szDosDevices[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
- 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);
-
- dump_ObjectAttributes (ObjectAttributes);
-
- if(ObjectAttributes->RootDirectory)
- {
- FIXME("Object root directory unknown %p\n",
- ObjectAttributes->RootDirectory);
- return STATUS_OBJECT_NAME_NOT_FOUND;
- }
-
- filename = ObjectAttributes->ObjectName->Buffer;
-
- /* FIXME: DOSFS stuff should call here, not vice-versa */
- if(strncmpW(filename, szDosDevices, strlenW(szDosDevices)))
- return STATUS_OBJECT_NAME_NOT_FOUND;
-
- /* FIXME: this calls SetLastError() -> bad */
- if(!DOSFS_GetFullName(&filename[strlenW(szDosDevices)], TRUE,
- &full_name))
- return STATUS_OBJECT_NAME_NOT_FOUND;
-
- /* FIXME: modify server protocol so
- create file takes an OBJECT_ATTRIBUTES structure */
- SERVER_START_REQ( create_file )
- {
- req->access = DesiredAccess;
- req->inherit = 0;
- req->sharing = ShareAccess;
- req->create = OPEN_EXISTING;
- req->attrs = 0;
- req->drive_type = GetDriveTypeW( full_name.short_name );
- wine_server_add_data( req, full_name.long_name, strlen(full_name.long_name) );
- SetLastError(0);
- r = wine_server_call( req );
- *FileHandle = reply->handle;
- }
- SERVER_END_REQ;
-
- return r;
+ return NtCreateFile(phndl, access, oa, iosb, NULL, 0,
+ share, FILE_OPEN, options, NULL, 0);
}
/**************************************************************************
@@ -145,25 +97,157 @@
* Success: 0. FileHandle and IoStatusBlock are updated.
* Failure: An NTSTATUS error code describing the error.
*/
-NTSTATUS WINAPI NtCreateFile(
- OUT PHANDLE FileHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes,
- OUT PIO_STATUS_BLOCK IoStatusBlock,
- PLARGE_INTEGER AllocateSize,
- ULONG FileAttributes,
- ULONG ShareAccess,
- ULONG CreateDisposition,
- ULONG CreateOptions,
- PVOID EaBuffer,
- ULONG EaLength)
-{
- FIXME("(%p,0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx) stub\n",
- FileHandle,DesiredAccess,ObjectAttributes,
- IoStatusBlock,AllocateSize,FileAttributes,
- ShareAccess,CreateDisposition,CreateOptions,EaBuffer,EaLength);
- dump_ObjectAttributes (ObjectAttributes);
- return 0;
+NTSTATUS WINAPI NtCreateFile(OUT PHANDLE FileHandle,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ PLARGE_INTEGER AllocateSize,
+ ULONG FileAttributes,
+ ULONG ShareAccess,
+ ULONG CreateDisposition,
+ ULONG CreateOptions,
+ PVOID EaBuffer,
+ ULONG EaLength)
+{
+ char buffer[2048]; /* FIXME */
+ WCHAR bs[2048], bl[2048]; /* FIXME */
+ UNICODE_STRING ntstr;
+ struct nt_to_unix_path paths;
+ BOOL check_last, unix_path = FALSE;
+
+ TRACE("(%p,0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx)\n",
+ FileHandle,DesiredAccess,ObjectAttributes,
+ IoStatusBlock,AllocateSize,FileAttributes,
+ ShareAccess,CreateDisposition,CreateOptions,EaBuffer,EaLength);
+ dump_ObjectAttributes (ObjectAttributes);
+
+ if (AllocateSize || CreateOptions || EaBuffer || EaLength)
+ {
+ FIXME("Unsupported parameter\n");
+ return IoStatusBlock->u.Status = STATUS_NOT_IMPLEMENTED;
+ }
+ if (DesiredAccess & (FILE_LIST_DIRECTORY|FILE_TRAVERSE))
+ {
+ FIXME("Cannot handle directories yet\n");
+ return IoStatusBlock->u.Status = STATUS_NOT_IMPLEMENTED;
+ }
+ if (ObjectAttributes->RootDirectory)
+ {
+ FIXME("Cannot handle non-absolute file names yet\n");
+ return IoStatusBlock->u.Status = STATUS_NOT_IMPLEMENTED;
+ }
+ /* FIXME, the string is perhaps not null terminated */
+ if (ObjectAttributes->ObjectName->Buffer[ObjectAttributes->ObjectName->Length / sizeof(WCHAR)] != '\0')
+ FIXME("Non terminated object attribute string\n");
+
+ paths.unix_str.Buffer = buffer;
+ paths.unix_str.Length = 0;
+ paths.unix_str.MaximumLength = sizeof(buffer);
+
+ paths.short_ustr.Buffer = bs;
+ paths.short_ustr.Length = 0;
+ paths.short_ustr.MaximumLength = sizeof(bs);
+
+ paths.long_ustr.Buffer = bl;
+ paths.long_ustr.Length = 0;
+ paths.long_ustr.MaximumLength = sizeof(bl);
+
+ if (!init_done) unix_path = TRUE;
+ else if (ObjectAttributes->ObjectName->Buffer[0] == '/')
+ {
+ /* may this is a fully qualified UNIX path... try to map it to a windows pathgate
+ */
+ WCHAR tmp[] = {'\\','?','?','\\','A',':','\\',0};
+
+ ntstr.Buffer = tmp;
+ ntstr.Length = 7 * sizeof(WCHAR);
+ ntstr.MaximumLength = 8 * sizeof(WCHAR);
+ for (tmp[4] = 'A'; tmp[4] <= 'Z'; tmp[4]++)
+ {
+ if (!FILE_GetUnixName(&ntstr, TRUE, &paths))
+ {
+ int i;
+
+ /* FIXME: use proper conversion here... (and path gate codepage) */
+ for (i = 0; i < paths.unix_str.Length; i++)
+ if (ObjectAttributes->ObjectName->Buffer[i] != paths.unix_str.Buffer[i]) break;
+ if (i == paths.unix_str.Length)
+ {
+ TRACE("Got mapping %s => %s\n", debugstr_w(tmp), paths.unix_str.Buffer);
+ unix_path = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ if (unix_path)
+ {
+ IoStatusBlock->u.Status = RtlUnicodeStringToAnsiString(&paths.unix_str, ObjectAttributes->ObjectName, FALSE);
+ }
+ else
+ {
+ if (!RtlDosPathNameToNtPathName_U(ObjectAttributes->ObjectName->Buffer,
+ &ntstr, NULL, NULL))
+ return IoStatusBlock->u.Status = STATUS_OBJECT_NAME_INVALID;
+ switch (CreateDisposition)
+ {
+ case FILE_SUPERSEDE:
+ case FILE_CREATE:
+ case FILE_OPEN_IF:
+ case FILE_OVERWRITE_IF:
+ check_last = FALSE;
+ break;
+ case FILE_OPEN:
+ case FILE_OVERWRITE:
+ check_last = TRUE;
+ break;
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ IoStatusBlock->u.Status = FILE_GetUnixName(&ntstr, check_last, &paths);
+ }
+
+ if (IoStatusBlock->u.Status == STATUS_SUCCESS)
+ {
+ if (paths.unix_str.Buffer[0] == '/')
+ {
+ again:
+ SERVER_START_REQ( create_file )
+ {
+ req->access = DesiredAccess;
+ req->inherit = ObjectAttributes->Attributes & OBJ_INHERIT;
+ req->sharing = ShareAccess;
+ req->create = CreateDisposition;
+ req->attrs = FileAttributes;
+ wine_server_add_data( req, paths.unix_str.Buffer, paths.unix_str.Length );
+ IoStatusBlock->u.Status = wine_server_call( req );
+ *FileHandle = reply->handle;
+ }
+ SERVER_END_REQ;
+
+ if (((IoStatusBlock->u.Status == STATUS_MEDIA_WRITE_PROTECTED) ||
+ (IoStatusBlock->u.Status == STATUS_ACCESS_DENIED)) &&
+ !(paths.flags & PATHGATE_FAIL_READ_ONLY) &&
+ !(FileAttributes & FILE_ATTRIBUTE_READONLY) &&
+ (DesiredAccess & GENERIC_WRITE))
+ {
+ TRACE("Write access failed for file '%s', "
+ "trying without write access\n",
+ debugstr_an(paths.unix_str.Buffer, paths.unix_str.Length));
+ DesiredAccess &= ~GENERIC_WRITE;
+ goto again;
+ }
+ }
+ else IoStatusBlock->u.Status = STATUS_NOT_IMPLEMENTED; /* device */
+ }
+
+ if (!unix_path) RtlFreeUnicodeString(&ntstr);
+
+ /* FIXME: IoStatusBlock.Information hadn't been set */
+
+ return IoStatusBlock->u.Status;
}
/***********************************************************************
@@ -250,12 +334,12 @@
* Retrieve the Nt Status code from errno.
* Try to be consistent with FILE_SetDosError().
*/
-static DWORD FILE_GetNtStatus(void)
+DWORD FILE_GetNtStatus(void)
{
int err = errno;
DWORD nt;
- TRACE( "errno = %d\n", errno );
+ TRACE( "errno = %d\n", err );
switch (err)
{
case EAGAIN: nt = STATUS_SHARING_VIOLATION; break;
@@ -271,6 +355,7 @@
case EINVAL:
case ENOTEMPTY: nt = STATUS_DIRECTORY_NOT_EMPTY; break;
case EPIPE: nt = STATUS_PIPE_BROKEN; break;
+ case ENOTDIR: nt = STATUS_NOT_A_DIRECTORY; break;
case ENOEXEC: /* ?? */
case ESPIPE: /* ?? */
case EEXIST: /* ?? */
@@ -434,7 +519,6 @@
switch (type)
{
case FD_TYPE_SMB:
- FIXME("NIY-SMB\n");
close(unix_handle);
return SMB_ReadFile(hFile, buffer, length, io_status);
@@ -553,9 +637,6 @@
TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p)!\n",
hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
- TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
- hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
-
io_status->Information = 0;
io_status->u.Status = FILE_GetUnixHandleType( hFile, GENERIC_WRITE, &type, &flags, &unix_handle );
@@ -945,7 +1026,6 @@
status = wine_server_call( req );
}
SERVER_END_REQ;
- status = STATUS_SUCCESS;
}
break;
default:
@@ -1220,3 +1300,325 @@
SERVER_END_REQ;
return status;
}
+
+/* Known filesystem types */
+
+typedef struct
+{
+ const WCHAR name[6];
+ UINT flags;
+} FS_DESCR;
+
+static const FS_DESCR known_filesystems[] =
+{
+ { {'u','n','i','x',0}, PATHGATE_CASE_SENSITIVE | PATHGATE_CASE_PRESERVING },
+ { {'m','s','d','o','s',0}, PATHGATE_SHORT_NAMES },
+ { {'d','o','s',0}, PATHGATE_SHORT_NAMES },
+ { {'f','a','t',0}, PATHGATE_SHORT_NAMES },
+ { {'v','f','a','t',0}, PATHGATE_CASE_PRESERVING },
+ { {'w','i','n','9','5',0}, PATHGATE_CASE_PRESERVING },
+ { { 0 }, 0 }
+};
+
+/***********************************************************************
+ * get_fs_flags
+ */
+static UINT get_fs_flags(int drive, LPCWSTR value)
+{
+ const FS_DESCR *descr;
+
+ for (descr = known_filesystems; *descr->name; descr++)
+ if (!strcmpiW( value, descr->name )) return descr->flags;
+ MESSAGE("Drive %c: unknown filesystem type %s, defaulting to 'win95'.\n",
+ 'A' + drive, debugstr_w(value) );
+ return PATHGATE_CASE_PRESERVING;
+}
+
+static void add_node(const WCHAR* root, size_t root_len,
+ const WCHAR* name, size_t name_len,
+ const WCHAR* extra, size_t extra_len,
+ unsigned codepage, unsigned flags)
+{
+ SERVER_START_REQ( create_pathgate )
+ {
+ req->codepage = codepage;
+ req->flags = flags;
+ req->root_len = root_len * sizeof(WCHAR);
+ req->name_len = name_len * sizeof(WCHAR);
+ wine_server_add_data( req, root, root_len * sizeof(WCHAR) );
+ wine_server_add_data( req, name, name_len * sizeof(WCHAR) );
+ if (extra) wine_server_add_data( req, extra, extra_len * sizeof(WCHAR));
+ wine_server_call( req );
+ }
+ SERVER_END_REQ;
+}
+
+#define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
+/* FIXME */
+extern void CDROM_InitRegistry(int);
+
+void FILE_InitPathNameSpace(void)
+{
+ static const WCHAR ntroot[] = {'\\','\0'};
+ static const WCHAR unc[] = {'U','N','C','\0'};
+ static const WCHAR dos[] = {'?','?','\0'};
+ static const WCHAR rdos[] = {'\\','?','?','\0'};
+
+ if (!CLIENT_IsBootThread()) return; /* already loaded */
+
+ int i, len, count = 0;
+ WCHAR driveW[] = {'M','a','c','h','i','n','e','\\','S','o','f','t','w','a','r','e','\\',
+ 'W','i','n','e','\\','W','i','n','e','\\',
+ 'C','o','n','f','i','g','\\','D','r','i','v','e',' ','A',0};
+ WCHAR drive_env[] = {'=','A',':',0};
+#define MAX_PATHNAME_LEN 1024 /* FIXME */
+ WCHAR path[MAX_PATHNAME_LEN];
+ char tmp[MAX_PATHNAME_LEN*sizeof(WCHAR) + sizeof(KEY_VALUE_PARTIAL_INFORMATION)];
+ struct stat drive_stat_buffer;
+ LPWSTR p;
+ LPSTR root, device;
+ HKEY hkey;
+ DWORD dummy;
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING nameW;
+ unsigned codepage, drivetype, driveflags = 0;
+
+ static const WCHAR PathW[] = {'P','a','t','h',0};
+ static const WCHAR CodepageW[] = {'C','o','d','e','p','a','g','e',0};
+ static const WCHAR LabelW[] = {'L','a','b','e','l',0};
+/* EPP static const WCHAR SerialW[] = {'S','e','r','i','a','l',0}; */
+ static const WCHAR TypeW[] = {'T','y','p','e',0};
+ static const WCHAR FilesystemW[] = {'F','i','l','e','s','y','s','t','e','m',0};
+ static const WCHAR DeviceW[] = {'D','e','v','i','c','e',0};
+ static const WCHAR ReadVolInfoW[] = {'R','e','a','d','V','o','l','I','n','f','o',0};
+ static const WCHAR FailReadOnlyW[] = {'F','a','i','l','R','e','a','d','O','n','l','y',0};
+/* EPP static const WCHAR driveC_labelW[] = {'D','r','i','v','e',' ','C',' ',' ',' ',' ',0}; */
+
+ /* system */
+ add_node(ntroot, strlenW(ntroot), dos, strlenW(dos), NULL, 0, 1242, 0);
+ add_node(rdos, strlenW(rdos), unc, strlenW(unc), NULL, 0, 1242, 0);
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = &nameW;
+ attr.Attributes = 0;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+
+ for (i = 0; i < 26 /* FIXME MAX_DOS_DRIVES */; i++)
+ {
+ RtlInitUnicodeString( &nameW, driveW );
+ nameW.Buffer[(nameW.Length / sizeof(WCHAR)) - 1] = 'A' + i;
+ if (NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr ) != STATUS_SUCCESS) continue;
+
+ /* Get the code page number */
+ RtlInitUnicodeString( &nameW, CodepageW );
+ if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
+ {
+ WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
+ codepage = strtolW( data, NULL, 10 );
+ } else codepage = 1252; /* ansi */
+
+ /* Get the root path */
+ RtlInitUnicodeString( &nameW, PathW );
+ if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
+ {
+ WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
+ ExpandEnvironmentStringsW( data, path, sizeof(path)/sizeof(WCHAR) );
+
+ p = path + strlenW(path) - 1;
+ while ((p > path) && (*p == '/')) *p-- = '\0';
+
+ if (path[0] == '/')
+ {
+ len = WideCharToMultiByte(codepage, 0, path, -1, NULL, 0, NULL, NULL);
+ root = RtlAllocateHeap(ntdll_get_process_heap(), 0, len);
+ WideCharToMultiByte(codepage, 0, path, -1, root, len, NULL, NULL);
+ }
+ else
+ {
+ /* relative paths are relative to config dir */
+ const char *config = wine_get_config_dir();
+ len = strlen(config);
+ len += WideCharToMultiByte(codepage, 0, path, -1, NULL, 0, NULL, NULL) + 2;
+ root = RtlAllocateHeap( ntdll_get_process_heap(), 0, len );
+ len -= sprintf( root, "%s/", config );
+ WideCharToMultiByte(codepage, 0, path, -1,
+ root + strlen(root), len, NULL, NULL);
+ }
+
+ if (stat( root, &drive_stat_buffer ))
+ {
+ MESSAGE("Could not stat %s (%s), ignoring drive %c:\n",
+ root, strerror(errno), 'A' + i);
+ RtlFreeHeap( ntdll_get_process_heap(), 0, root );
+ root = NULL;
+ goto next;
+ }
+ if (!S_ISDIR(drive_stat_buffer.st_mode))
+ {
+ MESSAGE("%s is not a directory, ignoring drive %c:\n",
+ root, 'A' + i );
+ RtlFreeHeap( ntdll_get_process_heap(), 0, root );
+ root = NULL;
+ goto next;
+ }
+
+#if 0
+ drive->dos_cwd = HeapAlloc(ntdll_get_process_heap(), HEAP_ZERO_MEMORY, sizeof(drive->dos_cwd[0]));
+ drive->unix_cwd = heap_strdup( "" );
+ drive->device = NULL;
+ drive->flags = 0;
+ drive->dev = drive_stat_buffer.st_dev;
+ drive->ino = drive_stat_buffer.st_ino;
+#endif
+
+ /* Get the drive type */
+ RtlInitUnicodeString( &nameW, TypeW );
+ if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
+ {
+ WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
+ TRACE("Got type %s\n", debugstr_w(data));
+ drivetype = DRIVE_FIXED; //DRIVE_GetDriveType( i, data );
+ }
+ else drivetype = DRIVE_FIXED;
+
+ /* Get the drive label */
+ RtlInitUnicodeString( &nameW, LabelW );
+ if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
+ {
+ WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
+ TRACE("Got label %s\n", debugstr_w(data));
+ // lstrcpynW( drive->label_conf, data, 12 );
+ }
+#if 0
+ if ((len = strlenW(drive->label_conf)) < 11)
+ {
+ /* Pad label with spaces */
+ while(len < 11) drive->label_conf[len++] = ' ';
+ drive->label_conf[11] = '\0';
+ }
+#endif
+
+#if 0
+ /* Get the serial number */
+ RtlInitUnicodeString( &nameW, SerialW );
+ if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
+ {
+ WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
+ drive->serial_conf = strtoulW( data, NULL, 16 );
+ }
+ else drive->serial_conf = 12345678;
+#endif
+
+ /* Get the filesystem type */
+ RtlInitUnicodeString( &nameW, FilesystemW );
+ if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
+ {
+ WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
+ driveflags = get_fs_flags( i, data );
+ }
+ else driveflags = PATHGATE_CASE_PRESERVING;
+
+ /* Get the device */
+ RtlInitUnicodeString( &nameW, DeviceW );
+ if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
+ {
+ WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
+ len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL);
+ device = RtlAllocateHeap(ntdll_get_process_heap(), 0, len);
+ WideCharToMultiByte(codepage, 0, data, -1, device, len, NULL, NULL);
+
+ RtlInitUnicodeString( &nameW, ReadVolInfoW );
+ if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
+ {
+ WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
+ if (IS_OPTION_TRUE(data[0])) driveflags |= PATHGATE_READ_VOL_INFO;
+ }
+ else driveflags |= PATHGATE_READ_VOL_INFO;
+
+ if (drivetype == DRIVE_CDROM)
+ {
+ int cd_fd;
+ if ((cd_fd = open(device, O_RDONLY|O_NONBLOCK)) != -1)
+ {
+ CDROM_InitRegistry(cd_fd);
+ close(cd_fd);
+ }
+ }
+ }
+
+ /* Get the FailReadOnly flag */
+ RtlInitUnicodeString( &nameW, FailReadOnlyW );
+ if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
+ {
+ WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
+ if (IS_OPTION_TRUE(data[0])) driveflags |= PATHGATE_FAIL_READ_ONLY;
+ }
+
+#if 0
+ /* Make the first hard disk the current drive */
+ if ((DRIVE_CurDrive == -1) && (drive->type == DRIVE_FIXED))
+ DRIVE_CurDrive = i;
+#endif
+ count++;
+#if 0
+ TRACE("Drive %c: path=%s type=%s label=%s serial=%08lx "
+ "flags=%08x codepage=%u dev=%x ino=%x\n",
+ 'A' + i, root, debugstr_w(DRIVE_Types[drive->type]),
+ debugstr_w(drive->label_conf), drive->serial_conf, drive->flags,
+ drive->codepage, (int)drive->dev, (int)drive->ino );
+#else
+ TRACE("Drive %c: path=%s type=%d label=-<>- serial=-<>- "
+ "flags=%08x codepage=%u\n",
+ 'A' + i, root, drivetype, driveflags, codepage);
+#endif
+ drive_env[1] = 'A' + i;
+ TRACE("Adding drive %c => %s/%s\n", 'A' + i, root, debugstr_w(path));
+ add_node(rdos, strlenW(rdos), drive_env + 1, strlenW(drive_env + 1), path, strlenW(path),
+ codepage, 0);
+ }
+
+ next:
+ NtClose( hkey );
+ }
+ init_done = TRUE;
+#if 0
+ if (!count)
+ {
+ MESSAGE("Warning: no valid DOS drive found, check your configuration file.\n" );
+ /* Create a C drive pointing to Unix root dir */
+ DOSDrives[2].root = heap_strdup( "/" );
+ DOSDrives[2].dos_cwd = RtlAllocateHeap(ntdll_get_process_heap(), HEAP_ZERO_MEMORY, sizeof(DOSDrives[2].dos_cwd[0]));
+ DOSDrives[2].unix_cwd = heap_strdup( "" );
+ strcpyW( DOSDrives[2].label_conf, driveC_labelW );
+ DOSDrives[2].serial_conf = 12345678;
+ DOSDrives[2].type = DRIVE_FIXED;
+ DOSDrives[2].device = NULL;
+ DOSDrives[2].flags = 0;
+ DRIVE_CurDrive = 2;
+ }
+
+ /* Make sure the current drive is valid */
+ if (DRIVE_CurDrive == -1)
+ {
+ for (i = 0, drive = DOSDrives; i < MAX_DOS_DRIVES; i++, drive++)
+ {
+ if (drive->root && !(drive->flags & DRIVE_DISABLED))
+ {
+ DRIVE_CurDrive = i;
+ break;
+ }
+ }
+ }
+
+ /* get current working directory info for all drives */
+ for (i = 0; i < MAX_DOS_DRIVES; i++, drive_env[1]++)
+ {
+ if (!GetEnvironmentVariableW(drive_env, path, MAX_PATHNAME_LEN)) continue;
+ /* sanity check */
+ if (toupperW(path[0]) != drive_env[1] || path[1] != ':') continue;
+ DRIVE_Chdir( i, path + 2 );
+ }
+#endif
+}
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll35/Makefile.in dlls/ntdll/Makefile.in
--- dlls/ntdll35/Makefile.in 2003-09-18 20:48:32.000000000 +0200
+++ dlls/ntdll/Makefile.in 2003-09-18 19:37:13.000000000 +0200
@@ -43,6 +43,7 @@
cdrom.c \
critsection.c \
debugtools.c \
+ dos_fs.c \
env.c \
error.c \
exception.c \
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll35/ntdll_misc.h dlls/ntdll/ntdll_misc.h
--- dlls/ntdll35/ntdll_misc.h 2003-09-13 21:06:36.000000000 +0200
+++ dlls/ntdll/ntdll_misc.h 2003-09-16 22:27:37.000000000 +0200
@@ -58,6 +58,25 @@
return NtCurrentTeb()->Peb->ProcessParameters;
}
+/* File IO */
+/* path gates options */
+#define PATHGATE_SHORT_NAMES 0x0002 /* Drive fs has 8.3 file names */
+#define PATHGATE_CASE_SENSITIVE 0x0004 /* Drive fs is case sensitive */
+#define PATHGATE_CASE_PRESERVING 0x0008 /* Drive fs is case preserving */
+#define PATHGATE_FAIL_READ_ONLY 0x0010 /* Fail opening read-only files for writing */
+#define PATHGATE_READ_VOL_INFO 0x0020 /* Try to read volume info from the device? */
+
+struct nt_to_unix_path {
+ ANSI_STRING unix_str;
+ UNICODE_STRING short_ustr;
+ UNICODE_STRING long_ustr;
+ unsigned flags;
+};
+extern NTSTATUS FILE_GetUnixName(const UNICODE_STRING* win_ustr, BOOL check_last,
+ struct nt_to_unix_path* n2up);
+
+extern DWORD FILE_GetNtStatus(void);
+
/* Device IO */
/* ntdll/cdrom.c.c */
extern NTSTATUS CDROM_DeviceIoControl(DWORD clientID, HANDLE hDevice,
diff -u -N -r -x '*~' -x '.#*' -x CVS files35/file.c files/file.c
--- files35/file.c 2003-09-18 20:48:44.000000000 +0200
+++ files/file.c 2003-09-18 20:54:37.000000000 +0200
@@ -404,6 +404,7 @@
DWORD attributes, HANDLE template, BOOL fail_read_only,
UINT drive_type )
{
+#if 0
unsigned int err;
HANDLE ret;
@@ -453,6 +454,54 @@
if (!ret) WARN("Unable to create file '%s' (GLE %ld)\n", filename, GetLastError());
return ret;
}
+#else
+ HANDLE h;
+ UNICODE_STRING u;
+ OBJECT_ATTRIBUTES oa;
+ IO_STATUS_BLOCK iosb;
+ ULONG disp;
+
+ oa.Length = sizeof(oa);
+ oa.ObjectName = &u;
+ oa.RootDirectory = 0;
+ oa.SecurityDescriptor = NULL;
+ oa.SecurityQualityOfService = NULL;
+ oa.Attributes = 0;
+ if (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle)
+ oa.Attributes |= OBJ_INHERIT;
+
+ RtlCreateUnicodeStringFromAsciiz(&u, filename);
+
+ switch (creation)
+ {
+ case CREATE_ALWAYS: disp = FILE_SUPERSEDE; break;
+ case CREATE_NEW: disp = FILE_CREATE; break;
+ case OPEN_ALWAYS: disp = FILE_OPEN_IF; break;
+ case OPEN_EXISTING: disp = FILE_OPEN; break;
+ case TRUNCATE_EXISTING: disp = FILE_OVERWRITE; break;
+ default: FIXME("Unknown creation flag\n"); disp = FILE_OPEN;
+ }
+ NtCreateFile(&h, access, &oa, &iosb, NULL, attributes,
+ sharing, disp, 0, NULL, 0);
+ RtlFreeUnicodeString(&u);
+
+ if (iosb.u.Status)
+ {
+ /* In the case file creation was rejected due to CREATE_NEW flag
+ * was specified and file with that name already exists, correct
+ * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS.
+ * Note: RtlNtStatusToDosError is not the subject to blame here.
+ */
+ if (iosb.u.Status == STATUS_OBJECT_NAME_COLLISION)
+ SetLastError( ERROR_FILE_EXISTS );
+ else
+ SetLastError( RtlNtStatusToDosError(iosb.u.Status) );
+ h = 0;
+ }
+
+ if (!h) WARN("Unable to create file '%s' (GLE %ld)\n", filename, GetLastError());
+ return h;
+#endif
}
@@ -1702,7 +1751,7 @@
/* check if we are allowed to delete the source */
hFile = FILE_CreateFile( full_name.long_name, GENERIC_READ|GENERIC_WRITE, 0,
- NULL, OPEN_EXISTING, 0, 0, TRUE,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, 0, TRUE,
GetDriveTypeW( full_name.short_name ) );
if (!hFile) return FALSE;
@@ -1985,7 +2034,7 @@
/* check if we are allowed to rename the source */
hFile = FILE_CreateFile( full_name1.long_name, 0, 0,
- NULL, OPEN_EXISTING, 0, 0, TRUE,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, 0, TRUE,
GetDriveTypeW( full_name1.short_name ) );
if (!hFile)
{
@@ -1998,7 +2047,7 @@
/* check, if we are allowed to delete the destination,
** (but the file not being there is fine) */
hFile = FILE_CreateFile( full_name2.long_name, GENERIC_READ|GENERIC_WRITE, 0,
- NULL, OPEN_EXISTING, 0, 0, TRUE,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, 0, TRUE,
GetDriveTypeW( full_name2.short_name ) );
if(!hFile && GetLastError() != ERROR_FILE_NOT_FOUND) return FALSE;
CloseHandle(hFile);
diff -u -N -r -x '*~' -x '.#*' -x CVS include35/winternl.h include/winternl.h
--- include35/winternl.h 2003-09-18 20:48:47.000000000 +0200
+++ include/winternl.h 2003-09-16 21:25:05.000000000 +0200
@@ -912,6 +912,15 @@
#define FILE_EXISTS 0x00000004
#define FILE_DOES_NOT_EXIST 0x00000005
+/* disposition for NtCreateFile */
+#define FILE_SUPERSEDE 0x0000
+#define FILE_OPEN 0x0001
+#define FILE_CREATE 0x0002
+#define FILE_OPEN_IF 0x0003
+#define FILE_OVERWRITE 0x0004
+#define FILE_OVERWRITE_IF 0x0005
+#define FILE_MAXIMUM_DISPOSITION 0x0005
+
#if (_WIN32_WINNT >= 0x0501)
#define INTERNAL_TS_ACTIVE_CONSOLE_ID ( *((volatile ULONG*)(0x7ffe02d8)) )
#endif /* (_WIN32_WINNT >= 0x0501) */
diff -u -N -r -x '*~' -x '.#*' -x CVS server35/directory.c server/directory.c
--- server35/directory.c 1970-01-01 01:00:00.000000000 +0100
+++ server/directory.c 2003-09-14 14:23:13.000000000 +0200
@@ -0,0 +1,248 @@
+/*
+ * Server-side file name space management
+ *
+ * Copyright (C) 2003 Eric Pouech
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "handle.h"
+#include "process.h"
+#include "request.h"
+#include "unicode.h"
+#include "console.h"
+
+static int verbose = 0;
+
+#define fprintf if (verbose) fprintf
+#define dump_strW if (verbose) dump_strW
+
+struct dir_node
+{
+ enum dir_node_type {regular, dlink} type;
+ struct dir_node* children; /* linked list of children */
+ struct dir_node* next; /* link to sibling */
+ unsigned codepage;
+ unsigned flags;
+ WCHAR* extra; /* extra information (mount point) */
+ size_t extra_len; /* sizeof of extra information */
+ struct dir_node* parent; /* parent node */
+ WCHAR name[1]; /* name of current node */
+};
+
+static struct dir_node all_root = {regular, NULL, NULL, 1252, 0, NULL, 0, NULL, {'\0'}};
+
+static struct dir_node* create_node(const WCHAR* name, size_t name_len,
+ enum dir_node_type type,
+ const WCHAR* extra, size_t extra_len,
+ unsigned codepage, unsigned flags)
+{
+ struct dir_node* node;
+
+ node = malloc(sizeof(struct dir_node) + name_len);
+ node->type = type;
+ node->children = NULL;
+ node->codepage = codepage;
+ node->flags = flags;
+ if (extra)
+ {
+ node->extra = malloc(extra_len);
+ memcpy(node->extra, extra, extra_len);
+ }
+ else
+ {
+ node->extra = NULL;
+ }
+ node->extra_len = extra_len;
+ node->next = NULL;
+ memcpy(node->name, name, name_len);
+ node->name[name_len / sizeof(WCHAR)] = '\0';
+ return node;
+}
+
+static void add_child(struct dir_node* parent, struct dir_node* new)
+{
+ new->parent = parent;
+ new->next = parent->children;
+ parent->children = new;
+}
+
+static struct dir_node* lookup(const WCHAR* name, size_t len, const WCHAR** ret)
+{
+ struct dir_node* node;
+ struct dir_node* child;
+ size_t elen;
+
+ len /= sizeof(WCHAR);
+
+ fprintf(stderr,"##");
+ dump_strW(name, len, stderr, "[]");
+ fprintf(stderr, "\n");
+
+ name++; /* skip first '\\' */
+ len--;
+
+ node = &all_root;
+ if (!*name) return node;
+
+ while (node->children)
+ {
+ fprintf(stderr," --");
+ dump_strW(name, len, stderr, "[]");
+ fprintf(stderr, "\n");
+
+ for (elen = 0; elen < len; elen++)
+ if (name[elen] == '\\') break;
+
+ for (child = node->children; child; child = child->next)
+ {
+ fprintf(stderr," <<");
+ dump_strW(child->name, strlenW(child->name), stderr, "[]");
+ fprintf(stderr, ">> %d\n", elen);
+
+ if (elen == strlenW(child->name) && strncmpiW(child->name, name, elen) == 0)
+ break;
+ }
+ if (!child) return NULL;
+ switch (child->type)
+ {
+ case dlink:
+ if (elen == len)
+ {
+ return lookup(child->extra, child->extra_len, ret);
+ }
+ else
+ {
+ WCHAR* n;
+ size_t xlen;
+
+ xlen = child->extra_len / sizeof(WCHAR);
+ n = malloc((xlen + len - elen + 1) * sizeof(WCHAR));
+ memcpy(n, child->extra, xlen * sizeof(WCHAR));
+ n[xlen] = '\\';
+ memcpy(n + xlen + 1, name + elen + 1, (len - elen) * sizeof(WCHAR));
+ node = lookup(n, (xlen + len - elen) * sizeof(WCHAR), ret);
+ if (*ret) *ret = name + (xlen + len - elen) - (*ret - n + xlen - 1);
+ free(n);
+ return node;
+ }
+ break;
+ case regular:
+ node = child;
+ break;
+ }
+
+ fprintf(stderr, "=> %d %d\n", elen, len);
+ if (elen == len) break;
+ len -= elen + 1;
+ name += elen + 1;
+ }
+ if (node) *ret = name;
+ return node;
+}
+
+static void add_node(const WCHAR* root, size_t root_len,
+ const WCHAR* name, size_t name_len,
+ enum dir_node_type type,
+ const WCHAR* extra, size_t extra_len,
+ unsigned codepage, unsigned flags)
+{
+ struct dir_node* parent;
+ struct dir_node* child;
+ const WCHAR* left;
+
+ parent = lookup(root, root_len, &left);
+
+ if (!parent)
+ {
+ fprintf(stderr, "issue: ");
+ dump_strW(root, root_len, stderr, "[]");
+ fprintf(stderr, "\n");
+ set_error(STATUS_OBJECT_PATH_NOT_FOUND);
+ }
+ child = create_node(name, name_len, type, extra, extra_len, codepage, flags);
+ add_child(parent, child);
+}
+
+DECL_HANDLER(create_pathgate)
+{
+ size_t len = get_req_data_size();
+ size_t extra_len;
+ const WCHAR* data = get_req_data();
+
+ extra_len = len - (req->root_len + req->name_len);
+
+ add_node(data, req->root_len,
+ data + req->root_len / sizeof(WCHAR), req->name_len,
+ regular,
+ extra_len ? data + (req->root_len + req->name_len) / sizeof(WCHAR) : NULL,
+ extra_len, req->codepage, req->flags);
+}
+
+DECL_HANDLER(get_file_name)
+{
+ const WCHAR* p;
+ struct dir_node* node;
+ const WCHAR* dirname = get_req_data();
+ struct dir_node* pp;
+ size_t rlen, pos, elen;
+ WCHAR* ptr;
+
+ fprintf(stderr, "imh1\n");
+ node = lookup(dirname, get_req_data_size(), &p);
+ if (!node)
+ {
+ set_error(STATUS_OBJECT_NAME_NOT_FOUND);
+ return;
+ }
+
+ fprintf(stderr, "imh2\n");
+ reply->dir_len = 0;
+ fprintf(stderr, "imh3\n");
+ for (pp = node; pp; pp = pp->parent)
+ {
+ reply->dir_len += strlenW(pp->name) + 1;
+ }
+ fprintf(stderr, "imh4\n");
+ reply->dir_len--;
+ reply->name_offset = p - dirname;
+ ptr = malloc(rlen = reply->dir_len * sizeof(WCHAR) + node->extra_len);
+ fprintf(stderr, "imh5\n");
+
+ pos = reply->dir_len;
+ for (pp = node; pp; pp = pp->parent)
+ {
+ elen = strlenW(pp->name);
+ pos -= elen;
+ memcpy(ptr + pos, pp->name, elen * sizeof(WCHAR));
+ if (pos > 0) ptr[--pos] = '/';
+ }
+ if (node->extra)
+ memcpy(ptr + reply->dir_len, node->extra, node->extra_len);
+ reply->dir_len *= sizeof(WCHAR);
+ reply->codepage = node->codepage;
+ reply->flags = node->flags;
+ set_reply_data_ptr(ptr, rlen);
+}
diff -u -N -r -x '*~' -x '.#*' -x CVS server35/file.c server/file.c
--- server35/file.c 2003-09-13 21:07:01.000000000 +0200
+++ server/file.c 2003-09-14 14:24:27.000000000 +0200
@@ -43,6 +43,8 @@
#include "winerror.h"
#include "windef.h"
#include "winbase.h"
+#include "winreg.h"
+#include "winternl.h"
#include "file.h"
#include "handle.h"
@@ -162,8 +164,7 @@
static struct file *create_file( const char *nameptr, size_t len, unsigned int access,
- unsigned int sharing, int create, unsigned int attrs,
- int drive_type )
+ unsigned int sharing, int create, unsigned int attrs)
{
struct file *file;
int hash, flags;
@@ -180,11 +181,12 @@
switch(create)
{
- case CREATE_NEW: flags = O_CREAT | O_EXCL; break;
- case CREATE_ALWAYS: flags = O_CREAT | O_TRUNC; break;
- case OPEN_ALWAYS: flags = O_CREAT; break;
- case TRUNCATE_EXISTING: flags = O_TRUNC; break;
- case OPEN_EXISTING: flags = 0; break;
+ case FILE_CREATE: flags = O_CREAT | O_EXCL; break;
+ case FILE_OVERWRITE_IF: /* FIXME: the difference is whether we trash existing attr or not */
+ case FILE_SUPERSEDE: flags = O_CREAT | O_TRUNC; break;
+ case FILE_OPEN: flags = 0; break;
+ case FILE_OPEN_IF: flags = O_CREAT; break;
+ case FILE_OVERWRITE: flags = O_TRUNC; break;
default: set_error( STATUS_INVALID_PARAMETER ); goto error;
}
switch(access & (GENERIC_READ | GENERIC_WRITE))
@@ -205,7 +207,7 @@
file->access = access;
file->flags = attrs;
file->sharing = sharing;
- file->drive_type = drive_type;
+ file->drive_type = 0; /* FIXME: this shall go away anyway */
file->name = name;
file->next = file_hash[hash];
file_hash[hash] = file;
@@ -598,7 +600,7 @@
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 )))
+ req->sharing, req->create, req->attrs )))
{
reply->handle = alloc_handle( current->process, file, req->access, req->inherit );
release_object( file );
diff -u -N -r -x '*~' -x '.#*' -x CVS server35/Makefile.in server/Makefile.in
--- server35/Makefile.in 2003-08-24 10:18:16.000000000 +0200
+++ server/Makefile.in 2003-08-12 20:55:23.000000000 +0200
@@ -16,6 +16,7 @@
context_sparc.c \
debugger.c \
device.c \
+ directory.c \
event.c \
fd.c \
file.c \
diff -u -N -r -x '*~' -x '.#*' -x CVS server35/protocol.def server/protocol.def
--- server35/protocol.def 2003-09-18 20:48:55.000000000 +0200
+++ server/protocol.def 2003-09-16 21:25:14.000000000 +0200
@@ -594,6 +596,32 @@
@END
+/* Create a path gate */
+(a)REQ(create_pathgate)
+ unsigned int codepage; /* pathgate's codepage */
+ unsigned int flags; /* flags */
+ size_t root_len; /* length of pathgate root directory */
+ size_t name_len; /* length of pathgate name */
+ VARARG(root,unicode_str,root_len); /* root directory */
+ VARARG(name,unicode_str,name_len); /* pathgate's name */
+ VARARG(extra,unicode_str); /* extra information for pathgate (Unix path) */
+(a)REPLY
+(a)END
+
+
+/* Lookup filename in pathgates */
+(a)REQ(get_file_name)
+ VARARG(name,unicode_str); /* name of file to lookup */
+(a)REPLY
+ unsigned int codepage; /* code page of path gate */
+ unsigned int flags; /* flags */
+ size_t name_offset; /* offset, in name, of the file name */
+ size_t dir_len; /* length of directory name */
+ VARARG(dirname,unicode_str,dir_len);/* actually dirname of name */
+ VARARG(extra,unicode_str); /* extra information on dirname (Unix path) */
+(a)END
+
+
/* Create a file */
@REQ(create_file)
unsigned int access; /* wanted access rights */
@@ -601,7 +629,6 @@
unsigned int sharing; /* sharing flags */
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 */
@REPLY
obj_handle_t handle; /* handle to the file */
@@ -2196,3 +2223,4 @@
#define OPEN_TOKEN_THREAD 1
#define OPEN_TOKEN_AS_SELF 2
+
1
0
Alexandre Julliard wrote:
> ChangeSet ID: 9365
> CVSROOT: /home/winehq/opt/cvs-commit
> Module name: wine
> Changes by: julliard(a)wine.codeweavers.com 2003/09/17 00:31:33
>
> Modified files:
> scheduler : thread.c process.c
> loader : module.c
> libs/wine : loader.c
> dlls/ntdll : Makefile.in
> dlls/kernel : thread.c process.c Makefile.in
> Added files:
> dlls/kernel : fiber.c except.c
> Removed files:
> win32 : except.c
> scheduler : fiber.c
>
> Log message:
> Moved almost all remaining process, thread, fiber and exception
> functions to dlls/kernel.
Quite a bit of the initialisation code is still in ntdll.
How do you see the final move:
- all initialisation code in kernel32
- part of it in ntdll, the rest in kernel32
A+
--
Eric Pouech
2
1
Hi folks,
Here is a little script that generates a table detailing
the i18n status. It works by comparing the last updated
timestamp from CVS of the language file with the master file.
It generates a matrix like this (hopefully it's not wrapped):
Legend:
'.' -- translation appears to be uptodate
'x' -- translation needs updating
'?' -- unknown status (file not under CVS control)
' ' -- translation missing
Master language is En
Module / Language Ca Cn Cs Da De En Eo Es Fi Fr Hu It Ja Ko Nl No Pl Pt Ru Si Sk Sv Sw Va Wa Xx Zh
dlls/avifil32 . . . . . . .
dlls/comctl32 . . . . . . . . .
dlls/commdlg . . . . . . . . . . . . . . . . . . . . . . . .
dlls/msvideo/msrle32 . . . . . . .
dlls/serialui . .
dlls/setupapi . .
dlls/shell32 . . . . . . . . . . . . . . . . . . . . . . . .
dlls/user/resources . . . . . . . . . . . . . . . . . . . . . . .
dlls/wineps . . . . . . . . .
dlls/wininet . . . . .
dlls/winmm . . . . . . . .
programs/clock . . . . . . . . . . . . . . .
programs/cmdlgtst . . . . . .
programs/notepad . . . . . . . . . . . . . . .
programs/progman x x . . . . . . . . . . . . . . . .
programs/view . . . . . . .
programs/wcmd . . . . .
programs/wineconsole . . . . . . .
programs/winemine . . . . .
programs/winhelp . . . . . . . . . . . . . . . . .
programs/regedit . . . . . .
programs/winefile . . . . . . . .
programs/start . . . . .
programs/winecfg . x x x x
programs/wineproc ?
Run it, it's fun! :) I guess I will submit it to the tree.
--
Dimi.
1
0