relative optional parameter will now be handled by setting the RelativeName of the relative struct to NT converted and collapsed relative path and the ContainingDirectory to an open handle of current working directory. CurDir is currently not implemented.
From: Rayhan Faizel rayhan.faizel@hotmail.com
--- dlls/ntdll/path.c | 211 ++++++++++++++++++++++++++++------------------ 1 file changed, 129 insertions(+), 82 deletions(-)
diff --git a/dlls/ntdll/path.c b/dlls/ntdll/path.c index 37ad4bbcea2..3ec5e48d5ca 100644 --- a/dlls/ntdll/path.c +++ b/dlls/ntdll/path.c @@ -290,7 +290,6 @@ NTSTATUS WINAPI RtlDosPathNameToNtPathName_U_WithStatus(const WCHAR *dos_path, U *file_part = ntpath->Buffer + ntpath->Length / sizeof(WCHAR) - wcslen(*file_part);
/* FIXME: cd filling */ - out: if (ptr != local) RtlFreeHeap(GetProcessHeap(), 0, ptr); return nts; @@ -309,6 +308,82 @@ BOOLEAN WINAPI RtlDosPathNameToNtPathName_U(PCWSTR dos_path, return RtlDosPathNameToNtPathName_U_WithStatus(dos_path, ntpath, file_part, cd) == STATUS_SUCCESS; }
+ + +/****************************************************************** + * collapse_path + * + * Helper for RtlGetFullPathName_U. + * Get rid of . and .. components in the path. + */ +static inline void collapse_path( WCHAR *path, UINT mark ) +{ + WCHAR *p, *next; + + /* convert every / into a \ */ + for (p = path; *p; p++) if (*p == '/') *p = '\'; + + /* collapse duplicate backslashes */ + next = path + max( 1, mark ); + for (p = next; *p; p++) if (*p != '\' || next[-1] != '\') *next++ = *p; + *next = 0; + + p = path + mark; + while (*p) + { + if (*p == '.') + { + switch(p[1]) + { + case '\': /* .\ component */ + next = p + 2; + memmove( p, next, (wcslen(next) + 1) * sizeof(WCHAR) ); + continue; + case 0: /* final . */ + if (p > path + mark) p--; + *p = 0; + continue; + case '.': + if (p[2] == '\') /* ..\ component */ + { + next = p + 3; + if (p > path + mark) + { + p--; + while (p > path + mark && p[-1] != '\') p--; + } + memmove( p, next, (wcslen(next) + 1) * sizeof(WCHAR) ); + continue; + } + else if (!p[2]) /* final .. */ + { + if (p > path + mark) + { + p--; + while (p > path + mark && p[-1] != '\') p--; + if (p > path + mark) p--; + } + *p = 0; + continue; + } + break; + } + } + /* skip to the next component */ + while (*p && *p != '\') p++; + if (*p == '\') + { + /* remove last dot in previous dir name */ + if (p > path + mark && p[-1] == '.') memmove( p-1, p, (wcslen(p) + 1) * sizeof(WCHAR) ); + else p++; + } + } + + /* remove trailing spaces and dots (yes, Windows really does that, don't ask) */ + while (p > path + mark && (p[-1] == ' ' || p[-1] == '.')) p--; + *p = 0; +} + /************************************************************************** * RtlDosPathNameToRelativeNtPathName_U_WithStatus [NTDLL.@] * @@ -317,17 +392,65 @@ BOOLEAN WINAPI RtlDosPathNameToNtPathName_U(PCWSTR dos_path, NTSTATUS WINAPI RtlDosPathNameToRelativeNtPathName_U_WithStatus(const WCHAR *dos_path, UNICODE_STRING *ntpath, WCHAR **file_part, RTL_RELATIVE_NAME *relative) { + + NTSTATUS ret; TRACE("(%s,%p,%p,%p)\n", debugstr_w(dos_path), ntpath, file_part, relative);
+ + ret = RtlDosPathNameToNtPathName_U_WithStatus(dos_path, ntpath, file_part, NULL); + if (relative) { - FIXME("Unsupported parameter\n"); - memset(relative, 0, sizeof(*relative)); - } + DOS_PATHNAME_TYPE type = RtlDetermineDosPathNameType_U(dos_path); + if (type == RELATIVE_PATH) + { + HANDLE handle;
- /* FIXME: fill parameter relative */ + IO_STATUS_BLOCK io; + OBJECT_ATTRIBUTES attr; + NTSTATUS ret_rel, nts; + UNICODE_STRING* cur_dir, cur_dir_nt; + int dos_path_len = wcslen(dos_path); + + WCHAR *converted_path = RtlAllocateHeap(GetProcessHeap(), 0, dos_path_len * sizeof(WCHAR));; + wcscpy(converted_path, dos_path); + collapse_path(converted_path, 3); + + if (NtCurrentTeb()->Tib.SubSystemTib) /* FIXME: hack */ + cur_dir = &((WIN16_SUBSYSTEM_TIB *)NtCurrentTeb()->Tib.SubSystemTib)->curdir.DosPath; + else + cur_dir = &NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory.DosPath; + + /* FIXME: Better way besides invoking this function twice? */ + ret_rel = RtlDosPathNameToNtPathName_U_WithStatus(cur_dir->Buffer, &cur_dir_nt, NULL, NULL); + if (ret_rel != STATUS_SUCCESS) + goto out; + + attr.Length = sizeof(attr); + attr.RootDirectory = 0; + attr.Attributes = OBJ_CASE_INSENSITIVE; + attr.ObjectName = &cur_dir_nt; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + + nts = NtOpenFile(&handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &io, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
- return RtlDosPathNameToNtPathName_U_WithStatus(dos_path, ntpath, file_part, NULL); + if (nts != STATUS_SUCCESS) + goto out; + RtlInitUnicodeString(&(relative->RelativeName),converted_path); + relative->ContainerDirectory = handle; + // No idea what this does. + relative->CurDirRef = NULL; + } + else + { + memset(relative,0,sizeof(*relative)); + } + } + out: + return ret; }
/************************************************************************** @@ -416,82 +539,6 @@ ULONG WINAPI RtlDosSearchPath_U(LPCWSTR paths, LPCWSTR search, LPCWSTR ext, return len; }
- -/****************************************************************** - * collapse_path - * - * Helper for RtlGetFullPathName_U. - * Get rid of . and .. components in the path. - */ -static inline void collapse_path( WCHAR *path, UINT mark ) -{ - WCHAR *p, *next; - - /* convert every / into a \ */ - for (p = path; *p; p++) if (*p == '/') *p = '\'; - - /* collapse duplicate backslashes */ - next = path + max( 1, mark ); - for (p = next; *p; p++) if (*p != '\' || next[-1] != '\') *next++ = *p; - *next = 0; - - p = path + mark; - while (*p) - { - if (*p == '.') - { - switch(p[1]) - { - case '\': /* .\ component */ - next = p + 2; - memmove( p, next, (wcslen(next) + 1) * sizeof(WCHAR) ); - continue; - case 0: /* final . */ - if (p > path + mark) p--; - *p = 0; - continue; - case '.': - if (p[2] == '\') /* ..\ component */ - { - next = p + 3; - if (p > path + mark) - { - p--; - while (p > path + mark && p[-1] != '\') p--; - } - memmove( p, next, (wcslen(next) + 1) * sizeof(WCHAR) ); - continue; - } - else if (!p[2]) /* final .. */ - { - if (p > path + mark) - { - p--; - while (p > path + mark && p[-1] != '\') p--; - if (p > path + mark) p--; - } - *p = 0; - continue; - } - break; - } - } - /* skip to the next component */ - while (*p && *p != '\') p++; - if (*p == '\') - { - /* remove last dot in previous dir name */ - if (p > path + mark && p[-1] == '.') memmove( p-1, p, (wcslen(p) + 1) * sizeof(WCHAR) ); - else p++; - } - } - - /* remove trailing spaces and dots (yes, Windows really does that, don't ask) */ - while (p > path + mark && (p[-1] == ' ' || p[-1] == '.')) p--; - *p = 0; -} - - /****************************************************************** * skip_unc_prefix *
From: Rayhan Faizel rayhan.faizel@hotmail.com
--- dlls/ntdll/path.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/path.c b/dlls/ntdll/path.c index 3ec5e48d5ca..26228d127e6 100644 --- a/dlls/ntdll/path.c +++ b/dlls/ntdll/path.c @@ -409,19 +409,24 @@ NTSTATUS WINAPI RtlDosPathNameToRelativeNtPathName_U_WithStatus(const WCHAR *dos IO_STATUS_BLOCK io; OBJECT_ATTRIBUTES attr; NTSTATUS ret_rel, nts; - UNICODE_STRING* cur_dir, cur_dir_nt; + UNICODE_STRING *cur_dir, cur_dir_nt; int dos_path_len = wcslen(dos_path);
- WCHAR *converted_path = RtlAllocateHeap(GetProcessHeap(), 0, dos_path_len * sizeof(WCHAR));; + WCHAR *converted_path = RtlAllocateHeap(GetProcessHeap(), 0, (dos_path_len+1) * sizeof(WCHAR));; wcscpy(converted_path, dos_path); - collapse_path(converted_path, 3); + collapse_path(converted_path, 0);
+ if (wcslen(converted_path) == 0) + { + memset(relative,0,sizeof(*relative)); // Collapsed path is empty so don't bother + goto out; + } if (NtCurrentTeb()->Tib.SubSystemTib) /* FIXME: hack */ cur_dir = &((WIN16_SUBSYSTEM_TIB *)NtCurrentTeb()->Tib.SubSystemTib)->curdir.DosPath; else cur_dir = &NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory.DosPath;
- /* FIXME: Better way besides invoking this function twice? */ + /* FIXME: Better way besides invoking this function twice? Maybe a more direct way of getting current dir in nt path form? */ ret_rel = RtlDosPathNameToNtPathName_U_WithStatus(cur_dir->Buffer, &cur_dir_nt, NULL, NULL); if (ret_rel != STATUS_SUCCESS) goto out; @@ -433,16 +438,21 @@ NTSTATUS WINAPI RtlDosPathNameToRelativeNtPathName_U_WithStatus(const WCHAR *dos attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL;
+ // Give open directory handle nts = NtOpenFile(&handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &io, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
if (nts != STATUS_SUCCESS) goto out; + RtlInitUnicodeString(&(relative->RelativeName),converted_path); relative->ContainerDirectory = handle; - // No idea what this does. + + // FIXME: No idea what this does. Some reference count or something? relative->CurDirRef = NULL; + + RtlFreeUnicodeString(&cur_dir_nt); } else {
Hi
thanks for the submission
from a cursory look (didn't go into the implementation details): - don't use C++ comment - don't do white space only changes - don't put several semi-colons at the end of line - the second commit should be merged into the first one - you could do without 'goto':s in implementation - there's lots of FIXME:s inside the code, letting think that the work isn't fully done - please start with a commit adding tests for RtlDosPathNameToRelativeNtPathName_U_WithStatus; that could (maybe) help with previous bullet point => this should cover: access rights (why did you remove the DELETE access flag in second commit?, what's the handling of relative parameter (optional?, zero out content in case of error?...) - second commit should be your implementation changes