mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 17:05:46 +00:00
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:
parent
e035ce116b
commit
cb05e516a2
13 changed files with 1039 additions and 1117 deletions
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue