fixed GetTempFileNameA/W by ripping from wine

impl. GetLongPathNameA/W by ripping from wine
impl. EnumResourceNamesA/W by ripping from wine
Use common routines for filename A2W/W2A conversion (wine inspired)
impl. ReadDirectoryChangesW (kmode part is not workin yet)
fixed RtlSetCurrentDirectory_U (dont convert to long path)

svn path=/trunk/; revision=14101
This commit is contained in:
Gunnar Dalsnes 2005-03-15 19:40:22 +00:00
parent e035ce116b
commit cb05e516a2
13 changed files with 1039 additions and 1117 deletions

View file

@ -14,12 +14,12 @@ LdrFindResource_U(IN PVOID BaseAddress,
IN ULONG Level,
OUT PIMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry);
/*NTSTATUS STDCALL
NTSTATUS STDCALL
LdrFindResourceDirectory_U( IN PVOID BaseAddress,
IN PLDR_RESOURCE_INFO ResourceInfo,
IN PLDR_RESOURCE_INFO ResourceInfo,
IN ULONG Level,
OUT PIMAGE_RESOURCE_DIRECTORY *ResourceDirectory);
*/
NTSTATUS STDCALL
LdrEnumResources(IN PVOID BaseAddress,
IN PLDR_RESOURCE_INFO ResourceInfo,

View file

@ -42,34 +42,14 @@ FindFirstChangeNotificationA (
DWORD dwNotifyFilter
)
{
UNICODE_STRING PathNameU;
ANSI_STRING PathName;
HANDLE hNotify;
PWCHAR PathNameW;
RtlInitAnsiString (&PathName,
(LPSTR)lpPathName);
if (!(PathNameW = FilenameA2W(lpPathName, FALSE)))
return INVALID_HANDLE_VALUE;
/* convert ansi (or oem) string to unicode */
if (bIsFileApiAnsi)
{
RtlAnsiStringToUnicodeString (&PathNameU,
&PathName,
TRUE);
}
else
{
RtlOemStringToUnicodeString (&PathNameU,
&PathName,
TRUE);
}
hNotify = FindFirstChangeNotificationW (PathNameU.Buffer,
return FindFirstChangeNotificationW (PathNameW ,
bWatchSubtree,
dwNotifyFilter);
RtlFreeUnicodeString(&PathNameU);
return hNotify;
}
@ -90,13 +70,6 @@ FindFirstChangeNotificationW (
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE hDir;
/*
RtlDosPathNameToNtPathName takes a fully qualified file name "C:\Projects\LoadLibrary\Debug\TestDll.dll"
and returns something like "\??\C:\Projects\LoadLibrary\Debug\TestDll.dll."
If the file name cannot be interpreted, then the routine returns STATUS_OBJECT_PATH_SYNTAX_BAD and
ends execution.
*/
if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpPathName,
&NtPathU,
NULL,
@ -106,9 +79,11 @@ FindFirstChangeNotificationW (
return INVALID_HANDLE_VALUE;
}
InitializeObjectAttributes (&ObjectAttributes,
&NtPathU,
0,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
@ -119,6 +94,23 @@ FindFirstChangeNotificationW (
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_DIRECTORY_FILE);
/*
FIXME: I think we should use FILE_OPEN_FOR_BACKUP_INTENT. See M$ Q188321
-Gunnar
*/
/* FIXME: We free the string alloced by RtlDosPathNameToNtPathName_U, but what
* about the special case where the user can pass a \\?\ path? We must not free
* the users buffer!. But should we even call RtlDosPathNameToNtPathName_U in that
* case??? -Gunnar
*/
RtlFreeUnicodeString( &NtPathU);
if (!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
@ -157,15 +149,16 @@ FindNextChangeNotification (
NTSTATUS Status;
Status = NtNotifyChangeDirectoryFile(hChangeHandle,
NULL,
NULL,
NULL,
&IoStatus,
NULL,//Buffer,
0,//BufferLength,
FILE_NOTIFY_CHANGE_SECURITY,//meaningless for subsequent calls, but must contain a valid flag(s)
0//meaningless for subsequent calls
);
NULL,
NULL,
NULL,
&IoStatus,
NULL,//Buffer,
0,//BufferLength,
FILE_NOTIFY_CHANGE_SECURITY,//meaningless/ignored for subsequent calls, but must contain a valid flag
0 //meaningless/ignored for subsequent calls
);
if (!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
@ -175,4 +168,62 @@ FindNextChangeNotification (
return TRUE;
}
extern VOID STDCALL
(ApcRoutine)(PVOID ApcContext,
struct _IO_STATUS_BLOCK* IoStatusBlock,
ULONG Reserved);
/*
* @implemented
*/
BOOL
STDCALL
ReadDirectoryChangesW(
HANDLE hDirectory,
LPVOID lpBuffer OPTIONAL,
DWORD nBufferLength,
BOOL bWatchSubtree,
DWORD dwNotifyFilter,
LPDWORD lpBytesReturned, /* undefined for asych. operations */
LPOVERLAPPED lpOverlapped OPTIONAL,
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine /* OPTIONAL???????? */
)
{
NTSTATUS Status;
IO_STATUS_BLOCK IoStatus;
if (lpOverlapped )
lpOverlapped->Internal = STATUS_PENDING;
Status = NtNotifyChangeDirectoryFile(
hDirectory,
lpOverlapped ? lpOverlapped->hEvent : NULL,
lpCompletionRoutine ? ApcRoutine : NULL, /* ApcRoutine OPTIONAL???? */
lpCompletionRoutine, /* ApcContext */
lpOverlapped ? (PIO_STATUS_BLOCK)lpOverlapped : &IoStatus,
lpBuffer,
nBufferLength,
dwNotifyFilter,
bWatchSubtree
);
if (!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
return FALSE;
}
/* NOTE: lpBytesReturned is undefined for asynch. operations */
*lpBytesReturned = IoStatus.Information;
return TRUE;
}
/* EOF */

View file

@ -25,6 +25,9 @@ UNICODE_STRING WindowsDirectory;
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
@ -35,71 +38,19 @@ GetCurrentDirectoryA (
LPSTR lpBuffer
)
{
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
ULONG Length;
WCHAR BufferW[MAX_PATH];
DWORD ret;
/* allocate buffer for unicode string */
UnicodeString.Length = 0;
UnicodeString.MaximumLength = nBufferLength * sizeof(WCHAR);
if (nBufferLength > 0)
{
UnicodeString.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
0,
UnicodeString.MaximumLength);
ret = GetCurrentDirectoryW(MAX_PATH, BufferW);
/* initialize ansi string */
AnsiString.Length = 0;
AnsiString.MaximumLength = nBufferLength;
AnsiString.Buffer = lpBuffer;
}
else
{
UnicodeString.Buffer = NULL;
}
/* get current directory */
UnicodeString.Length = RtlGetCurrentDirectory_U (UnicodeString.MaximumLength,
UnicodeString.Buffer);
DPRINT("UnicodeString.Buffer %wZ\n", &UnicodeString);
/* convert unicode string to ansi (or oem) */
if (bIsFileApiAnsi)
{
Length = RtlUnicodeStringToAnsiSize (&UnicodeString);
if (Length > nBufferLength)
{
RtlFreeHeap (RtlGetProcessHeap (),
0,
UnicodeString.Buffer);
return Length-1;
}
RtlUnicodeStringToAnsiString (&AnsiString,
&UnicodeString,
FALSE);
}
else
{
Length = RtlUnicodeStringToOemSize (&UnicodeString);
if (Length > nBufferLength)
{
RtlFreeHeap (RtlGetProcessHeap (),
0,
UnicodeString.Buffer);
return Length-1;
}
RtlUnicodeStringToOemString (&AnsiString,
&UnicodeString,
FALSE);
}
DPRINT("AnsiString.Buffer %s\n", AnsiString.Buffer);
/* free unicode string */
RtlFreeHeap (RtlGetProcessHeap (),
0,
UnicodeString.Buffer);
return AnsiString.Length;
if (!ret) return 0;
if (ret > MAX_PATH)
{
SetLastError(ERROR_FILENAME_EXCED_RANGE);
return 0;
}
return FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1);
}
@ -122,6 +73,7 @@ GetCurrentDirectoryW (
}
/*
* @implemented
*/
@ -131,26 +83,15 @@ SetCurrentDirectoryA (
LPCSTR lpPathName
)
{
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
PUNICODE_STRING PathNameU;
NTSTATUS Status;
RtlInitAnsiString (&AnsiString,
(LPSTR)lpPathName);
DPRINT("setcurrdir: %s\n",lpPathName);
/* convert ansi (or oem) to unicode */
if (bIsFileApiAnsi)
RtlAnsiStringToUnicodeString (&UnicodeString,
&AnsiString,
TRUE);
else
RtlOemStringToUnicodeString (&UnicodeString,
&AnsiString,
TRUE);
if (!(PathNameU = FilenameA2U(lpPathName, FALSE)))
return FALSE;
Status = RtlSetCurrentDirectory_U (&UnicodeString);
RtlFreeUnicodeString (&UnicodeString);
Status = RtlSetCurrentDirectory_U(PathNameU);
if (!NT_SUCCESS(Status))
{
@ -190,6 +131,8 @@ SetCurrentDirectoryW (
/*
* @implemented
*
* NOTE: Windows returns a dos/short (8.3) path
*/
DWORD
STDCALL
@ -198,138 +141,82 @@ GetTempPathA (
LPSTR lpBuffer
)
{
UNICODE_STRING UnicodeString;
ANSI_STRING AnsiString;
DWORD Length;
WCHAR BufferW[MAX_PATH];
DWORD ret;
AnsiString.Length = 0;
AnsiString.MaximumLength = nBufferLength;
AnsiString.Buffer = lpBuffer;
ret = GetTempPathW(MAX_PATH, BufferW);
/* initialize allocate unicode string */
UnicodeString.Length = 0;
if(nBufferLength > 0)
{
UnicodeString.MaximumLength = (nBufferLength + 1) * sizeof(WCHAR);
UnicodeString.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
0,
UnicodeString.MaximumLength);
if (UnicodeString.Buffer == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
}
else
{
UnicodeString.MaximumLength = 0;
UnicodeString.Buffer = NULL;
}
if (!ret)
return 0;
Length = GetTempPathW (nBufferLength,
UnicodeString.Buffer);
if (ret > MAX_PATH)
{
SetLastError(ERROR_FILENAME_EXCED_RANGE);
return 0;
}
if (nBufferLength >= Length)
{
/* only touch the buffer if the supplied buffer length is at least
the length that GetTempPathW returned! */
UnicodeString.Length = Length * sizeof(WCHAR);
/* convert unicode string to ansi (or oem) */
if (bIsFileApiAnsi)
RtlUnicodeStringToAnsiString (&AnsiString,
&UnicodeString,
FALSE);
else
RtlUnicodeStringToOemString (&AnsiString,
&UnicodeString,
FALSE);
}
/* free unicode string buffer */
RtlFreeHeap (RtlGetProcessHeap (),
0,
UnicodeString.Buffer);
return Length;
return FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1);
}
/*
* @implemented
*
* ripped from wine
*/
DWORD
STDCALL
GetTempPathW (
DWORD nBufferLength,
LPWSTR lpBuffer
DWORD count,
LPWSTR path
)
{
UNICODE_STRING Name;
PUNICODE_STRING Value;
PTEB Teb;
DWORD Length;
NTSTATUS Status;
WCHAR tmp_path[MAX_PATH];
WCHAR tmp_full_path[MAX_PATH];
UINT ret;
Teb = NtCurrentTeb();
Teb->StaticUnicodeString.Length = 0;
Teb->StaticUnicodeString.MaximumLength = MAX_PATH * sizeof(WCHAR);
Teb->StaticUnicodeString.Buffer = Teb->StaticUnicodeBuffer;
Value = &Teb->StaticUnicodeString;
DPRINT("GetTempPathW(%lu,%p)\n", nBufferLength, lpBuffer);
RtlRosInitUnicodeStringFromLiteral (&Name,
L"TMP");
if (!(ret = GetEnvironmentVariableW( L"TMP", tmp_path, MAX_PATH )))
if (!(ret = GetEnvironmentVariableW( L"TEMP", tmp_path, MAX_PATH )))
if (!(ret = GetCurrentDirectoryW( MAX_PATH, tmp_path )))
return 0;
Status = RtlQueryEnvironmentVariable_U (NULL,
&Name,
Value);
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL)
{
RtlRosInitUnicodeStringFromLiteral (&Name,
L"TEMP");
if (ret > MAX_PATH)
{
SetLastError(ERROR_FILENAME_EXCED_RANGE);
return 0;
}
Status = RtlQueryEnvironmentVariable_U (NULL,
&Name,
Value);
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL)
{
Value->Length = RtlGetCurrentDirectory_U(Value->MaximumLength,
Value->Buffer);
}
}
ret = GetFullPathNameW(tmp_path, MAX_PATH, tmp_full_path, NULL);
if (!ret) return 0;
if (!NT_SUCCESS(Status))
{
SetLastError(RtlNtStatusToDosError(Status));
return 0;
}
if (ret > MAX_PATH - 2)
{
SetLastError(ERROR_FILENAME_EXCED_RANGE);
return 0;
}
Length = Value->Length / sizeof(WCHAR) + 1;
if (nBufferLength < Value->Length / sizeof(WCHAR) + 2)
Length++;
if (tmp_full_path[ret-1] != '\\')
{
tmp_full_path[ret++] = '\\';
tmp_full_path[ret] = '\0';
}
if (nBufferLength >= Value->Length /sizeof(WCHAR) + 1)
{
if (nBufferLength < Value->Length / sizeof(WCHAR) + 2)
{
memcpy (lpBuffer,
Value->Buffer,
nBufferLength * sizeof(WCHAR));
}
else
{
memcpy (lpBuffer,
Value->Buffer,
Value->Length);
lpBuffer[Value->Length / sizeof(WCHAR)] = L'\\';
lpBuffer[Value->Length / sizeof(WCHAR) + 1] = 0;
}
} else if (nBufferLength > 0)
{
lpBuffer[0] = L'\0';
}
ret++; /* add space for terminating 0 */
if (count)
{
lstrcpynW(path, tmp_full_path, count);
if (count >= ret)
ret--; /* return length without 0 */
else if (count < 4)
path[0] = 0; /* avoid returning ambiguous "X:" */
}
DPRINT("GetTempPathW returning %u, %s\n", ret, path);
return ret;
return Length;
}
@ -343,37 +230,7 @@ GetSystemDirectoryA (
UINT uSize
)
{
ANSI_STRING String;
ULONG Length;
NTSTATUS Status;
Length = RtlUnicodeStringToAnsiSize (&SystemDirectory); //len of ansi str incl. nullchar
if (lpBuffer == NULL)
return Length;
if (uSize >= Length){
String.Length = 0;
String.MaximumLength = uSize;
String.Buffer = lpBuffer;
/* convert unicode string to ansi (or oem) */
if (bIsFileApiAnsi)
Status = RtlUnicodeStringToAnsiString (&String,
&SystemDirectory,
FALSE);
else
Status = RtlUnicodeStringToOemString (&String,
&SystemDirectory,
FALSE);
if (!NT_SUCCESS(Status) )
return 0;
return Length-1; //good: ret chars excl. nullchar
}
return Length; //bad: ret space needed incl. nullchar
return FilenameU2A_FitOrFail(lpBuffer, uSize, &SystemDirectory);
}
@ -416,38 +273,7 @@ GetWindowsDirectoryA (
UINT uSize
)
{
ANSI_STRING String;
ULONG Length;
NTSTATUS Status;
Length = RtlUnicodeStringToAnsiSize (&WindowsDirectory); //len of ansi str incl. nullchar
if (lpBuffer == NULL)
return Length;
if (uSize >= Length){
String.Length = 0;
String.MaximumLength = uSize;
String.Buffer = lpBuffer;
/* convert unicode string to ansi (or oem) */
if (bIsFileApiAnsi)
Status = RtlUnicodeStringToAnsiString (&String,
&WindowsDirectory,
FALSE);
else
Status = RtlUnicodeStringToOemString (&String,
&WindowsDirectory,
FALSE);
if (!NT_SUCCESS(Status))
return 0;
return Length-1; //good: ret chars excl. nullchar
}
return Length; //bad: ret space needed incl. nullchar
return FilenameU2A_FitOrFail(lpBuffer, uSize, &WindowsDirectory);
}

View file

@ -50,65 +50,26 @@ CreateDirectoryExA (
LPCSTR lpNewDirectory,
LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{
UNICODE_STRING TmplDirU;
UNICODE_STRING NewDirU;
ANSI_STRING TmplDir;
ANSI_STRING NewDir;
BOOL Result;
PWCHAR TemplateDirectoryW;
PWCHAR NewDirectoryW;
BOOL ret;
RtlInitUnicodeString (&TmplDirU,
NULL);
if (!(TemplateDirectoryW = FilenameA2W(lpTemplateDirectory, FALSE)))
return FALSE;
if (!(NewDirectoryW = FilenameA2W(lpNewDirectory, TRUE)))
return FALSE;
ret = CreateDirectoryExW (TemplateDirectoryW,
NewDirectoryW,
lpSecurityAttributes);
RtlInitUnicodeString (&NewDirU,
NULL);
if (lpNewDirectory != NULL)
RtlFreeHeap (RtlGetProcessHeap (),
0,
NewDirectoryW);
if (lpTemplateDirectory != NULL)
{
RtlInitAnsiString (&TmplDir,
(LPSTR)lpTemplateDirectory);
/* convert ansi (or oem) string to unicode */
if (bIsFileApiAnsi)
RtlAnsiStringToUnicodeString (&TmplDirU,
&TmplDir,
TRUE);
else
RtlOemStringToUnicodeString (&TmplDirU,
&TmplDir,
TRUE);
}
if (lpNewDirectory != NULL)
{
RtlInitAnsiString (&NewDir,
(LPSTR)lpNewDirectory);
/* convert ansi (or oem) string to unicode */
if (bIsFileApiAnsi)
RtlAnsiStringToUnicodeString (&NewDirU,
&NewDir,
TRUE);
else
RtlOemStringToUnicodeString (&NewDirU,
&NewDir,
TRUE);
}
Result = CreateDirectoryExW (TmplDirU.Buffer,
NewDirU.Buffer,
lpSecurityAttributes);
if (lpTemplateDirectory != NULL)
RtlFreeHeap (RtlGetProcessHeap (),
0,
TmplDirU.Buffer);
if (lpNewDirectory != NULL)
RtlFreeHeap (RtlGetProcessHeap (),
0,
NewDirU.Buffer);
return Result;
return ret;
}
@ -215,30 +176,14 @@ RemoveDirectoryA (
LPCSTR lpPathName
)
{
UNICODE_STRING PathNameU;
ANSI_STRING PathName;
BOOL Result;
PWCHAR PathNameW;
DPRINT("RemoveDirectoryA(%s)\n",lpPathName);
RtlInitAnsiString (&PathName,
(LPSTR)lpPathName);
if (!(PathNameW = FilenameA2W(lpPathName, FALSE)))
return FALSE;
/* convert ansi (or oem) string to unicode */
if (bIsFileApiAnsi)
RtlAnsiStringToUnicodeString (&PathNameU,
&PathName,
TRUE);
else
RtlOemStringToUnicodeString (&PathNameU,
&PathName,
TRUE);
Result = RemoveDirectoryW (PathNameU.Buffer);
RtlFreeHeap (RtlGetProcessHeap (),
0,
PathNameU.Buffer);
return Result;
return RemoveDirectoryW (PathNameW);
}
@ -337,70 +282,49 @@ GetFullPathNameA (
LPSTR *lpFilePart
)
{
UNICODE_STRING nameW;
WCHAR bufferW[MAX_PATH];
DWORD ret;
LPWSTR FilePart = NULL;
WCHAR BufferW[MAX_PATH];
PWCHAR FileNameW;
DWORD ret;
LPWSTR FilePartW = NULL;
DPRINT("GetFullPathNameA(lpFileName %s, nBufferLength %d, lpBuffer %p, "
"lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart);
DPRINT("GetFullPathNameA(lpFileName %s, nBufferLength %d, lpBuffer %p, "
"lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart);
if (!lpFileName)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if (!lpFileName)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if (!RtlCreateUnicodeStringFromAsciiz(&nameW, (LPSTR)lpFileName))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
return 0;
if (lpFilePart)
{
*lpFilePart = NULL;
}
ret = GetFullPathNameW(FileNameW, MAX_PATH, BufferW, &FilePartW);
if (!ret)
return 0;
if (ret > MAX_PATH)
{
SetLastError(ERROR_FILENAME_EXCED_RANGE);
return 0;
}
ret = FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1);
if (ret < nBufferLength && lpFilePart)
{
/* if the path closed with '\', FilePart is NULL */
if (!FilePartW)
*lpFilePart=NULL;
else
*lpFilePart = (FilePartW - BufferW) + lpBuffer;
}
DPRINT("GetFullPathNameA ret: lpBuffer %s lpFilePart %s\n",
lpBuffer, (lpFilePart == NULL) ? "NULL" : *lpFilePart);
ret = GetFullPathNameW(nameW.Buffer, MAX_PATH, bufferW, &FilePart);
if (MAX_PATH < ret)
{
SetLastError(ERROR_FILENAME_EXCED_RANGE);
ret = 0;
}
else if (0 < ret)
{
if (ret < nBufferLength)
{
ANSI_STRING AnsiBuffer;
UNICODE_STRING UnicodeBuffer;
UnicodeBuffer.Length = wcslen(bufferW) * sizeof(WCHAR);
UnicodeBuffer.MaximumLength = MAX_PATH * sizeof(WCHAR);
UnicodeBuffer.Buffer = bufferW;
AnsiBuffer.MaximumLength = nBufferLength;
AnsiBuffer.Length = 0;
AnsiBuffer.Buffer = lpBuffer;
RtlUnicodeStringToAnsiString(&AnsiBuffer, &UnicodeBuffer, FALSE);
if (lpFilePart && FilePart != NULL)
{
*lpFilePart = (FilePart - bufferW) + lpBuffer;
}
}
else
{
ret++;
}
}
RtlFreeUnicodeString(&nameW);
DPRINT("lpBuffer %s lpFilePart %s Length %ld\n",
lpBuffer, (lpFilePart == NULL) ? "NULL" : *lpFilePart, nameW.Length);
return ret;
return ret;
}
@ -426,17 +350,10 @@ GetFullPathNameW (
lpBuffer,
lpFilePart);
DPRINT("lpBuffer %S lpFilePart %S Length %ld\n",
DPRINT("GetFullPathNameW ret: lpBuffer %S lpFilePart %S Length %ld\n",
lpBuffer, (lpFilePart == NULL) ? L"NULL" : *lpFilePart, Length / sizeof(WCHAR));
Length = Length / sizeof(WCHAR);
if (nBufferLength < Length + 1)
{
DPRINT("Adjusting Length for terminator\n");
Length++;
}
return Length;
return Length/sizeof(WCHAR);
}
@ -452,9 +369,9 @@ GetShortPathNameA (
DWORD shortlen
)
{
UNICODE_STRING longpathW;
WCHAR shortpathW[MAX_PATH];
DWORD ret, retW;
PWCHAR LongPathW;
WCHAR ShortPathW[MAX_PATH];
DWORD ret;
if (!longpath)
{
@ -462,33 +379,21 @@ GetShortPathNameA (
return 0;
}
if (!RtlCreateUnicodeStringFromAsciiz(&longpathW, longpath))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
if (!(LongPathW = FilenameA2W(longpath, FALSE)))
return 0;
ret = GetShortPathNameW(LongPathW, ShortPathW, MAX_PATH);
if (!ret)
return 0;
}
retW = GetShortPathNameW(longpathW.Buffer, shortpathW, MAX_PATH);
if (!retW)
ret = 0;
else if (retW > PATH_MAX)
if (ret > MAX_PATH)
{
SetLastError(ERROR_FILENAME_EXCED_RANGE);
ret = 0;
return 0;
}
else
{
ret = WideCharToMultiByte(CP_ACP, 0, shortpathW, -1, NULL, 0, NULL, NULL);
if (ret <= shortlen)
{
WideCharToMultiByte(CP_ACP, 0, shortpathW, -1, shortpath, shortlen, NULL, NULL);
ret--; /* length without 0 */
}
}
RtlFreeUnicodeString(&longpathW);
return ret;
return FilenameW2A_FitOrFail(shortpath, shortlen, ShortPathW, ret+1);
}
@ -513,6 +418,8 @@ GetShortPathNameW (
UNICODE_STRING ustr;
WCHAR ustr_buf[8+1+3+1];
DPRINT("GetShortPathNameW: %S\n",longpath);
if (!longpath)
{
SetLastError(ERROR_INVALID_PARAMETER);
@ -931,38 +838,18 @@ SetDllDirectoryW(
BOOL
STDCALL
SetDllDirectoryA(
LPCSTR lpPathName
LPCSTR lpPathName /* can be NULL */
)
{
UNICODE_STRING PathNameU;
ANSI_STRING PathNameA;
BOOL Ret;
PWCHAR PathNameW=NULL;
if(lpPathName != NULL)
if(lpPathName)
{
RtlInitAnsiString(&PathNameA, lpPathName);
if(bIsFileApiAnsi)
{
RtlAnsiStringToUnicodeString(&PathNameU, &PathNameA, TRUE);
}
else
{
RtlOemStringToUnicodeString(&PathNameU, &PathNameA, TRUE);
}
}
else
{
PathNameU.Buffer = NULL;
if (!(PathNameW = FilenameA2W(lpPathName, FALSE)))
return FALSE;
}
Ret = SetDllDirectoryW(PathNameU.Buffer);
if(lpPathName != NULL)
{
RtlFreeUnicodeString(&PathNameU);
}
return Ret;
return SetDllDirectoryW(PathNameW);
}
/*
@ -1012,51 +899,21 @@ GetDllDirectoryA(
LPSTR lpBuffer
)
{
UNICODE_STRING PathNameU;
ANSI_STRING PathNameA;
DWORD Ret;
if(nBufferLength > 0)
WCHAR BufferW[MAX_PATH];
DWORD ret;
ret = GetDllDirectoryW(MAX_PATH, BufferW);
if (!ret)
return 0;
if (ret > MAX_PATH)
{
if(!(PathNameU.Buffer = (PWSTR)RtlAllocateHeap(RtlGetProcessHeap(),
0,
nBufferLength * sizeof(WCHAR))))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
PathNameU.Length = 0;
PathNameU.MaximumLength = nBufferLength * sizeof(WCHAR);
}
Ret = GetDllDirectoryW(nBufferLength,
((nBufferLength > 0) ? PathNameU.Buffer : NULL));
if(nBufferLength > 0)
{
PathNameU.Length = Ret * sizeof(WCHAR);
PathNameA.Length = 0;
PathNameA.MaximumLength = nBufferLength;
PathNameA.Buffer = lpBuffer;
if(Ret > 0)
{
if(bIsFileApiAnsi)
{
RtlUnicodeStringToAnsiString(&PathNameA, &PathNameU, FALSE);
}
else
{
RtlUnicodeStringToOemString(&PathNameA, &PathNameU, FALSE);
}
}
lpBuffer[Ret] = '\0';
RtlFreeHeap(RtlGetProcessHeap(), 0, PathNameU.Buffer);
SetLastError(ERROR_FILENAME_EXCED_RANGE);
return 0;
}
return Ret;
return FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1);
}
@ -1078,25 +935,148 @@ NeedCurrentDirectoryForExePathW(LPCWSTR ExeName)
BOOL STDCALL
NeedCurrentDirectoryForExePathA(LPCSTR ExeName)
{
ANSI_STRING ExeNameA;
UNICODE_STRING ExeNameU;
BOOL Ret;
PWCHAR ExeNameW;
RtlInitAnsiString(&ExeNameA, ExeName);
if(bIsFileApiAnsi)
{
RtlAnsiStringToUnicodeString(&ExeNameU, &ExeNameA, TRUE);
}
else
{
RtlOemStringToUnicodeString(&ExeNameU, &ExeNameA, TRUE);
}
if (!(ExeNameW = FilenameA2W(ExeName, FALSE)))
return FALSE;
Ret = NeedCurrentDirectoryForExePathW(ExeNameU.Buffer);
RtlFreeUnicodeString(&ExeNameU);
return Ret;
return NeedCurrentDirectoryForExePathW(ExeNameW);
}
/***********************************************************************
* @implemented
*
* GetLongPathNameW (KERNEL32.@)
*
* NOTES
* observed (Win2000):
* shortpath=NULL: LastError=ERROR_INVALID_PARAMETER, ret=0
* shortpath="": LastError=ERROR_PATH_NOT_FOUND, ret=0
*/
DWORD STDCALL GetLongPathNameW( LPCWSTR shortpath, LPWSTR longpath, DWORD longlen )
{
#define MAX_PATHNAME_LEN 1024
WCHAR tmplongpath[MAX_PATHNAME_LEN];
LPCWSTR p;
DWORD sp = 0, lp = 0;
DWORD tmplen;
BOOL unixabsolute = (shortpath[0] == '/');
WIN32_FIND_DATAW wfd;
HANDLE goit;
if (!shortpath)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if (!shortpath[0])
{
SetLastError(ERROR_PATH_NOT_FOUND);
return 0;
}
DPRINT("GetLongPathNameW(%s,%p,%ld)\n", shortpath, longpath, longlen);
if (shortpath[0] == '\\' && shortpath[1] == '\\')
{
DPRINT1("ERR: UNC pathname %s\n", shortpath);
lstrcpynW( longpath, shortpath, longlen );
return wcslen(longpath);
}
/* check for drive letter */
if (!unixabsolute && shortpath[1] == ':' )
{
tmplongpath[0] = shortpath[0];
tmplongpath[1] = ':';
lp = sp = 2;
}
while (shortpath[sp])
{
/* check for path delimiters and reproduce them */
if (shortpath[sp] == '\\' || shortpath[sp] == '/')
{
if (!lp || tmplongpath[lp-1] != '\\')
{
/* strip double "\\" */
tmplongpath[lp++] = '\\';
}
tmplongpath[lp] = 0; /* terminate string */
sp++;
continue;
}
p = shortpath + sp;
if (sp == 0 && p[0] == '.' && (p[1] == '/' || p[1] == '\\'))
{
tmplongpath[lp++] = *p++;
tmplongpath[lp++] = *p++;
}
for (; *p && *p != '/' && *p != '\\'; p++);
tmplen = p - (shortpath + sp);
lstrcpynW(tmplongpath + lp, shortpath + sp, tmplen + 1);
/* Check if the file exists and use the existing file name */
goit = FindFirstFileW(tmplongpath, &wfd);
if (goit == INVALID_HANDLE_VALUE)
{
DPRINT("not found %s!\n", tmplongpath);
SetLastError ( ERROR_FILE_NOT_FOUND );
return 0;
}
FindClose(goit);
wcscpy(tmplongpath + lp, wfd.cFileName);
lp += wcslen(tmplongpath + lp);
sp += tmplen;
}
tmplen = wcslen(shortpath) - 1;
if ((shortpath[tmplen] == '/' || shortpath[tmplen] == '\\') &&
(tmplongpath[lp - 1] != '/' && tmplongpath[lp - 1] != '\\'))
tmplongpath[lp++] = shortpath[tmplen];
tmplongpath[lp] = 0;
tmplen = wcslen(tmplongpath) + 1;
if (tmplen <= longlen)
{
wcscpy(longpath, tmplongpath);
DPRINT("returning %s\n", longpath);
tmplen--; /* length without 0 */
}
return tmplen;
}
/***********************************************************************
* GetLongPathNameA (KERNEL32.@)
*/
DWORD STDCALL GetLongPathNameA( LPCSTR shortpath, LPSTR longpath, DWORD longlen )
{
WCHAR *shortpathW;
WCHAR longpathW[MAX_PATH];
DWORD ret;
DPRINT("GetLongPathNameA %s, %i\n",shortpath,longlen );
if (!(shortpathW = FilenameA2W( shortpath, FALSE )))
return 0;
ret = GetLongPathNameW(shortpathW, longpathW, MAX_PATH);
if (!ret) return 0;
if (ret > MAX_PATH)
{
SetLastError(ERROR_FILENAME_EXCED_RANGE);
return 0;
}
return FilenameW2A_FitOrFail(longpath, longlen, longpathW, ret+1 );
}
/* EOF */

View file

@ -25,6 +25,162 @@ BOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem
/* FUNCTIONS ****************************************************************/
PWCHAR
FilenameA2W(LPCSTR NameA, BOOL alloc)
{
PUNICODE_STRING pstrW;
pstrW = FilenameA2U(NameA, alloc);
return pstrW ? pstrW->Buffer : NULL;
}
PUNICODE_STRING
FilenameA2U(LPCSTR NameA, BOOL alloc)
{
ANSI_STRING str;
UNICODE_STRING strW;
PUNICODE_STRING pstrW;
NTSTATUS Status;
ASSERT(NtCurrentTeb()->StaticUnicodeString.Buffer == NtCurrentTeb()->StaticUnicodeBuffer);
ASSERT(NtCurrentTeb()->StaticUnicodeString.MaximumLength == sizeof(NtCurrentTeb()->StaticUnicodeBuffer));
RtlInitAnsiString(&str, NameA);
pstrW = alloc ? &strW : &NtCurrentTeb()->StaticUnicodeString;
if (bIsFileApiAnsi)
Status= RtlAnsiStringToUnicodeString( pstrW, &str, alloc );
else
Status= RtlOemStringToUnicodeString( pstrW, &str, alloc );
if (NT_SUCCESS(Status))
return pstrW;
if (Status== STATUS_BUFFER_OVERFLOW)
SetLastError( ERROR_FILENAME_EXCED_RANGE );
else
SetLastErrorByStatus(Status);
return NULL;
}
/*
No copy/conversion is done if the dest. buffer is too small.
Returns:
Success: number of TCHARS copied into dest. buffer NOT including nullterm
Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm
*/
DWORD
FilenameU2A_FitOrFail(
LPSTR DestA,
INT destLen, /* buffer size in TCHARS incl. nullchar */
PUNICODE_STRING SourceU
)
{
DWORD ret;
ret = bIsFileApiAnsi? RtlUnicodeStringToAnsiSize(SourceU) : RtlUnicodeStringToOemSize(SourceU);
/* ret incl. nullchar */
if (DestA && ret <= destLen)
{
ANSI_STRING str;
str.Buffer = DestA;
str.MaximumLength = destLen;
if (bIsFileApiAnsi)
RtlUnicodeStringToAnsiString(&str, SourceU, FALSE );
else
RtlUnicodeStringToOemString(&str, SourceU, FALSE );
ret = str.Length; /* SUCCESS: length without terminating 0 */
}
return ret;
}
/*
No copy/conversion is done if the dest. buffer is too small.
Returns:
Success: number of TCHARS copied into dest. buffer NOT including nullterm
Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm
*/
DWORD
FilenameW2A_FitOrFail(
LPSTR DestA,
INT destLen, /* buffer size in TCHARS incl. nullchar */
LPCWSTR SourceW,
INT sourceLen /* buffer size in TCHARS incl. nullchar */
)
{
UNICODE_STRING strW;
if (sourceLen < 0) sourceLen = wcslen(SourceW) + 1;
strW.Buffer = (PWCHAR)SourceW;
strW.MaximumLength = sourceLen * sizeof(WCHAR);
strW.Length = strW.MaximumLength - sizeof(WCHAR);
return FilenameU2A_FitOrFail(DestA, destLen, &strW);
}
DWORD
FilenameA2W_N(
LPWSTR dest,
INT destlen, /* buffer size in TCHARS incl. nullchar */
LPCSTR src,
INT srclen /* buffer size in TCHARS incl. nullchar */
)
{
DWORD ret;
if (srclen < 0) srclen = strlen( src ) + 1;
if (bIsFileApiAnsi)
RtlMultiByteToUnicodeN( dest, destlen* sizeof(WCHAR), &ret, (LPSTR)src, srclen );
else
RtlOemToUnicodeN( dest, destlen* sizeof(WCHAR), &ret, (LPSTR)src, srclen );
if (ret) dest[(ret/sizeof(WCHAR))-1]=0;
return ret;
}
DWORD
FilenameW2A_N(
LPSTR dest,
INT destlen, /* buffer size in TCHARS incl. nullchar */
LPCWSTR src,
INT srclen /* buffer size in TCHARS incl. nullchar */
)
{
DWORD ret;
if (srclen < 0) srclen = wcslen( src ) + 1;
if (bIsFileApiAnsi)
RtlUnicodeToMultiByteN( dest, destlen, &ret, (LPWSTR) src, srclen * sizeof(WCHAR));
else
RtlUnicodeToOemN( dest, destlen, &ret, (LPWSTR) src, srclen * sizeof(WCHAR) );
if (ret) dest[ret-1]=0;
return ret;
}
/*
* @implemented
*/
@ -518,29 +674,12 @@ DWORD STDCALL
GetCompressedFileSizeA(LPCSTR lpFileName,
LPDWORD lpFileSizeHigh)
{
UNICODE_STRING FileNameU;
ANSI_STRING FileName;
DWORD Size;
PWCHAR FileNameW;
RtlInitAnsiString(&FileName,
(LPSTR)lpFileName);
if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
return INVALID_FILE_SIZE;
/* convert ansi (or oem) string to unicode */
if (bIsFileApiAnsi)
RtlAnsiStringToUnicodeString(&FileNameU,
&FileName,
TRUE);
else
RtlOemStringToUnicodeString(&FileNameU,
&FileName,
TRUE);
Size = GetCompressedFileSizeW(FileNameU.Buffer,
lpFileSizeHigh);
RtlFreeUnicodeString (&FileNameU);
return Size;
return GetCompressedFileSizeW(FileNameW, lpFileSizeHigh);
}
@ -563,23 +702,28 @@ GetCompressedFileSizeW(LPCWSTR lpFileName,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
return INVALID_FILE_SIZE;
errCode = NtQueryInformationFile(hFile,
&IoStatusBlock,
&FileCompression,
sizeof(FILE_COMPRESSION_INFORMATION),
FileCompressionInformation);
CloseHandle(hFile);
if (!NT_SUCCESS(errCode))
{
CloseHandle(hFile);
SetLastErrorByStatus(errCode);
return INVALID_FILE_SIZE;
}
CloseHandle(hFile);
if(lpFileSizeHigh)
*lpFileSizeHigh = FileCompression.CompressedFileSize.u.HighPart;
SetLastError(NO_ERROR);
return FileCompression.CompressedFileSize.u.LowPart;
}
@ -773,27 +917,12 @@ GetFileAttributesExA(LPCSTR lpFileName,
GET_FILEEX_INFO_LEVELS fInfoLevelId,
LPVOID lpFileInformation)
{
UNICODE_STRING FileNameU;
ANSI_STRING FileName;
BOOL Result;
RtlInitAnsiString (&FileName,
(LPSTR)lpFileName);
PWCHAR FileNameW;
if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
return FALSE;
/* convert ansi (or oem) string to unicode */
if (bIsFileApiAnsi)
RtlAnsiStringToUnicodeString (&FileNameU,
&FileName,
TRUE);
else
RtlOemStringToUnicodeString (&FileNameU,
&FileName,
TRUE);
Result = GetFileAttributesExW(FileNameU.Buffer, fInfoLevelId, lpFileInformation);
RtlFreeUnicodeString (&FileNameU);
return Result;
return GetFileAttributesExW(FileNameW, fInfoLevelId, lpFileInformation);
}
@ -803,29 +932,16 @@ GetFileAttributesExA(LPCSTR lpFileName,
DWORD STDCALL
GetFileAttributesA(LPCSTR lpFileName)
{
WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
UNICODE_STRING FileNameU;
ANSI_STRING FileName;
BOOL Result;
WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
PWSTR FileNameW;
BOOL ret;
RtlInitAnsiString (&FileName,
(LPSTR)lpFileName);
if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
return INVALID_FILE_ATTRIBUTES;
ret = GetFileAttributesExW(FileNameW, GetFileExInfoStandard, &FileAttributeData);
/* convert ansi (or oem) string to unicode */
if (bIsFileApiAnsi)
RtlAnsiStringToUnicodeString (&FileNameU,
&FileName,
TRUE);
else
RtlOemStringToUnicodeString (&FileNameU,
&FileName,
TRUE);
Result = GetFileAttributesExW(FileNameU.Buffer, GetFileExInfoStandard, &FileAttributeData);
RtlFreeUnicodeString (&FileNameU);
return Result ? FileAttributeData.dwFileAttributes : 0xffffffff;
return ret ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
}
@ -842,36 +958,20 @@ GetFileAttributesW(LPCWSTR lpFileName)
Result = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &FileAttributeData);
return Result ? FileAttributeData.dwFileAttributes : 0xffffffff;
return Result ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
}
BOOL STDCALL
SetFileAttributesA(LPCSTR lpFileName,
DWORD dwFileAttributes)
SetFileAttributesA(
LPCSTR lpFileName,
DWORD dwFileAttributes)
{
UNICODE_STRING FileNameU;
ANSI_STRING FileName;
BOOL Result;
PWCHAR FileNameW;
RtlInitAnsiString (&FileName,
(LPSTR)lpFileName);
if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
return FALSE;
/* convert ansi (or oem) string to unicode */
if (bIsFileApiAnsi)
RtlAnsiStringToUnicodeString (&FileNameU,
&FileName,
TRUE);
else
RtlOemStringToUnicodeString (&FileNameU,
&FileName,
TRUE);
Result = SetFileAttributesW (FileNameU.Buffer,
dwFileAttributes);
RtlFreeUnicodeString (&FileNameU);
return Result;
return SetFileAttributesW(FileNameW, dwFileAttributes);
}
@ -956,100 +1056,91 @@ SetFileAttributesW(LPCWSTR lpFileName,
}
/*
* @implemented
/***********************************************************************
* GetTempFileNameA (KERNEL32.@)
*/
UINT STDCALL
GetTempFileNameA(LPCSTR lpPathName,
LPCSTR lpPrefixString,
UINT uUnique,
LPSTR lpTempFileName)
UINT WINAPI GetTempFileNameA( LPCSTR path, LPCSTR prefix, UINT unique, LPSTR buffer)
{
HANDLE hFile;
UINT unique = uUnique;
UINT len;
const char *format = "%.*s\\~%.3s%4.4x.TMP";
DPRINT("GetTempFileNameA(lpPathName %s, lpPrefixString %.*s, "
"uUnique %x, lpTempFileName %x)\n", lpPathName, 4,
lpPrefixString, uUnique, lpTempFileName);
if (lpPathName == NULL)
return 0;
len = strlen(lpPathName);
if (len > 0 && (lpPathName[len-1] == '\\' || lpPathName[len-1] == '/'))
len--;
if (uUnique == 0)
uUnique = GetCurrentTime();
WCHAR BufferW[MAX_PATH];
PWCHAR PathW;
WCHAR PrefixW[3+1];
UINT ret;
sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
if (!(PathW = FilenameA2W(path, FALSE)))
return 0;
if (prefix)
FilenameA2W_N(PrefixW, 3+1, prefix, -1);
if (unique)
return uUnique;
ret = GetTempFileNameW(PathW, prefix ? PrefixW : NULL, unique, BufferW);
if (ret)
FilenameW2A_N(buffer, MAX_PATH, BufferW, -1);
while ((hFile = CreateFileA(lpTempFileName, GENERIC_WRITE, 0, NULL,
CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
0)) == INVALID_HANDLE_VALUE)
{
if (GetLastError() != ERROR_FILE_EXISTS)
{
return 0;
}
sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
}
CloseHandle(hFile);
return uUnique;
return ret;
}
/***********************************************************************
* GetTempFileNameW (KERNEL32.@)
*/
UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, LPWSTR buffer )
{
static const WCHAR formatW[] = L"%x.tmp";
int i;
LPWSTR p;
if ( !path || !prefix || !buffer )
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
wcscpy( buffer, path );
p = buffer + wcslen(buffer);
/* add a \, if there isn't one */
if ((p == buffer) || (p[-1] != '\\')) *p++ = '\\';
for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
unique &= 0xffff;
if (unique) swprintf( p, formatW, unique );
else
{
/* get a "random" unique number and try to create the file */
HANDLE handle;
UINT num = GetTickCount() & 0xffff;
if (!num) num = 1;
unique = num;
do
{
swprintf( p, formatW, unique );
handle = CreateFileW( buffer, GENERIC_WRITE, 0, NULL,
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
if (handle != INVALID_HANDLE_VALUE)
{ /* We created it */
DPRINT("created %S\n", buffer);
CloseHandle( handle );
break;
}
if (GetLastError() != ERROR_FILE_EXISTS &&
GetLastError() != ERROR_SHARING_VIOLATION)
break; /* No need to go on */
if (!(++unique & 0xffff)) unique = 1;
} while (unique != num);
}
DPRINT("returning %S\n", buffer);
return unique;
}
/*
* @implemented
*/
UINT STDCALL
GetTempFileNameW(LPCWSTR lpPathName,
LPCWSTR lpPrefixString,
UINT uUnique,
LPWSTR lpTempFileName)
{
HANDLE hFile;
UINT unique = uUnique;
UINT len;
const WCHAR *format = L"%.*s\\~%.3s%4.4x.TMP";
DPRINT("GetTempFileNameW(lpPathName %S, lpPrefixString %.*S, "
"uUnique %x, lpTempFileName %x)\n", lpPathName, 4,
lpPrefixString, uUnique, lpTempFileName);
if (lpPathName == NULL)
return 0;
len = wcslen(lpPathName);
if (len > 0 && (lpPathName[len-1] == L'\\' || lpPathName[len-1] == L'/'))
len--;
if (uUnique == 0)
uUnique = GetCurrentTime();
swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
if (unique)
return uUnique;
while ((hFile = CreateFileW(lpTempFileName, GENERIC_WRITE, 0, NULL,
CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
0)) == INVALID_HANDLE_VALUE)
{
if (GetLastError() != ERROR_FILE_EXISTS)
{
return 0;
}
swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
}
CloseHandle(hFile);
return uUnique;
}
/*
@ -1258,6 +1349,7 @@ SetFileValidData(
}
/*
* @implemented
*/
@ -1324,10 +1416,7 @@ SetFileShortNameA(
LPCSTR lpShortName
)
{
NTSTATUS Status;
BOOL Ret;
ANSI_STRING ShortNameA;
UNICODE_STRING ShortName;
PWCHAR ShortNameW;
if(IsConsoleHandle(hFile))
{
@ -1341,22 +1430,10 @@ SetFileShortNameA(
return FALSE;
}
RtlInitAnsiString(&ShortNameA, (LPSTR)lpShortName);
if(bIsFileApiAnsi)
Status = RtlAnsiStringToUnicodeString(&ShortName, &ShortNameA, TRUE);
else
Status = RtlOemStringToUnicodeString(&ShortName, &ShortNameA, TRUE);
if(!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
return FALSE;
}
Ret = SetFileShortNameW(hFile, ShortName.Buffer);
RtlFreeUnicodeString(&ShortName);
return Ret;
if (!(ShortNameW = FilenameA2W(lpShortName, FALSE)))
return FALSE;
return SetFileShortNameW(hFile, ShortNameW);
}

View file

@ -200,9 +200,7 @@ CreateHardLinkA(LPCSTR lpFileName,
LPCSTR lpExistingFileName,
LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{
ANSI_STRING FileNameA, ExistingFileNameA;
UNICODE_STRING FileName, ExistingFileName;
NTSTATUS Status;
PWCHAR FileNameW, ExistingFileNameW;
BOOL Ret;
if(!lpFileName || !lpExistingFileName)
@ -211,34 +209,15 @@ CreateHardLinkA(LPCSTR lpFileName,
return FALSE;
}
RtlInitAnsiString(&FileNameA, (LPSTR)lpFileName);
RtlInitAnsiString(&ExistingFileNameA, (LPSTR)lpExistingFileName);
if(bIsFileApiAnsi)
Status = RtlAnsiStringToUnicodeString(&FileName, &FileNameA, TRUE);
else
Status = RtlOemStringToUnicodeString(&FileName, &FileNameA, TRUE);
if(!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
return FALSE;
}
if(bIsFileApiAnsi)
Status = RtlAnsiStringToUnicodeString(&ExistingFileName, &ExistingFileNameA, TRUE);
else
Status = RtlOemStringToUnicodeString(&ExistingFileName, &ExistingFileNameA, TRUE);
if(!NT_SUCCESS(Status))
{
RtlFreeUnicodeString(&FileName);
SetLastErrorByStatus(Status);
if (!(ExistingFileNameW = FilenameA2W(lpExistingFileName, TRUE)))
return FALSE;
}
Ret = CreateHardLinkW(FileNameW , ExistingFileNameW , lpSecurityAttributes);
Ret = CreateHardLinkW(FileName.Buffer, ExistingFileName.Buffer, lpSecurityAttributes);
RtlFreeUnicodeString(&FileName);
RtlFreeUnicodeString(&ExistingFileName);
RtlFreeHeap(RtlGetProcessHeap(), 0, ExistingFileNameW);
return Ret;
}

View file

@ -188,43 +188,19 @@ GetDiskFreeSpaceA (
LPDWORD lpTotalNumberOfClusters
)
{
UNICODE_STRING RootPathNameU;
ANSI_STRING RootPathName;
BOOL Result;
PWCHAR RootPathNameW=NULL;
RtlInitAnsiString (&RootPathName,
(LPSTR)lpRootPathName);
RtlInitUnicodeString (&RootPathNameU,
NULL);
if (lpRootPathName)
{
/* convert ansi (or oem) string to unicode */
if (bIsFileApiAnsi)
RtlAnsiStringToUnicodeString (&RootPathNameU,
&RootPathName,
TRUE);
else
RtlOemStringToUnicodeString (&RootPathNameU,
&RootPathName,
TRUE);
}
Result = GetDiskFreeSpaceW (RootPathNameU.Buffer,
if (lpRootPathName)
{
if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
return FALSE;
}
return GetDiskFreeSpaceW (RootPathNameW,
lpSectorsPerCluster,
lpBytesPerSector,
lpNumberOfFreeClusters,
lpTotalNumberOfClusters);
if (lpRootPathName)
{
RtlFreeHeap (RtlGetProcessHeap (),
0,
RootPathNameU.Buffer);
}
return Result;
}
@ -290,48 +266,24 @@ GetDiskFreeSpaceW(
*/
BOOL STDCALL
GetDiskFreeSpaceExA (
LPCSTR lpDirectoryName,
LPCSTR lpDirectoryName OPTIONAL,
PULARGE_INTEGER lpFreeBytesAvailableToCaller,
PULARGE_INTEGER lpTotalNumberOfBytes,
PULARGE_INTEGER lpTotalNumberOfFreeBytes
)
{
UNICODE_STRING DirectoryNameU;
ANSI_STRING DirectoryName;
BOOL Result;
RtlInitAnsiString (&DirectoryName,
(LPSTR)lpDirectoryName);
RtlInitUnicodeString (&DirectoryNameU,
NULL);
PWCHAR DirectoryNameW=NULL;
if (lpDirectoryName)
{
/* convert ansi (or oem) string to unicode */
if (bIsFileApiAnsi)
RtlAnsiStringToUnicodeString (&DirectoryNameU,
&DirectoryName,
TRUE);
else
RtlOemStringToUnicodeString (&DirectoryNameU,
&DirectoryName,
TRUE);
if (!(DirectoryNameW = FilenameA2W(lpDirectoryName, FALSE)))
return FALSE;
}
Result = GetDiskFreeSpaceExW (DirectoryNameU.Buffer,
return GetDiskFreeSpaceExW (DirectoryNameW ,
lpFreeBytesAvailableToCaller,
lpTotalNumberOfBytes,
lpTotalNumberOfFreeBytes);
if (lpDirectoryName)
{
RtlFreeHeap (RtlGetProcessHeap (),
0,
DirectoryNameU.Buffer);
}
return Result;
}
@ -340,7 +292,7 @@ GetDiskFreeSpaceExA (
*/
BOOL STDCALL
GetDiskFreeSpaceExW(
LPCWSTR lpDirectoryName,
LPCWSTR lpDirectoryName OPTIONAL,
PULARGE_INTEGER lpFreeBytesAvailableToCaller,
PULARGE_INTEGER lpTotalNumberOfBytes,
PULARGE_INTEGER lpTotalNumberOfFreeBytes
@ -353,6 +305,10 @@ GetDiskFreeSpaceExW(
HANDLE hFile;
NTSTATUS errCode;
/*
FIXME: this is obviously wrong for UNC paths, symbolic directories etc.
-Gunnar
*/
if (lpDirectoryName)
{
wcsncpy (RootPathName, lpDirectoryName, 3);
@ -408,30 +364,12 @@ GetDiskFreeSpaceExW(
UINT STDCALL
GetDriveTypeA(LPCSTR lpRootPathName)
{
UNICODE_STRING RootPathNameU;
ANSI_STRING RootPathName;
UINT Result;
PWCHAR RootPathNameW;
if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
return DRIVE_UNKNOWN;
RtlInitAnsiString (&RootPathName,
(LPSTR)lpRootPathName);
/* convert ansi (or oem) string to unicode */
if (bIsFileApiAnsi)
RtlAnsiStringToUnicodeString (&RootPathNameU,
&RootPathName,
TRUE);
else
RtlOemStringToUnicodeString (&RootPathNameU,
&RootPathName,
TRUE);
Result = GetDriveTypeW (RootPathNameU.Buffer);
RtlFreeHeap (RtlGetProcessHeap (),
0,
RootPathNameU.Buffer);
return Result;
return GetDriveTypeW(RootPathNameW);
}
@ -505,27 +443,16 @@ GetVolumeInformationA(
DWORD nFileSystemNameSize
)
{
UNICODE_STRING RootPathNameU;
UNICODE_STRING FileSystemNameU;
UNICODE_STRING VolumeNameU;
ANSI_STRING RootPathName;
ANSI_STRING VolumeName;
ANSI_STRING FileSystemName;
PWCHAR RootPathNameW;
BOOL Result;
RtlInitAnsiString (&RootPathName,
(LPSTR)lpRootPathName);
/* convert ansi (or oem) string to unicode */
if (bIsFileApiAnsi)
RtlAnsiStringToUnicodeString (&RootPathNameU,
&RootPathName,
TRUE);
else
RtlOemStringToUnicodeString (&RootPathNameU,
&RootPathName,
TRUE);
if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
return FALSE;
if (lpVolumeNameBuffer)
{
VolumeNameU.Length = 0;
@ -544,7 +471,7 @@ GetVolumeInformationA(
FileSystemNameU.MaximumLength);
}
Result = GetVolumeInformationW (RootPathNameU.Buffer,
Result = GetVolumeInformationW (RootPathNameW,
lpVolumeNameBuffer ? VolumeNameU.Buffer : NULL,
nVolumeNameSize,
lpVolumeSerialNumber,
@ -604,9 +531,6 @@ GetVolumeInformationA(
}
}
RtlFreeHeap (RtlGetProcessHeap (),
0,
RootPathNameU.Buffer);
if (lpVolumeNameBuffer)
{
RtlFreeHeap (RtlGetProcessHeap (),
@ -750,49 +674,31 @@ BOOL
STDCALL
SetVolumeLabelA (
LPCSTR lpRootPathName,
LPCSTR lpVolumeName
LPCSTR lpVolumeName /* NULL if deleting label */
)
{
UNICODE_STRING RootPathNameU;
ANSI_STRING RootPathName;
UNICODE_STRING VolumeNameU;
ANSI_STRING VolumeName;
PWCHAR RootPathNameW;
PWCHAR VolumeNameW = NULL;
BOOL Result;
RtlInitAnsiString (&RootPathName,
(LPSTR)lpRootPathName);
RtlInitAnsiString (&VolumeName,
(LPSTR)lpVolumeName);
if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
return FALSE;
/* convert ansi (or oem) strings to unicode */
if (bIsFileApiAnsi)
{
RtlAnsiStringToUnicodeString (&RootPathNameU,
&RootPathName,
TRUE);
RtlAnsiStringToUnicodeString (&VolumeNameU,
&VolumeName,
TRUE);
}
else
{
RtlOemStringToUnicodeString (&RootPathNameU,
&RootPathName,
TRUE);
RtlOemStringToUnicodeString (&VolumeNameU,
&VolumeName,
TRUE);
}
if (lpVolumeName)
{
if (!(VolumeNameW = FilenameA2W(lpVolumeName, TRUE)))
return FALSE;
}
Result = SetVolumeLabelW (RootPathNameW,
VolumeNameW);
Result = SetVolumeLabelW (RootPathNameU.Buffer,
VolumeNameU.Buffer);
RtlFreeHeap (RtlGetProcessHeap (),
0,
RootPathNameU.Buffer);
RtlFreeHeap (RtlGetProcessHeap (),
0,
VolumeNameU.Buffer);
if (VolumeNameW)
{
RtlFreeHeap (RtlGetProcessHeap (),
0,
VolumeNameW );
}
return Result;
}
@ -802,8 +708,10 @@ SetVolumeLabelA (
* @implemented
*/
BOOL STDCALL
SetVolumeLabelW(LPCWSTR lpRootPathName,
LPCWSTR lpVolumeName)
SetVolumeLabelW(
LPCWSTR lpRootPathName,
LPCWSTR lpVolumeName /* NULL if deleting label */
)
{
PFILE_FS_LABEL_INFORMATION LabelInfo;
IO_STATUS_BLOCK IoStatusBlock;

View file

@ -60,5 +60,16 @@ HANDLE STDCALL OpenConsoleW (LPWSTR wsName,
PTEB GetTeb(VOID);
PWCHAR FilenameA2W(LPCSTR NameA, BOOL alloc);
PUNICODE_STRING FilenameA2U(LPCSTR NameA, BOOL alloc);
DWORD FilenameW2A_FitOrFail(LPSTR DestA, INT destLen, LPCWSTR SourceW, INT sourceLen);
DWORD FilenameU2A_FitOrFail(LPSTR DestA, INT destLen, PUNICODE_STRING SourceU);
#endif /* ndef _KERNEL32_INCLUDE_KERNEL32_H */

View file

@ -82,7 +82,8 @@ DllMain(HANDLE hDll,
LPVOID lpReserved)
{
NTSTATUS Status;
PTEB Teb = NtCurrentTeb();
(void)lpReserved;
DPRINT("DllMain(hInst %lx, dwReason %lu)\n",
@ -147,8 +148,13 @@ DllMain(HANDLE hDll,
RtlInitializeCriticalSection(&ConsoleLock);
SetConsoleCtrlHandler(DefaultConsoleCtrlHandler, TRUE);
/* Insert more dll attach stuff here! */
Teb->StaticUnicodeString.Length = 0;
Teb->StaticUnicodeString.MaximumLength = sizeof(Teb->StaticUnicodeBuffer);
Teb->StaticUnicodeString.Buffer = Teb->StaticUnicodeBuffer;
/* Insert more dll attach stuff here! */
DllInitialized = TRUE;
break;
@ -172,6 +178,14 @@ DllMain(HANDLE hDll,
}
break;
case DLL_THREAD_ATTACH:
Teb->StaticUnicodeString.Length = 0;
Teb->StaticUnicodeString.MaximumLength = sizeof(Teb->StaticUnicodeBuffer);
Teb->StaticUnicodeString.Buffer = Teb->StaticUnicodeBuffer;
break;
default:
break;
}

View file

@ -8,6 +8,7 @@
*/
#include <k32.h>
#include <ddk/ldrfuncs.h>
#define NDEBUG
#include "../include/debug.h"
@ -312,39 +313,172 @@ EnumResourceLanguagesA (
}
/*
* @unimplemented
*/
BOOL
STDCALL
EnumResourceNamesW (
HINSTANCE hModule,
LPCWSTR lpType,
ENUMRESNAMEPROCW lpEnumFunc,
LONG lParam
)
/* retrieve the resource name to pass to the ntdll functions */
static NTSTATUS get_res_nameA( LPCSTR name, UNICODE_STRING *str )
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
if (!HIWORD(name))
{
str->Buffer = (LPWSTR)name;
return STATUS_SUCCESS;
}
if (name[0] == '#')
{
ULONG value;
if (RtlCharToInteger( name + 1, 10, &value ) != STATUS_SUCCESS || HIWORD(value))
return STATUS_INVALID_PARAMETER;
str->Buffer = (LPWSTR)value;
return STATUS_SUCCESS;
}
RtlCreateUnicodeStringFromAsciiz( str, name );
RtlUpcaseUnicodeString( str, str, FALSE );
return STATUS_SUCCESS;
}
/* retrieve the resource name to pass to the ntdll functions */
static NTSTATUS get_res_nameW( LPCWSTR name, UNICODE_STRING *str )
{
if (!HIWORD(name))
{
str->Buffer = (LPWSTR)name;
return STATUS_SUCCESS;
}
if (name[0] == '#')
{
ULONG value;
RtlInitUnicodeString( str, name + 1 );
if (RtlUnicodeStringToInteger( str, 10, &value ) != STATUS_SUCCESS || HIWORD(value))
return STATUS_INVALID_PARAMETER;
str->Buffer = (LPWSTR)value;
return STATUS_SUCCESS;
}
RtlCreateUnicodeString( str, name );
RtlUpcaseUnicodeString( str, str, FALSE );
return STATUS_SUCCESS;
}
/**********************************************************************
* EnumResourceNamesA (KERNEL32.@)
*/
BOOL STDCALL EnumResourceNamesA( HMODULE hmod, LPCSTR type, ENUMRESNAMEPROCA lpfun, LONG_PTR lparam )
{
int i;
BOOL ret = FALSE;
DWORD len = 0, newlen;
LPSTR name = NULL;
NTSTATUS status;
UNICODE_STRING typeW;
LDR_RESOURCE_INFO info;
PIMAGE_RESOURCE_DIRECTORY basedir, resdir;
const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
const IMAGE_RESOURCE_DIR_STRING_U *str;
DPRINT( "%p %s %p %lx\n", hmod, type, lpfun, lparam );
if (!hmod) hmod = GetModuleHandleA( NULL );
typeW.Buffer = NULL;
if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
goto done;
if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS)
goto done;
info.Type = (ULONG)typeW.Buffer;
if ((status = LdrFindResourceDirectory_U( hmod, &info, 1, &resdir )) != STATUS_SUCCESS)
goto done;
et = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1);
for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
{
if (et[i].NameIsString)
{
str = (IMAGE_RESOURCE_DIR_STRING_U *) ((LPBYTE) basedir + et[i].NameOffset);
newlen = WideCharToMultiByte(CP_ACP, 0, str->NameString, str->Length, NULL, 0, NULL, NULL);
if (newlen + 1 > len)
{
len = newlen + 1;
HeapFree( GetProcessHeap(), 0, name );
if (!(name = HeapAlloc(GetProcessHeap(), 0, len + 1 )))
{
ret = FALSE;
break;
}
}
WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, name, len, NULL, NULL );
name[newlen] = 0;
ret = lpfun(hmod,type,name,lparam);
}
else
{
ret = lpfun( hmod, type, (LPSTR)(int)et[i].Id, lparam );
}
if (!ret) break;
}
done:
HeapFree( GetProcessHeap(), 0, name );
if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
return ret;
}
/*
* @unimplemented
/**********************************************************************
* EnumResourceNamesW (KERNEL32.@)
*/
BOOL
STDCALL
EnumResourceNamesA (
HINSTANCE hModule,
LPCSTR lpType,
ENUMRESNAMEPROCA lpEnumFunc,
LONG lParam
)
BOOL STDCALL EnumResourceNamesW( HMODULE hmod, LPCWSTR type, ENUMRESNAMEPROCW lpfun, LONG_PTR lparam )
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
int i, len = 0;
BOOL ret = FALSE;
LPWSTR name = NULL;
NTSTATUS status;
UNICODE_STRING typeW;
LDR_RESOURCE_INFO info;
PIMAGE_RESOURCE_DIRECTORY basedir, resdir;
const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
const IMAGE_RESOURCE_DIR_STRING_U *str;
DPRINT( "%p %s %p %lx\n", hmod, type, lpfun, lparam );
if (!hmod) hmod = GetModuleHandleW( NULL );
typeW.Buffer = NULL;
if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
goto done;
if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS)
goto done;
info.Type = (ULONG)typeW.Buffer;
if ((status = LdrFindResourceDirectory_U( hmod, &info, 1, &resdir )) != STATUS_SUCCESS)
goto done;
et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
{
if (et[i].NameIsString)
{
str = (IMAGE_RESOURCE_DIR_STRING_U *) ((LPBYTE) basedir + et[i].NameOffset);
if (str->Length + 1 > len)
{
len = str->Length + 1;
HeapFree( GetProcessHeap(), 0, name );
if (!(name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
{
ret = FALSE;
break;
}
}
memcpy(name, str->NameString, str->Length * sizeof (WCHAR));
name[str->Length] = 0;
ret = lpfun(hmod,type,name,lparam);
}
else
{
ret = lpfun( hmod, type, (LPWSTR)(int)et[i].Id, lparam );
}
if (!ret) break;
}
done:
HeapFree( GetProcessHeap(), 0, name );
if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
return ret;
}
/*
* @unimplemented

View file

@ -788,25 +788,8 @@ QueueUserWorkItem(
return 0;
}
/*
* @unimplemented
*/
BOOL
STDCALL
ReadDirectoryChangesW(
HANDLE hDirectory,
LPVOID lpBuffer,
DWORD nBufferLength,
BOOL bWatchSubtree,
DWORD dwNotifyFilter,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped,
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
{
STUB;
return 0;
}
/*
* @unimplemented
@ -1156,20 +1139,7 @@ GetFirmwareEnvironmentVariableW(
return 0;
}
/*
* @unimplemented
*/
DWORD
STDCALL
GetLongPathNameW(
LPCWSTR lpszShortPath,
LPWSTR lpszLongPath,
DWORD cchBuffer
)
{
STUB;
return 0;
}
/*
* @unimplemented
@ -1443,20 +1413,7 @@ GetFirmwareEnvironmentVariableA(
return 0;
}
/*
* @unimplemented
*/
DWORD
STDCALL
GetLongPathNameA(
LPCSTR lpszShortPath,
LPSTR lpszLongPath,
DWORD cchBuffer
)
{
STUB;
return 0;
}
/*
* @unimplemented

View file

@ -320,9 +320,9 @@ LdrAccessResource(IN PVOID BaseAddress,
*/
NTSTATUS STDCALL
LdrFindResourceDirectory_U(IN PVOID BaseAddress,
WCHAR** name,
DWORD level,
OUT PVOID* addr)
IN PLDR_RESOURCE_INFO info,
IN ULONG level,
OUT PIMAGE_RESOURCE_DIRECTORY* addr)
{
PIMAGE_RESOURCE_DIRECTORY ResDir;
PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
@ -330,6 +330,7 @@ LdrFindResourceDirectory_U(IN PVOID BaseAddress,
ULONG i;
NTSTATUS Status = STATUS_SUCCESS;
WCHAR* ws;
PWCHAR* name = (PWCHAR*) info;
/* Get the pointer to the resource directory */
ResDir = (PIMAGE_RESOURCE_DIRECTORY)

View file

@ -241,59 +241,33 @@ RtlGetCurrentDirectory_U(ULONG MaximumLength,
* @implemented
*/
NTSTATUS STDCALL
RtlSetCurrentDirectory_U(PUNICODE_STRING name)
RtlSetCurrentDirectory_U(PUNICODE_STRING dir)
{
UNICODE_STRING full;
UNICODE_STRING envvar;
FILE_FS_DEVICE_INFORMATION device_info;
OBJECT_ATTRIBUTES Attr;
IO_STATUS_BLOCK iosb;
PCURDIR cd;
NTSTATUS Status;
ULONG size;
HANDLE handle = NULL;
PWSTR wcs;
PWSTR buf = 0;
PFILE_NAME_INFORMATION filenameinfo;
ULONG backslashcount = 0;
ULONG Index;
WCHAR var[4];
PWSTR ptr;
DPRINT ("RtlSetCurrentDirectory %wZ\n", name);
DPRINT("RtlSetCurrentDirectory %wZ\n", dir);
RtlAcquirePebLock ();
cd = (PCURDIR)&NtCurrentPeb ()->ProcessParameters->CurrentDirectoryName;
size = cd->DosPath.MaximumLength;
buf = RtlAllocateHeap (RtlGetProcessHeap(),
0,
size);
if (buf == NULL)
{
RtlReleasePebLock ();
return STATUS_NO_MEMORY;
}
if (!RtlDosPathNameToNtPathName_U (dir->Buffer, &full, 0, 0))
{
RtlReleasePebLock ();
return STATUS_OBJECT_NAME_INVALID;
}
size = RtlGetFullPathName_U (name->Buffer, size, buf, 0);
if (!size)
{
RtlFreeHeap (RtlGetProcessHeap (),
0,
buf);
RtlReleasePebLock ();
return STATUS_OBJECT_NAME_INVALID;
}
if (!RtlDosPathNameToNtPathName_U (buf, &full, 0, 0))
{
RtlFreeHeap (RtlGetProcessHeap (),
0,
buf);
RtlFreeHeap (RtlGetProcessHeap (),
0,
full.Buffer);
RtlReleasePebLock ();
return STATUS_OBJECT_NAME_INVALID;
}
DPRINT("RtlSetCurrentDirectory: full %wZ\n",&full);
InitializeObjectAttributes (&Attr,
&full,
@ -307,114 +281,124 @@ RtlSetCurrentDirectory_U(PUNICODE_STRING name)
&iosb,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(Status))
{
RtlFreeHeap (RtlGetProcessHeap (),
0,
buf);
RtlFreeHeap (RtlGetProcessHeap (),
0,
full.Buffer);
RtlReleasePebLock ();
return Status;
}
{
RtlFreeUnicodeString( &full);
RtlReleasePebLock ();
return Status;
}
/* don't keep the directory handle open on removable media */
if (!NtQueryVolumeInformationFile( handle, &iosb, &device_info,
sizeof(device_info), FileFsDeviceInformation ) &&
(device_info.Characteristics & FILE_REMOVABLE_MEDIA))
{
DPRINT1("don't keep the directory handle open on removable media\n");
NtClose( handle );
handle = 0;
}
/* What the heck is this all about??? It looks like its getting the long path,
* and if does, ITS WRONG! If current directory is set with a short path,
* GetCurrentDir should return a short path.
* If anyone agrees with me, remove this stuff.
* -Gunnar
*/
#if 0
filenameinfo = RtlAllocateHeap(RtlGetProcessHeap(),
0,
MAX_PATH*sizeof(WCHAR)+sizeof(ULONG));
0,
MAX_PATH*sizeof(WCHAR)+sizeof(ULONG));
Status = NtQueryInformationFile(handle,
&iosb,
filenameinfo,
MAX_PATH*sizeof(WCHAR)+sizeof(ULONG),
FileNameInformation);
&iosb,
filenameinfo,
MAX_PATH*sizeof(WCHAR)+sizeof(ULONG),
FileNameInformation);
if (!NT_SUCCESS(Status))
{
RtlFreeHeap(RtlGetProcessHeap(),
0,
filenameinfo);
RtlFreeHeap(RtlGetProcessHeap(),
0,
buf);
RtlFreeHeap(RtlGetProcessHeap(),
0,
full.Buffer);
RtlReleasePebLock();
return(Status);
RtlFreeHeap(RtlGetProcessHeap(),
0,
filenameinfo);
RtlFreeHeap(RtlGetProcessHeap(),
0,
buf);
RtlFreeHeap(RtlGetProcessHeap(),
0,
full.Buffer);
RtlReleasePebLock();
return(Status);
}
/* If it's just "\", we need special handling */
if (filenameinfo->FileNameLength > sizeof(WCHAR))
{
wcs = buf + size / sizeof(WCHAR) - 1;
if (*wcs == L'\\')
{
*(wcs) = 0;
wcs--;
size -= sizeof(WCHAR);
}
for (Index = 0;
Index < filenameinfo->FileNameLength / sizeof(WCHAR);
Index++)
{
if (filenameinfo->FileName[Index] == '\\') backslashcount++;
}
DPRINT("%d \n",backslashcount);
for (;backslashcount;wcs--)
{
if (*wcs=='\\') backslashcount--;
}
wcs++;
RtlCopyMemory(wcs, filenameinfo->FileName, filenameinfo->FileNameLength);
wcs[filenameinfo->FileNameLength / sizeof(WCHAR)] = 0;
size = (wcs - buf) * sizeof(WCHAR) + filenameinfo->FileNameLength;
}
RtlFreeHeap (RtlGetProcessHeap (),
0,
filenameinfo);
/* append backslash if missing */
wcs = buf + size / sizeof(WCHAR) - 1;
if (*wcs != L'\\')
if (*wcs == L'\\')
{
*(++wcs) = L'\\';
*(++wcs) = 0;
size += sizeof(WCHAR);
*(wcs) = 0;
wcs--;
size -= sizeof(WCHAR);
}
memmove(cd->DosPath.Buffer,
buf,
size + sizeof(WCHAR));
cd->DosPath.Length = size;
for (Index = 0;
Index < filenameinfo->FileNameLength / sizeof(WCHAR);
Index++)
{
if (filenameinfo->FileName[Index] == '\\') backslashcount++;
}
DPRINT("%d \n",backslashcount);
for (;backslashcount;wcs--)
{
if (*wcs=='\\') backslashcount--;
}
wcs++;
RtlCopyMemory(wcs, filenameinfo->FileName, filenameinfo->FileNameLength);
wcs[filenameinfo->FileNameLength / sizeof(WCHAR)] = 0;
size = (wcs - buf) * sizeof(WCHAR) + filenameinfo->FileNameLength;
}
#endif
if (cd->Handle)
NtClose(cd->Handle);
NtClose(cd->Handle);
cd->Handle = handle;
if (cd->DosPath.Buffer[1]==':')
{
envvar.Length = 2 * swprintf (var, L"=%c:", cd->DosPath.Buffer[0]);
envvar.MaximumLength = 8;
envvar.Buffer = var;
/* append trailing \ if missing */
size = full.Length / sizeof(WCHAR);
ptr = full.Buffer;
ptr += 4; /* skip \??\ prefix */
size -= 4;
RtlSetEnvironmentVariable(NULL,
&envvar,
&cd->DosPath);
/* This is ok because RtlDosPathNameToNtPathName_U returns a nullterminated string.
* So the nullterm is replaced with \
* -Gunnar
*/
if (size && ptr[size - 1] != '\\') ptr[size++] = '\\';
memcpy( cd->DosPath.Buffer, ptr, size * sizeof(WCHAR));
cd->DosPath.Buffer[size] = 0;
cd->DosPath.Length = size * sizeof(WCHAR);
/* FIXME: whats this all about??? Wine doesnt have this. -Gunnar */
if (cd->DosPath.Buffer[1]==':')
{
envvar.Length = 2 * swprintf (var, L"=%c:", cd->DosPath.Buffer[0]);
envvar.MaximumLength = 8;
envvar.Buffer = var;
RtlSetEnvironmentVariable(NULL,
&envvar,
&cd->DosPath);
}
RtlFreeHeap (RtlGetProcessHeap (),
0,
buf);
RtlFreeHeap (RtlGetProcessHeap (),
0,
full.Buffer);
RtlFreeUnicodeString( &full);
RtlReleasePebLock();
return STATUS_SUCCESS;