Commit 72aad7dc authored by Alexandre Julliard's avatar Alexandre Julliard

Make CreateFileW use NtCreateFile.

parent 9bca690d
...@@ -307,54 +307,61 @@ HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing, ...@@ -307,54 +307,61 @@ HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
LPSECURITY_ATTRIBUTES sa, DWORD creation, LPSECURITY_ATTRIBUTES sa, DWORD creation,
DWORD attributes, HANDLE template ) DWORD attributes, HANDLE template )
{ {
DOS_FULL_NAME full_name; NTSTATUS status;
UINT options;
OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW;
IO_STATUS_BLOCK io;
HANDLE ret; HANDLE ret;
DWORD dosdev; DWORD dosdev;
static const WCHAR bkslashes_with_question_markW[] = {'\\','\\','?','\\',0};
static const WCHAR bkslashes_with_dotW[] = {'\\','\\','.','\\',0}; static const WCHAR bkslashes_with_dotW[] = {'\\','\\','.','\\',0};
static const WCHAR bkslashesW[] = {'\\','\\',0};
static const WCHAR coninW[] = {'C','O','N','I','N','$',0}; static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0}; static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
static const char * const creation_name[5] =
{ "CREATE_NEW", "CREATE_ALWAYS", "OPEN_EXISTING", "OPEN_ALWAYS", "TRUNCATE_EXISTING" };
static const UINT nt_disposition[5] =
{
FILE_CREATE, /* CREATE_NEW */
FILE_OVERWRITE_IF, /* CREATE_ALWAYS */
FILE_OPEN, /* OPEN_EXISTING */
FILE_OPEN_IF, /* OPEN_ALWAYS */
FILE_OVERWRITE /* TRUNCATE_EXISTING */
};
/* sanity checks */
if (!filename || !filename[0]) if (!filename || !filename[0])
{ {
SetLastError( ERROR_PATH_NOT_FOUND ); SetLastError( ERROR_PATH_NOT_FOUND );
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
} }
if (creation < CREATE_NEW || creation > TRUNCATE_EXISTING)
{
SetLastError( ERROR_INVALID_PARAMETER );
return INVALID_HANDLE_VALUE;
}
TRACE("%s %s%s%s%s%s%s%s attributes 0x%lx\n", debugstr_w(filename), TRACE("%s %s%s%s%s%s%s%s attributes 0x%lx\n", debugstr_w(filename),
((access & GENERIC_READ)==GENERIC_READ)?"GENERIC_READ ":"", (access & GENERIC_READ)?"GENERIC_READ ":"",
((access & GENERIC_WRITE)==GENERIC_WRITE)?"GENERIC_WRITE ":"", (access & GENERIC_WRITE)?"GENERIC_WRITE ":"",
(!access)?"QUERY_ACCESS ":"", (!access)?"QUERY_ACCESS ":"",
((sharing & FILE_SHARE_READ)==FILE_SHARE_READ)?"FILE_SHARE_READ ":"", (sharing & FILE_SHARE_READ)?"FILE_SHARE_READ ":"",
((sharing & FILE_SHARE_WRITE)==FILE_SHARE_WRITE)?"FILE_SHARE_WRITE ":"", (sharing & FILE_SHARE_WRITE)?"FILE_SHARE_WRITE ":"",
((sharing & FILE_SHARE_DELETE)==FILE_SHARE_DELETE)?"FILE_SHARE_DELETE ":"", (sharing & FILE_SHARE_DELETE)?"FILE_SHARE_DELETE ":"",
(creation ==CREATE_NEW)?"CREATE_NEW": creation_name[creation - CREATE_NEW], attributes);
(creation ==CREATE_ALWAYS)?"CREATE_ALWAYS ":
(creation ==OPEN_EXISTING)?"OPEN_EXISTING ":
(creation ==OPEN_ALWAYS)?"OPEN_ALWAYS ":
(creation ==TRUNCATE_EXISTING)?"TRUNCATE_EXISTING ":"", attributes);
/* Open a console for CONIN$ or CONOUT$ */ /* Open a console for CONIN$ or CONOUT$ */
if (!strcmpiW(filename, coninW) || !strcmpiW(filename, conoutW)) if (!strcmpiW(filename, coninW) || !strcmpiW(filename, conoutW))
{ {
ret = OpenConsoleW(filename, access, (sa && sa->bInheritHandle), creation); ret = OpenConsoleW(filename, access, (sa && sa->bInheritHandle), creation);
goto done; goto done;
} }
/* If the name starts with '\\?\', ignore the first 4 chars. */
if (!strncmpW(filename, bkslashes_with_question_markW, 4))
{
static const WCHAR uncW[] = {'U','N','C','\\',0};
filename += 4;
if (!strncmpiW(filename, uncW, 4))
{
FIXME("UNC name (%s) not supported.\n", debugstr_w(filename) );
SetLastError( ERROR_PATH_NOT_FOUND );
return INVALID_HANDLE_VALUE;
}
}
if (!strncmpW(filename, bkslashes_with_dotW, 4)) if (!strncmpW(filename, bkslashes_with_dotW, 4))
{ {
static const WCHAR pipeW[] = {'P','I','P','E','\\',0}; static const WCHAR pipeW[] = {'P','I','P','E','\\',0};
...@@ -375,7 +382,7 @@ HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing, ...@@ -375,7 +382,7 @@ HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
else else
{ {
SetLastError( ERROR_ACCESS_DENIED ); SetLastError( ERROR_ACCESS_DENIED );
ret = INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
} }
goto done; goto done;
} }
...@@ -383,11 +390,16 @@ HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing, ...@@ -383,11 +390,16 @@ HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
{ {
dosdev += MAKELONG( 0, 4*sizeof(WCHAR) ); /* adjust position to start of filename */ dosdev += MAKELONG( 0, 4*sizeof(WCHAR) ); /* adjust position to start of filename */
} }
else else if (filename[4])
{ {
ret = VXD_Open( filename+4, access, sa ); ret = VXD_Open( filename+4, access, sa );
goto done; goto done;
} }
else
{
SetLastError( ERROR_INVALID_NAME );
return INVALID_HANDLE_VALUE;
}
} }
else dosdev = RtlIsDosDeviceName_U( filename ); else dosdev = RtlIsDosDeviceName_U( filename );
...@@ -412,7 +424,6 @@ HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing, ...@@ -412,7 +424,6 @@ HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
ret = OpenConsoleW(conoutW, access, (sa && sa->bInheritHandle), creation); ret = OpenConsoleW(conoutW, access, (sa && sa->bInheritHandle), creation);
goto done; goto done;
default: default:
FIXME("can't open CON read/write\n");
SetLastError( ERROR_FILE_NOT_FOUND ); SetLastError( ERROR_FILE_NOT_FOUND );
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
} }
...@@ -422,32 +433,57 @@ HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing, ...@@ -422,32 +433,57 @@ HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
goto done; goto done;
} }
/* If the name still starts with '\\', it's a UNC name. */ if (!RtlDosPathNameToNtPathName_U( filename, &nameW, NULL, NULL ))
if (!strncmpW(filename, bkslashesW, 2))
{ {
ret = SMB_CreateFileW(filename, access, sharing, sa, creation, attributes, template ); SetLastError( ERROR_PATH_NOT_FOUND );
goto done; return INVALID_HANDLE_VALUE;
} }
/* If the name contains a DOS wild card (* or ?), do no create a file */ /* now call NtCreateFile */
if(strchrW(filename, '*') || strchrW(filename, '?'))
options = 0;
if (attributes & FILE_FLAG_BACKUP_SEMANTICS)
options |= FILE_OPEN_FOR_BACKUP_INTENT;
else
options |= FILE_NON_DIRECTORY_FILE;
if (attributes & FILE_FLAG_DELETE_ON_CLOSE)
options |= FILE_DELETE_ON_CLOSE;
if (!(attributes & FILE_FLAG_OVERLAPPED))
options |= FILE_SYNCHRONOUS_IO_ALERT;
if (attributes & FILE_FLAG_RANDOM_ACCESS)
options |= FILE_RANDOM_ACCESS;
attributes &= FILE_ATTRIBUTE_VALID_FLAGS;
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.Attributes = OBJ_CASE_INSENSITIVE;
attr.ObjectName = &nameW;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
if (sa && sa->bInheritHandle) attr.Attributes |= OBJ_INHERIT;
status = NtCreateFile( &ret, access, &attr, &io, NULL, attributes,
sharing, nt_disposition[creation - CREATE_NEW],
options, NULL, 0 );
if (status)
{ {
SetLastError(ERROR_BAD_PATHNAME); WARN("Unable to create file %s (status %lx)\n", debugstr_w(filename), status);
return INVALID_HANDLE_VALUE; ret = INVALID_HANDLE_VALUE;
}
/* check for filename, don't check for last entry if creating */ /* In the case file creation was rejected due to CREATE_NEW flag
if (!DOSFS_GetFullName( filename, * was specified and file with that name already exists, correct
(creation == OPEN_EXISTING) || * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS.
(creation == TRUNCATE_EXISTING), * Note: RtlNtStatusToDosError is not the subject to blame here.
&full_name )) { */
WARN("Unable to get full filename from %s (GLE %ld)\n", if (status == STATUS_OBJECT_NAME_COLLISION)
debugstr_w(filename), GetLastError()); SetLastError( ERROR_FILE_EXISTS );
return INVALID_HANDLE_VALUE; else
SetLastError( RtlNtStatusToDosError(status) );
} }
else SetLastError(0);
RtlFreeUnicodeString( &nameW );
ret = FILE_CreateFile( full_name.long_name, access, sharing,
sa, creation, attributes, template );
done: done:
if (!ret) ret = INVALID_HANDLE_VALUE; if (!ret) ret = INVALID_HANDLE_VALUE;
TRACE("returning %p\n", ret); TRACE("returning %p\n", ret);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment