mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 22:52:54 +00:00
[KERNEL32]
- Get rid of Wine's implementation of GetTempFileNameA/W and reimplement them in the Windows 2003 way. This fixes bug #5481 svn path=/trunk/; revision=50839
This commit is contained in:
parent
6b74e9a992
commit
bd3cef98c1
2 changed files with 194 additions and 69 deletions
|
@ -5,7 +5,7 @@
|
||||||
* FILE: lib/kernel32/file/file.c
|
* FILE: lib/kernel32/file/file.c
|
||||||
* PURPOSE: Directory functions
|
* PURPOSE: Directory functions
|
||||||
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
|
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
|
||||||
* GetTempFileName is modified from WINE [ Alexandre Juiliard ]
|
* Pierre Schweitzer (pierre.schweitzer@reactos.org)
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
* Created 01/11/98
|
* Created 01/11/98
|
||||||
*/
|
*/
|
||||||
|
@ -1212,83 +1212,205 @@ SetFileAttributesW(LPCWSTR lpFileName,
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* GetTempFileNameA (KERNEL32.@)
|
* GetTempFileNameA (KERNEL32.@)
|
||||||
*/
|
*/
|
||||||
UINT WINAPI GetTempFileNameA( LPCSTR path, LPCSTR prefix, UINT unique, LPSTR buffer)
|
UINT WINAPI
|
||||||
|
GetTempFileNameA(IN LPCSTR lpPathName,
|
||||||
|
IN LPCSTR lpPrefixString,
|
||||||
|
IN UINT uUnique,
|
||||||
|
OUT LPSTR lpTempFileName)
|
||||||
{
|
{
|
||||||
WCHAR BufferW[MAX_PATH];
|
UINT ID;
|
||||||
PWCHAR PathW;
|
NTSTATUS Status;
|
||||||
WCHAR PrefixW[3+1];
|
LPWSTR lpTempFileNameW;
|
||||||
UINT ret;
|
PUNICODE_STRING lpPathNameW;
|
||||||
|
ANSI_STRING TempFileNameStringA;
|
||||||
|
UNICODE_STRING lpPrefixStringW, TempFileNameStringW;
|
||||||
|
|
||||||
if (!(PathW = FilenameA2W(path, FALSE)))
|
/* Convert strings */
|
||||||
return 0;
|
lpPathNameW = Basep8BitStringToStaticUnicodeString(lpPathName);
|
||||||
|
if (!lpPathNameW)
|
||||||
if (prefix)
|
|
||||||
FilenameA2W_N(PrefixW, 3+1, prefix, -1);
|
|
||||||
|
|
||||||
ret = GetTempFileNameW(PathW, prefix ? PrefixW : NULL, unique, BufferW);
|
|
||||||
|
|
||||||
if (ret)
|
|
||||||
FilenameW2A_N(buffer, MAX_PATH, BufferW, -1);
|
|
||||||
|
|
||||||
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 || !buffer )
|
|
||||||
{
|
{
|
||||||
SetLastError( ERROR_INVALID_PARAMETER );
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
wcscpy( buffer, path );
|
if (!Basep8BitStringToDynamicUnicodeString(&lpPrefixStringW, lpPrefixString))
|
||||||
p = buffer + wcslen(buffer);
|
|
||||||
|
|
||||||
/* add a \, if there isn't one */
|
|
||||||
if ((p == buffer) || (p[-1] != '\\')) *p++ = '\\';
|
|
||||||
|
|
||||||
if ( prefix )
|
|
||||||
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 */
|
return 0;
|
||||||
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 */
|
|
||||||
TRACE("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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("returning %S\n", buffer);
|
lpTempFileNameW = RtlAllocateHeap(RtlGetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
|
||||||
return unique;
|
if (!lpTempFileNameW)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
RtlFreeUnicodeString(&lpPrefixStringW);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call Unicode */
|
||||||
|
ID = GetTempFileNameW(lpPathNameW->Buffer, lpPrefixStringW.Buffer, uUnique, lpTempFileNameW);
|
||||||
|
if (ID)
|
||||||
|
{
|
||||||
|
RtlInitUnicodeString(&TempFileNameStringW, lpTempFileNameW);
|
||||||
|
TempFileNameStringA.Buffer = lpTempFileName;
|
||||||
|
TempFileNameStringA.MaximumLength = MAX_PATH;
|
||||||
|
|
||||||
|
Status = BasepUnicodeStringTo8BitString(&TempFileNameStringA, &TempFileNameStringW, FALSE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
BaseSetLastNTError(Status);
|
||||||
|
ID = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cleanup */
|
||||||
|
RtlFreeUnicodeString(&lpPrefixStringW);
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, lpTempFileNameW);
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* GetTempFileNameW (KERNEL32.@)
|
||||||
|
*/
|
||||||
|
UINT WINAPI
|
||||||
|
GetTempFileNameW(IN LPCWSTR lpPathName,
|
||||||
|
IN LPCWSTR lpPrefixString,
|
||||||
|
IN UINT uUnique,
|
||||||
|
OUT LPWSTR lpTempFileName)
|
||||||
|
{
|
||||||
|
CHAR * Let;
|
||||||
|
HANDLE TempFile;
|
||||||
|
UINT ID, Num = 0;
|
||||||
|
CHAR IDString[5];
|
||||||
|
WCHAR * TempFileName;
|
||||||
|
CSR_API_MESSAGE ApiMessage;
|
||||||
|
DWORD FileAttributes, LastError;
|
||||||
|
UNICODE_STRING PathNameString, PrefixString;
|
||||||
|
static const WCHAR Ext[] = { L'.', 't', 'm', 'p', UNICODE_NULL };
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&PathNameString, lpPathName);
|
||||||
|
if (PathNameString.Length == 0 || PathNameString.Buffer[PathNameString.Length - sizeof(WCHAR)] != L'\\')
|
||||||
|
{
|
||||||
|
PathNameString.Length += sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* lpTempFileName must be able to contain: PathName, Prefix (3), number(4), .tmp(4) & \0(1)
|
||||||
|
* See: http://msdn.microsoft.com/en-us/library/aa364991%28v=vs.85%29.aspx
|
||||||
|
*/
|
||||||
|
if (PathNameString.Length > (MAX_PATH - 3 - 4 - 4 - 1) * sizeof(WCHAR))
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_BUFFER_OVERFLOW);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If PathName and TempFileName aren't the same buffer, move PathName to TempFileName */
|
||||||
|
if (lpPathName != lpTempFileName)
|
||||||
|
{
|
||||||
|
memmove(lpTempFileName, PathNameString.Buffer, PathNameString.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PathName MUST BE a path. Check it */
|
||||||
|
lpTempFileName[PathNameString.Length - sizeof(WCHAR)] = UNICODE_NULL;
|
||||||
|
FileAttributes = GetFileAttributesW(lpTempFileName);
|
||||||
|
if (FileAttributes == INVALID_FILE_ATTRIBUTES)
|
||||||
|
{
|
||||||
|
/* Append a '\' if necessary */
|
||||||
|
lpTempFileName[PathNameString.Length - sizeof(WCHAR)] = L'\\';
|
||||||
|
lpTempFileName[PathNameString.Length] = UNICODE_NULL;
|
||||||
|
FileAttributes = GetFileAttributesW(lpTempFileName);
|
||||||
|
if (FileAttributes == INVALID_FILE_ATTRIBUTES)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_DIRECTORY);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!(FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_DIRECTORY);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure not to mix path & prefix */
|
||||||
|
lpTempFileName[PathNameString.Length - sizeof(WCHAR)] = L'\\';
|
||||||
|
RtlInitUnicodeString(&PrefixString, lpPrefixString);
|
||||||
|
if (PrefixString.Length > 3 * sizeof(WCHAR))
|
||||||
|
{
|
||||||
|
PrefixString.Length = 3 * sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append prefix to path */
|
||||||
|
TempFileName = lpTempFileName + PathNameString.Length / sizeof(WCHAR) - 1;
|
||||||
|
memmove(TempFileName, PrefixString.Buffer, PrefixString.Length);
|
||||||
|
TempFileName += PrefixString.Length / sizeof(WCHAR);
|
||||||
|
|
||||||
|
/* Then, generate filename */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* If user didn't gave any ID, ask Csrss to give one */
|
||||||
|
if (!uUnique)
|
||||||
|
{
|
||||||
|
CsrClientCallServer(&ApiMessage, NULL, MAKE_CSR_API(GET_TEMP_FILE, CSR_NATIVE), sizeof(CSR_API_MESSAGE));
|
||||||
|
if (ApiMessage.Data.GetTempFile.UniqueID == 0)
|
||||||
|
{
|
||||||
|
Num++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ID = ApiMessage.Data.GetTempFile.UniqueID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ID = uUnique;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert that ID to wchar */
|
||||||
|
RtlIntegerToChar(ID, 0x10, sizeof(IDString), IDString);
|
||||||
|
Let = IDString;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*(TempFileName++) = RtlAnsiCharToUnicodeChar(&Let);
|
||||||
|
} while (*Let != 0);
|
||||||
|
|
||||||
|
/* Append extension & UNICODE_NULL */
|
||||||
|
memmove(TempFileName, Ext, sizeof(Ext) + sizeof(WCHAR));
|
||||||
|
|
||||||
|
/* If user provided its ID, just return */
|
||||||
|
if (uUnique)
|
||||||
|
{
|
||||||
|
return uUnique;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then, try to create file */
|
||||||
|
if (!RtlIsDosDeviceName_U(lpTempFileName))
|
||||||
|
{
|
||||||
|
TempFile = CreateFileW(lpTempFileName,
|
||||||
|
GENERIC_READ,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
CREATE_NEW,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
0);
|
||||||
|
if (TempFile != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
NtClose(TempFile);
|
||||||
|
DPRINT("Temp file: %S\n", lpTempFileName);
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
LastError = GetLastError();
|
||||||
|
/* There is no need to recover from those errors, they would hit next step */
|
||||||
|
if (LastError == ERROR_INVALID_PARAMETER || LastError == ERROR_CANNOT_MAKE ||
|
||||||
|
LastError == ERROR_WRITE_PROTECT || LastError == ERROR_NETWORK_ACCESS_DENIED ||
|
||||||
|
LastError == ERROR_DISK_FULL || LastError == ERROR_INVALID_NAME ||
|
||||||
|
LastError == ERROR_BAD_PATHNAME || LastError == ERROR_NO_INHERITANCE ||
|
||||||
|
LastError == ERROR_DISK_CORRUPT ||
|
||||||
|
(LastError == ERROR_ACCESS_DENIED && NtCurrentTeb()->LastStatusValue != STATUS_FILE_IS_A_DIRECTORY))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Num++;
|
||||||
|
} while (Num & 0xFFFF);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -224,3 +224,6 @@ InitCommandLines(VOID);
|
||||||
VOID
|
VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
BaseSetLastNTError(IN NTSTATUS Status);
|
BaseSetLastNTError(IN NTSTATUS Status);
|
||||||
|
|
||||||
|
/* FIXME */
|
||||||
|
WCHAR WINAPI RtlAnsiCharToUnicodeChar(LPSTR *);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue