X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fdll%2Fwin32%2Fkernel32%2Ffile%2Ffile.c;h=7f0c0446441f7530367127f5bac939eb72d8af57;hp=66046621821eedaa787f39c2db2fcc3a782084b2;hb=a815fa86d2fb863d97b63219b5878ab68cb16506;hpb=cbdf28bb6ace5e3faec494c5743371d7288f191c diff --git a/reactos/dll/win32/kernel32/file/file.c b/reactos/dll/win32/kernel32/file/file.c index 66046621821..7f0c0446441 100644 --- a/reactos/dll/win32/kernel32/file/file.c +++ b/reactos/dll/win32/kernel32/file/file.c @@ -5,7 +5,7 @@ * FILE: lib/kernel32/file/file.c * PURPOSE: Directory functions * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) - * GetTempFileName is modified from WINE [ Alexandre Juiliard ] + * Pierre Schweitzer (pierre.schweitzer@reactos.org) * UPDATE HISTORY: * Created 01/11/98 */ @@ -13,9 +13,9 @@ /* INCLUDES *****************************************************************/ #include -#include - -WINE_DEFAULT_DEBUG_CHANNEL(kernel32file); +#define NDEBUG +#include +DEBUG_CHANNEL(kernel32file); /* GLOBALS ******************************************************************/ @@ -72,6 +72,9 @@ FilenameU2A_FitOrFail( { DWORD ret; + /* destLen should never exceed MAX_PATH */ + if (destLen > MAX_PATH) destLen = MAX_PATH; + ret = bIsFileApiAnsi? RtlUnicodeStringToAnsiSize(SourceU) : RtlUnicodeStringToOemSize(SourceU); /* ret incl. nullchar */ @@ -403,26 +406,26 @@ OpenFile(LPCSTR lpFileName, * @implemented */ BOOL WINAPI -FlushFileBuffers(HANDLE hFile) +FlushFileBuffers(IN HANDLE hFile) { - NTSTATUS errCode; - IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; - hFile = TranslateStdHandle(hFile); + hFile = TranslateStdHandle(hFile); - if (IsConsoleHandle(hFile)) - { - return FALSE; - } + if (IsConsoleHandle(hFile)) + { + return FlushConsoleInputBuffer(hFile); + } - errCode = NtFlushBuffersFile(hFile, - &IoStatusBlock); - if (!NT_SUCCESS(errCode)) - { - SetLastErrorByStatus(errCode); - return(FALSE); - } - return(TRUE); + Status = NtFlushBuffersFile(hFile, + &IoStatusBlock); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + return TRUE; } @@ -1209,83 +1212,205 @@ SetFileAttributesW(LPCWSTR lpFileName, /*********************************************************************** * 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]; - PWCHAR PathW; - WCHAR PrefixW[3+1]; - UINT ret; - - if (!(PathW = FilenameA2W(path, FALSE))) - return 0; - - if (prefix) - FilenameA2W_N(PrefixW, 3+1, prefix, -1); + UINT ID; + NTSTATUS Status; + LPWSTR lpTempFileNameW; + PUNICODE_STRING lpPathNameW; + ANSI_STRING TempFileNameStringA; + UNICODE_STRING lpPrefixStringW, TempFileNameStringW; + + /* Convert strings */ + lpPathNameW = Basep8BitStringToStaticUnicodeString(lpPathName); + if (!lpPathNameW) + { + return 0; + } - ret = GetTempFileNameW(PathW, prefix ? PrefixW : NULL, unique, BufferW); + if (!Basep8BitStringToDynamicUnicodeString(&lpPrefixStringW, lpPrefixString)) + { + return 0; + } - if (ret) - FilenameW2A_N(buffer, MAX_PATH, BufferW, -1); + lpTempFileNameW = RtlAllocateHeap(RtlGetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); + if (!lpTempFileNameW) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + RtlFreeUnicodeString(&lpPrefixStringW); + return 0; + } - return ret; -} + /* 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; + } + } -/*********************************************************************** - * GetTempFileNameW (KERNEL32.@) - */ -UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, LPWSTR buffer ) + /* 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) { - static const WCHAR formatW[] = L"%x.tmp"; - - int i; - LPWSTR p; + 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)) - 1] != L'\\') + { + PathNameString.Length += sizeof(WCHAR); + } - if ( !path || !buffer ) + /* 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_INVALID_PARAMETER ); + SetLastError(ERROR_BUFFER_OVERFLOW); return 0; } - - wcscpy( buffer, path ); - 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 + + /* If PathName and TempFileName aren't the same buffer, move PathName to TempFileName */ + if (lpPathName != lpTempFileName) { - /* get a "random" unique number and try to create the file */ - HANDLE handle; - UINT num = GetTickCount() & 0xffff; + memmove(lpTempFileName, PathNameString.Buffer, PathNameString.Length); + } - if (!num) num = 1; - unique = num; + /* PathName MUST BE a path. Check it */ + lpTempFileName[(PathNameString.Length / sizeof(WCHAR)) - 1] = UNICODE_NULL; + FileAttributes = GetFileAttributesW(lpTempFileName); + if (FileAttributes == INVALID_FILE_ATTRIBUTES) + { + /* Append a '\' if necessary */ + lpTempFileName[(PathNameString.Length / sizeof(WCHAR)) - 1] = L'\\'; + lpTempFileName[PathNameString.Length / sizeof(WCHAR)] = 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)) - 1] = 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); + 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 { - 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; + *(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; } - 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); - return unique; + 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; } @@ -1296,40 +1421,51 @@ UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, LPWSTR * @implemented */ BOOL WINAPI -GetFileTime(HANDLE hFile, - LPFILETIME lpCreationTime, - LPFILETIME lpLastAccessTime, - LPFILETIME lpLastWriteTime) +GetFileTime(IN HANDLE hFile, + OUT LPFILETIME lpCreationTime OPTIONAL, + OUT LPFILETIME lpLastAccessTime OPTIONAL, + OUT LPFILETIME lpLastWriteTime OPTIONAL) { - IO_STATUS_BLOCK IoStatusBlock; - FILE_BASIC_INFORMATION FileBasic; - NTSTATUS Status; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + FILE_BASIC_INFORMATION FileBasic; - if(IsConsoleHandle(hFile)) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } + if(IsConsoleHandle(hFile)) + { + BaseSetLastNTError(STATUS_INVALID_HANDLE); + return FALSE; + } - Status = NtQueryInformationFile(hFile, - &IoStatusBlock, - &FileBasic, - sizeof(FILE_BASIC_INFORMATION), - FileBasicInformation); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } + Status = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } - if (lpCreationTime) - memcpy(lpCreationTime, &FileBasic.CreationTime, sizeof(FILETIME)); - if (lpLastAccessTime) - memcpy(lpLastAccessTime, &FileBasic.LastAccessTime, sizeof(FILETIME)); - if (lpLastWriteTime) - memcpy(lpLastWriteTime, &FileBasic.LastWriteTime, sizeof(FILETIME)); + if (lpCreationTime) + { + lpCreationTime->dwLowDateTime = FileBasic.CreationTime.LowPart; + lpCreationTime->dwHighDateTime = FileBasic.CreationTime.HighPart; + } - return TRUE; + if (lpLastAccessTime) + { + lpLastAccessTime->dwLowDateTime = FileBasic.LastAccessTime.LowPart; + lpLastAccessTime->dwHighDateTime = FileBasic.LastAccessTime.HighPart; + } + + if (lpLastWriteTime) + { + lpLastWriteTime->dwLowDateTime = FileBasic.LastWriteTime.LowPart; + lpLastWriteTime->dwHighDateTime = FileBasic.LastWriteTime.HighPart; + } + + return TRUE; } @@ -1337,53 +1473,53 @@ GetFileTime(HANDLE hFile, * @implemented */ BOOL WINAPI -SetFileTime(HANDLE hFile, - CONST FILETIME *lpCreationTime, - CONST FILETIME *lpLastAccessTime, - CONST FILETIME *lpLastWriteTime) +SetFileTime(IN HANDLE hFile, + CONST FILETIME *lpCreationTime OPTIONAL, + CONST FILETIME *lpLastAccessTime OPTIONAL, + CONST FILETIME *lpLastWriteTime OPTIONAL) { - FILE_BASIC_INFORMATION FileBasic; - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + FILE_BASIC_INFORMATION FileBasic; - if(IsConsoleHandle(hFile)) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } + if(IsConsoleHandle(hFile)) + { + BaseSetLastNTError(STATUS_INVALID_HANDLE); + return FALSE; + } - Status = NtQueryInformationFile(hFile, - &IoStatusBlock, - &FileBasic, - sizeof(FILE_BASIC_INFORMATION), - FileBasicInformation); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } + memset(&FileBasic, 0, sizeof(FILE_BASIC_INFORMATION)); - if (lpCreationTime) - memcpy(&FileBasic.CreationTime, lpCreationTime, sizeof(FILETIME)); - if (lpLastAccessTime) - memcpy(&FileBasic.LastAccessTime, lpLastAccessTime, sizeof(FILETIME)); - if (lpLastWriteTime) - memcpy(&FileBasic.LastWriteTime, lpLastWriteTime, sizeof(FILETIME)); - - // should i initialize changetime ??? - - Status = NtSetInformationFile(hFile, - &IoStatusBlock, - &FileBasic, - sizeof(FILE_BASIC_INFORMATION), - FileBasicInformation); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } + if (lpCreationTime) + { + FileBasic.CreationTime.LowPart = lpCreationTime->dwLowDateTime; + FileBasic.CreationTime.HighPart = lpCreationTime->dwHighDateTime; + } - return TRUE; + if (lpLastAccessTime) + { + FileBasic.LastAccessTime.LowPart = lpLastAccessTime->dwLowDateTime; + FileBasic.LastAccessTime.HighPart = lpLastAccessTime->dwHighDateTime; + } + + if (lpLastWriteTime) + { + FileBasic.LastWriteTime.LowPart = lpLastWriteTime->dwLowDateTime; + FileBasic.LastWriteTime.HighPart = lpLastWriteTime->dwHighDateTime; + } + + Status = NtSetInformationFile(hFile, + &IoStatusBlock, + &FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; } @@ -1906,7 +2042,8 @@ ReplaceFileW( ) { HANDLE hReplaced = NULL, hReplacement = NULL; - UNICODE_STRING NtReplacedName, NtReplacementName; + UNICODE_STRING NtReplacedName = { 0, 0, NULL }; + UNICODE_STRING NtReplacementName = { 0, 0, NULL }; DWORD Error = ERROR_SUCCESS; NTSTATUS Status; BOOL Ret = FALSE; @@ -2029,8 +2166,10 @@ Cleanup: if (hReplacement) NtClose(hReplacement); if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); - RtlFreeUnicodeString(&NtReplacementName); - RtlFreeUnicodeString(&NtReplacedName); + if (NtReplacementName.Buffer) + RtlFreeHeap(GetProcessHeap(), 0, NtReplacementName.Buffer); + if (NtReplacedName.Buffer) + RtlFreeHeap(GetProcessHeap(), 0, NtReplacedName.Buffer); /* If there was an error, set the error code */ if(!Ret)