Reimplemented CreateDirectoryW and RemoveDirectoryW using ntdll
functions.
This commit is contained in:
parent
cf67839bc4
commit
ad9b799324
|
@ -1003,6 +1003,195 @@ BOOL WINAPI MoveFileA( LPCSTR source, LPCSTR dest )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* CreateDirectoryW (KERNEL32.@)
|
||||||
|
* RETURNS:
|
||||||
|
* TRUE : success
|
||||||
|
* FALSE : failure
|
||||||
|
* ERROR_DISK_FULL: on full disk
|
||||||
|
* ERROR_ALREADY_EXISTS: if directory name exists (even as file)
|
||||||
|
* ERROR_ACCESS_DENIED: on permission problems
|
||||||
|
* ERROR_FILENAME_EXCED_RANGE: too long filename(s)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI CreateDirectoryW( LPCWSTR path, LPSECURITY_ATTRIBUTES sa )
|
||||||
|
{
|
||||||
|
OBJECT_ATTRIBUTES attr;
|
||||||
|
UNICODE_STRING nt_name;
|
||||||
|
IO_STATUS_BLOCK io;
|
||||||
|
NTSTATUS status;
|
||||||
|
HANDLE handle;
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
|
TRACE( "%s\n", debugstr_w(path) );
|
||||||
|
|
||||||
|
if (!RtlDosPathNameToNtPathName_U( path, &nt_name, NULL, NULL ))
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_PATH_NOT_FOUND );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
attr.Length = sizeof(attr);
|
||||||
|
attr.RootDirectory = 0;
|
||||||
|
attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||||
|
attr.ObjectName = &nt_name;
|
||||||
|
attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
|
||||||
|
attr.SecurityQualityOfService = NULL;
|
||||||
|
|
||||||
|
status = NtCreateFile( &handle, GENERIC_READ, &attr, &io, NULL,
|
||||||
|
FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_CREATE,
|
||||||
|
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
|
||||||
|
|
||||||
|
if (status == STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
NtClose( handle );
|
||||||
|
ret = TRUE;
|
||||||
|
}
|
||||||
|
else SetLastError( RtlNtStatusToDosError(status) );
|
||||||
|
|
||||||
|
RtlFreeUnicodeString( &nt_name );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* CreateDirectoryA (KERNEL32.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI CreateDirectoryA( LPCSTR path, LPSECURITY_ATTRIBUTES sa )
|
||||||
|
{
|
||||||
|
UNICODE_STRING pathW;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
if (path)
|
||||||
|
{
|
||||||
|
if (!RtlCreateUnicodeStringFromAsciiz(&pathW, path))
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else pathW.Buffer = NULL;
|
||||||
|
ret = CreateDirectoryW( pathW.Buffer, sa );
|
||||||
|
RtlFreeUnicodeString( &pathW );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* CreateDirectoryExA (KERNEL32.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI CreateDirectoryExA( LPCSTR template, LPCSTR path, LPSECURITY_ATTRIBUTES sa )
|
||||||
|
{
|
||||||
|
UNICODE_STRING pathW, templateW;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
if (path)
|
||||||
|
{
|
||||||
|
if (!RtlCreateUnicodeStringFromAsciiz( &pathW, path ))
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else pathW.Buffer = NULL;
|
||||||
|
|
||||||
|
if (template)
|
||||||
|
{
|
||||||
|
if (!RtlCreateUnicodeStringFromAsciiz( &templateW, template ))
|
||||||
|
{
|
||||||
|
RtlFreeUnicodeString( &pathW );
|
||||||
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else templateW.Buffer = NULL;
|
||||||
|
|
||||||
|
ret = CreateDirectoryExW( templateW.Buffer, pathW.Buffer, sa );
|
||||||
|
RtlFreeUnicodeString( &pathW );
|
||||||
|
RtlFreeUnicodeString( &templateW );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* CreateDirectoryExW (KERNEL32.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI CreateDirectoryExW( LPCWSTR template, LPCWSTR path, LPSECURITY_ATTRIBUTES sa )
|
||||||
|
{
|
||||||
|
return CreateDirectoryW( path, sa );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* RemoveDirectoryW (KERNEL32.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI RemoveDirectoryW( LPCWSTR path )
|
||||||
|
{
|
||||||
|
OBJECT_ATTRIBUTES attr;
|
||||||
|
UNICODE_STRING nt_name;
|
||||||
|
ANSI_STRING unix_name;
|
||||||
|
IO_STATUS_BLOCK io;
|
||||||
|
NTSTATUS status;
|
||||||
|
HANDLE handle;
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
|
TRACE( "%s\n", debugstr_w(path) );
|
||||||
|
|
||||||
|
if (!RtlDosPathNameToNtPathName_U( path, &nt_name, NULL, NULL ))
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_PATH_NOT_FOUND );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
attr.Length = sizeof(attr);
|
||||||
|
attr.RootDirectory = 0;
|
||||||
|
attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||||
|
attr.ObjectName = &nt_name;
|
||||||
|
attr.SecurityDescriptor = NULL;
|
||||||
|
attr.SecurityQualityOfService = NULL;
|
||||||
|
|
||||||
|
status = NtOpenFile( &handle, GENERIC_READ, &attr, &io,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT );
|
||||||
|
if (status == STATUS_SUCCESS)
|
||||||
|
status = wine_nt_to_unix_file_name( &nt_name, &unix_name, FILE_OPEN, FALSE );
|
||||||
|
RtlFreeUnicodeString( &nt_name );
|
||||||
|
|
||||||
|
if (status != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
SetLastError( RtlNtStatusToDosError(status) );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ret = (rmdir( unix_name.Buffer ) != -1))) FILE_SetDosError();
|
||||||
|
RtlFreeAnsiString( &unix_name );
|
||||||
|
NtClose( handle );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* RemoveDirectoryA (KERNEL32.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI RemoveDirectoryA( LPCSTR path )
|
||||||
|
{
|
||||||
|
UNICODE_STRING pathW;
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RtlCreateUnicodeStringFromAsciiz(&pathW, path))
|
||||||
|
{
|
||||||
|
ret = RemoveDirectoryW(pathW.Buffer);
|
||||||
|
RtlFreeUnicodeString(&pathW);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* wine_get_unix_file_name (KERNEL32.@) Not a Windows API
|
* wine_get_unix_file_name (KERNEL32.@) Not a Windows API
|
||||||
*
|
*
|
||||||
|
|
|
@ -329,157 +329,3 @@ UINT WINAPI GetSystemDirectoryA( LPSTR path, UINT count )
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* CreateDirectoryW (KERNEL32.@)
|
|
||||||
* RETURNS:
|
|
||||||
* TRUE : success
|
|
||||||
* FALSE : failure
|
|
||||||
* ERROR_DISK_FULL: on full disk
|
|
||||||
* ERROR_ALREADY_EXISTS: if directory name exists (even as file)
|
|
||||||
* ERROR_ACCESS_DENIED: on permission problems
|
|
||||||
* ERROR_FILENAME_EXCED_RANGE: too long filename(s)
|
|
||||||
*/
|
|
||||||
BOOL WINAPI CreateDirectoryW( LPCWSTR path,
|
|
||||||
LPSECURITY_ATTRIBUTES lpsecattribs )
|
|
||||||
{
|
|
||||||
DOS_FULL_NAME full_name;
|
|
||||||
|
|
||||||
if (!path || !*path)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_PATH_NOT_FOUND);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE_(file)("(%s,%p)\n", debugstr_w(path), lpsecattribs );
|
|
||||||
|
|
||||||
if (RtlIsDosDeviceName_U( path ))
|
|
||||||
{
|
|
||||||
TRACE_(file)("cannot use device %s!\n", debugstr_w(path));
|
|
||||||
SetLastError( ERROR_ACCESS_DENIED );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (!DOSFS_GetFullName( path, FALSE, &full_name )) return 0;
|
|
||||||
if (mkdir( full_name.long_name, 0777 ) == -1) {
|
|
||||||
WARN_(file)("Error '%s' trying to create directory '%s'\n", strerror(errno), full_name.long_name);
|
|
||||||
/* the FILE_SetDosError() generated error codes don't match the
|
|
||||||
* CreateDirectory ones for some errnos */
|
|
||||||
switch (errno) {
|
|
||||||
case EEXIST:
|
|
||||||
{
|
|
||||||
if (!strcmp(DRIVE_GetRoot(full_name.drive), full_name.long_name))
|
|
||||||
SetLastError(ERROR_ACCESS_DENIED);
|
|
||||||
else
|
|
||||||
SetLastError(ERROR_ALREADY_EXISTS);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ENOSPC: SetLastError(ERROR_DISK_FULL); break;
|
|
||||||
default: FILE_SetDosError();break;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* CreateDirectoryA (KERNEL32.@)
|
|
||||||
*/
|
|
||||||
BOOL WINAPI CreateDirectoryA( LPCSTR path,
|
|
||||||
LPSECURITY_ATTRIBUTES lpsecattribs )
|
|
||||||
{
|
|
||||||
UNICODE_STRING pathW;
|
|
||||||
BOOL ret = FALSE;
|
|
||||||
|
|
||||||
if (!path || !*path)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_PATH_NOT_FOUND);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RtlCreateUnicodeStringFromAsciiz(&pathW, path))
|
|
||||||
{
|
|
||||||
ret = CreateDirectoryW(pathW.Buffer, lpsecattribs);
|
|
||||||
RtlFreeUnicodeString(&pathW);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* CreateDirectoryExA (KERNEL32.@)
|
|
||||||
*/
|
|
||||||
BOOL WINAPI CreateDirectoryExA( LPCSTR template, LPCSTR path,
|
|
||||||
LPSECURITY_ATTRIBUTES lpsecattribs)
|
|
||||||
{
|
|
||||||
return CreateDirectoryA(path,lpsecattribs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* CreateDirectoryExW (KERNEL32.@)
|
|
||||||
*/
|
|
||||||
BOOL WINAPI CreateDirectoryExW( LPCWSTR template, LPCWSTR path,
|
|
||||||
LPSECURITY_ATTRIBUTES lpsecattribs)
|
|
||||||
{
|
|
||||||
return CreateDirectoryW(path,lpsecattribs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* RemoveDirectoryW (KERNEL32.@)
|
|
||||||
*/
|
|
||||||
BOOL WINAPI RemoveDirectoryW( LPCWSTR path )
|
|
||||||
{
|
|
||||||
DOS_FULL_NAME full_name;
|
|
||||||
|
|
||||||
if (!path)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE_(file)("%s\n", debugstr_w(path));
|
|
||||||
|
|
||||||
if (RtlIsDosDeviceName_U( path ))
|
|
||||||
{
|
|
||||||
TRACE_(file)("cannot remove device %s!\n", debugstr_w(path));
|
|
||||||
SetLastError( ERROR_FILE_NOT_FOUND );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (!DOSFS_GetFullName( path, TRUE, &full_name )) return FALSE;
|
|
||||||
if (rmdir( full_name.long_name ) == -1)
|
|
||||||
{
|
|
||||||
FILE_SetDosError();
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* RemoveDirectoryA (KERNEL32.@)
|
|
||||||
*/
|
|
||||||
BOOL WINAPI RemoveDirectoryA( LPCSTR path )
|
|
||||||
{
|
|
||||||
UNICODE_STRING pathW;
|
|
||||||
BOOL ret = FALSE;
|
|
||||||
|
|
||||||
if (!path)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RtlCreateUnicodeStringFromAsciiz(&pathW, path))
|
|
||||||
{
|
|
||||||
ret = RemoveDirectoryW(pathW.Buffer);
|
|
||||||
RtlFreeUnicodeString(&pathW);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
15
server/fd.c
15
server/fd.c
|
@ -929,6 +929,21 @@ struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode,
|
||||||
release_object( fd );
|
release_object( fd );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
/* create the directory if needed */
|
||||||
|
if ((options & FILE_DIRECTORY_FILE) && (flags & O_CREAT))
|
||||||
|
{
|
||||||
|
if (mkdir( name, 0777 ) == -1)
|
||||||
|
{
|
||||||
|
if (errno != EEXIST || (flags & O_EXCL))
|
||||||
|
{
|
||||||
|
file_set_error();
|
||||||
|
release_object( fd );
|
||||||
|
free( closed_fd );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
|
||||||
|
}
|
||||||
if ((fd->unix_fd = open( name, flags, *mode )) == -1)
|
if ((fd->unix_fd = open( name, flags, *mode )) == -1)
|
||||||
{
|
{
|
||||||
file_set_error();
|
file_set_error();
|
||||||
|
|
Loading…
Reference in New Issue