diff --git a/dlls/kernel/process.c b/dlls/kernel/process.c index a41b74f6d06..f51eb54c465 100644 --- a/dlls/kernel/process.c +++ b/dlls/kernel/process.c @@ -617,7 +617,7 @@ static RTL_USER_PROCESS_PARAMETERS *init_user_process_params( size_t info_size ) params->AllocationSize = size; /* make sure the strings are valid */ - fix_unicode_string( ¶ms->CurrentDirectoryName, (char *)info_size ); + fix_unicode_string( ¶ms->CurrentDirectory.DosPath, (char *)info_size ); fix_unicode_string( ¶ms->DllPath, (char *)info_size ); fix_unicode_string( ¶ms->ImagePathName, (char *)info_size ); fix_unicode_string( ¶ms->CommandLine, (char *)info_size ); @@ -685,13 +685,13 @@ static BOOL process_init( char *argv[], char **environ ) wine_server_fd_to_handle( 2, GENERIC_WRITE|SYNCHRONIZE, TRUE, ¶ms->hStdError ); /* */ - params->CurrentDirectoryName.Length = 3 * sizeof(WCHAR); - params->CurrentDirectoryName.MaximumLength = RtlGetLongestNtPathLength() * sizeof(WCHAR); - params->CurrentDirectoryName.Buffer = RtlAllocateHeap( GetProcessHeap(), 0, params->CurrentDirectoryName.MaximumLength); - params->CurrentDirectoryName.Buffer[0] = 'C'; - params->CurrentDirectoryName.Buffer[1] = ':'; - params->CurrentDirectoryName.Buffer[2] = '\\'; - params->CurrentDirectoryName.Buffer[3] = '\0'; + params->CurrentDirectory.DosPath.Length = 3 * sizeof(WCHAR); + params->CurrentDirectory.DosPath.MaximumLength = RtlGetLongestNtPathLength() * sizeof(WCHAR); + params->CurrentDirectory.DosPath.Buffer = RtlAllocateHeap( GetProcessHeap(), 0, params->CurrentDirectory.DosPath.MaximumLength); + params->CurrentDirectory.DosPath.Buffer[0] = 'C'; + params->CurrentDirectory.DosPath.Buffer[1] = ':'; + params->CurrentDirectory.DosPath.Buffer[2] = '\\'; + params->CurrentDirectory.DosPath.Buffer[3] = '\0'; /* */ } else diff --git a/dlls/kernel/task.c b/dlls/kernel/task.c index 94844f67afb..b477e9595ae 100644 --- a/dlls/kernel/task.c +++ b/dlls/kernel/task.c @@ -442,12 +442,13 @@ static WIN16_SUBSYSTEM_TIB *allocate_win16_tib( TDB *pTask ) else tib->exe_name = NULL; RtlAcquirePebLock(); - curdir = &NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectoryName; - tib->curdir.MaximumLength = sizeof(tib->curdir_buffer); - tib->curdir.Length = min( curdir->Length, tib->curdir.MaximumLength-sizeof(WCHAR) ); - tib->curdir.Buffer = tib->curdir_buffer; - memcpy( tib->curdir_buffer, curdir->Buffer, tib->curdir.Length ); - tib->curdir_buffer[tib->curdir.Length/sizeof(WCHAR)] = 0; + curdir = &NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory.DosPath; + tib->curdir.DosPath.MaximumLength = sizeof(tib->curdir_buffer); + tib->curdir.DosPath.Length = min( curdir->Length, tib->curdir.DosPath.MaximumLength-sizeof(WCHAR) ); + tib->curdir.DosPath.Buffer = tib->curdir_buffer; + tib->curdir.Handle = 0; + memcpy( tib->curdir_buffer, curdir->Buffer, tib->curdir.DosPath.Length ); + tib->curdir_buffer[tib->curdir.DosPath.Length/sizeof(WCHAR)] = 0; RtlReleasePebLock(); return tib; } diff --git a/dlls/ntdll/env.c b/dlls/ntdll/env.c index fa80374a2be..a5d56aadf22 100644 --- a/dlls/ntdll/env.c +++ b/dlls/ntdll/env.c @@ -348,7 +348,7 @@ PRTL_USER_PROCESS_PARAMETERS WINAPI RtlNormalizeProcessParams( RTL_USER_PROCESS_ { if (params && !(params->Flags & PROCESS_PARAMS_FLAG_NORMALIZED)) { - normalize( params, ¶ms->CurrentDirectoryName.Buffer ); + normalize( params, ¶ms->CurrentDirectory.DosPath.Buffer ); normalize( params, ¶ms->DllPath.Buffer ); normalize( params, ¶ms->ImagePathName.Buffer ); normalize( params, ¶ms->CommandLine.Buffer ); @@ -374,7 +374,7 @@ PRTL_USER_PROCESS_PARAMETERS WINAPI RtlDeNormalizeProcessParams( RTL_USER_PROCES { if (params && (params->Flags & PROCESS_PARAMS_FLAG_NORMALIZED)) { - denormalize( params, ¶ms->CurrentDirectoryName.Buffer ); + denormalize( params, ¶ms->CurrentDirectory.DosPath.Buffer ); denormalize( params, ¶ms->DllPath.Buffer ); denormalize( params, ¶ms->ImagePathName.Buffer ); denormalize( params, ¶ms->CommandLine.Buffer ); @@ -425,7 +425,7 @@ NTSTATUS WINAPI RtlCreateProcessParameters( RTL_USER_PROCESS_PARAMETERS **result RtlAcquirePebLock(); cur_params = NtCurrentTeb()->Peb->ProcessParameters; if (!DllPath) DllPath = &cur_params->DllPath; - if (!CurrentDirectoryName) CurrentDirectoryName = &cur_params->CurrentDirectoryName; + if (!CurrentDirectoryName) CurrentDirectoryName = &cur_params->CurrentDirectory.DosPath; if (!CommandLine) CommandLine = ImagePathName; if (!Environment) Environment = cur_params->Environment; if (!WindowTitle) WindowTitle = &empty_str; @@ -456,7 +456,7 @@ NTSTATUS WINAPI RtlCreateProcessParameters( RTL_USER_PROCESS_PARAMETERS **result /* all other fields are zero */ ptr = params + 1; - append_unicode_string( &ptr, CurrentDirectoryName, ¶ms->CurrentDirectoryName ); + append_unicode_string( &ptr, CurrentDirectoryName, ¶ms->CurrentDirectory.DosPath ); append_unicode_string( &ptr, DllPath, ¶ms->DllPath ); append_unicode_string( &ptr, ImagePathName, ¶ms->ImagePathName ); append_unicode_string( &ptr, CommandLine, ¶ms->CommandLine ); diff --git a/dlls/ntdll/path.c b/dlls/ntdll/path.c index 85392842d2c..1db4cef1513 100644 --- a/dlls/ntdll/path.c +++ b/dlls/ntdll/path.c @@ -29,6 +29,7 @@ #include "winbase.h" #include "winreg.h" #include "winternl.h" +#include "winioctl.h" #include "wine/unicode.h" #include "wine/debug.h" #include "wine/library.h" @@ -542,9 +543,9 @@ static ULONG get_full_path_helper(LPCWSTR name, LPWSTR buffer, ULONG size) RtlAcquirePebLock(); if (NtCurrentTeb()->Tib.SubSystemTib) /* FIXME: hack */ - cd = &((WIN16_SUBSYSTEM_TIB *)NtCurrentTeb()->Tib.SubSystemTib)->curdir; + cd = &((WIN16_SUBSYSTEM_TIB *)NtCurrentTeb()->Tib.SubSystemTib)->curdir.DosPath; else - cd = &NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectoryName; + cd = &NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory.DosPath; switch (type = RtlDetermineDosPathNameType_U(name)) { @@ -855,9 +856,9 @@ NTSTATUS WINAPI RtlGetCurrentDirectory_U(ULONG buflen, LPWSTR buf) RtlAcquirePebLock(); if (NtCurrentTeb()->Tib.SubSystemTib) /* FIXME: hack */ - us = &((WIN16_SUBSYSTEM_TIB *)NtCurrentTeb()->Tib.SubSystemTib)->curdir; + us = &((WIN16_SUBSYSTEM_TIB *)NtCurrentTeb()->Tib.SubSystemTib)->curdir.DosPath; else - us = &NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectoryName; + us = &NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory.DosPath; len = us->Length / sizeof(WCHAR); if (us->Buffer[len - 1] == '\\' && us->Buffer[len - 2] != ':') @@ -884,66 +885,68 @@ NTSTATUS WINAPI RtlGetCurrentDirectory_U(ULONG buflen, LPWSTR buf) */ NTSTATUS WINAPI RtlSetCurrentDirectory_U(const UNICODE_STRING* dir) { - UNICODE_STRING* curdir; - NTSTATUS nts = STATUS_SUCCESS; - ULONG size; - PWSTR buf = NULL; + FILE_FS_DEVICE_INFORMATION device_info; + OBJECT_ATTRIBUTES attr; + UNICODE_STRING newdir; + IO_STATUS_BLOCK io; + CURDIR *curdir; + HANDLE handle; + NTSTATUS nts; + ULONG size; + PWSTR ptr; - TRACE("(%s)\n", debugstr_w(dir->Buffer)); + newdir.Buffer = NULL; RtlAcquirePebLock(); if (NtCurrentTeb()->Tib.SubSystemTib) /* FIXME: hack */ curdir = &((WIN16_SUBSYSTEM_TIB *)NtCurrentTeb()->Tib.SubSystemTib)->curdir; else - curdir = &NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectoryName; + curdir = &NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory; - size = curdir->MaximumLength; - - buf = RtlAllocateHeap(GetProcessHeap(), 0, size); - if (buf == NULL) - { - nts = STATUS_NO_MEMORY; - goto out; - } - - size = RtlGetFullPathName_U(dir->Buffer, size, buf, 0); - if (!size) + if (!RtlDosPathNameToNtPathName_U( dir->Buffer, &newdir, NULL, NULL )) { nts = STATUS_OBJECT_NAME_INVALID; goto out; } - switch (RtlDetermineDosPathNameType_U(buf)) + attr.Length = sizeof(attr); + attr.RootDirectory = 0; + attr.Attributes = OBJ_CASE_INSENSITIVE; + attr.ObjectName = &newdir; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + + nts = NtOpenFile( &handle, 0, &attr, &io, 0, FILE_DIRECTORY_FILE ); + if (nts != STATUS_SUCCESS) goto out; + + /* don't keep the directory handle open on removable media */ + if (!NtQueryVolumeInformationFile( handle, &io, &device_info, + sizeof(device_info), FileFsDeviceInformation ) && + (device_info.Characteristics & FILE_REMOVABLE_MEDIA)) { - case ABSOLUTE_DRIVE_PATH: - case UNC_PATH: - break; - default: - FIXME("Don't support those cases yes\n"); - nts = STATUS_NOT_IMPLEMENTED; - goto out; + NtClose( handle ); + handle = 0; } - /* FIXME: should check that the directory actually exists, - * and fill CurrentDirectoryHandle accordingly - */ + if (curdir->Handle) NtClose( curdir->Handle ); + curdir->Handle = handle; /* append trailing \ if missing */ - if (buf[size / sizeof(WCHAR) - 1] != '\\') - { - buf[size / sizeof(WCHAR)] = '\\'; - buf[size / sizeof(WCHAR) + 1] = '\0'; - size += sizeof(WCHAR); - } + size = newdir.Length / sizeof(WCHAR); + ptr = newdir.Buffer; + ptr += 4; /* skip \??\ prefix */ + size -= 4; + if (size && ptr[size - 1] != '\\') ptr[size++] = '\\'; - memmove(curdir->Buffer, buf, size + sizeof(WCHAR)); - curdir->Length = size; + memcpy( curdir->DosPath.Buffer, ptr, size * sizeof(WCHAR)); + curdir->DosPath.Buffer[size] = 0; + curdir->DosPath.Length = size * sizeof(WCHAR); + + TRACE( "curdir now %s %p\n", debugstr_w(curdir->DosPath.Buffer), curdir->Handle ); out: - if (buf) RtlFreeHeap(GetProcessHeap(), 0, buf); - + RtlFreeUnicodeString( &newdir ); RtlReleasePebLock(); - return nts; } diff --git a/include/thread.h b/include/thread.h index 9c2ae9fa3ee..335e364a12f 100644 --- a/include/thread.h +++ b/include/thread.h @@ -143,7 +143,7 @@ typedef struct /* the following fields do not exist under Windows */ UNICODE_STRING exe_str; /* exe name string pointed to by exe_name */ - UNICODE_STRING curdir; /* current directory */ + CURDIR curdir; /* current directory */ WCHAR curdir_buffer[MAX_PATH]; } WIN16_SUBSYSTEM_TIB; diff --git a/include/winternl.h b/include/winternl.h index e526678338b..19e497dfd20 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -106,8 +106,7 @@ typedef struct _RTL_USER_PROCESS_PARAMETERS HANDLE hStdInput; HANDLE hStdOutput; HANDLE hStdError; - UNICODE_STRING CurrentDirectoryName; - HANDLE CurrentDirectoryHandle; + CURDIR CurrentDirectory; UNICODE_STRING DllPath; UNICODE_STRING ImagePathName; UNICODE_STRING CommandLine; diff --git a/server/trace.c b/server/trace.c index 3d9d7b905ce..4d6c4230784 100644 --- a/server/trace.c +++ b/server/trace.c @@ -329,7 +329,7 @@ static void dump_varargs_startup_info( size_t size ) fprintf( stderr, "hStdInput=%p,", params.hStdInput ); fprintf( stderr, "hStdOutput=%p,", params.hStdOutput ); fprintf( stderr, "hStdError=%p,", params.hStdError ); - fprintf( stderr, "CurrentDirectoryHandle=%p,", params.CurrentDirectoryHandle ); + fprintf( stderr, "CurrentDirectory.Handle=%p,", params.CurrentDirectory.Handle ); fprintf( stderr, "dwX=%ld,", params.dwX ); fprintf( stderr, "dwY=%ld,", params.dwY ); fprintf( stderr, "dwXSize=%ld,", params.dwXSize ); @@ -339,8 +339,8 @@ static void dump_varargs_startup_info( size_t size ) fprintf( stderr, "dwFillAttribute=%lx,", params.dwFillAttribute ); fprintf( stderr, "dwFlags=%lx,", params.dwFlags ); fprintf( stderr, "wShowWindow=%lx,", params.wShowWindow ); - fprintf( stderr, "CurrentDirectoryName=L\"" ); - dump_inline_unicode_string( ¶ms.CurrentDirectoryName, cur_data, size ); + fprintf( stderr, "CurrentDirectory.DosPath=L\"" ); + dump_inline_unicode_string( ¶ms.CurrentDirectory.DosPath, cur_data, size ); fprintf( stderr, "\",DllPath=L\"" ); dump_inline_unicode_string( ¶ms.DllPath, cur_data, size ); fprintf( stderr, "\",ImagePathName=L\"" );