1 /* $Id: file.c 54310 2011-11-06 04:13:21Z ion $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/file/file.c
6 * PURPOSE: Directory functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * Pierre Schweitzer (pierre.schweitzer@reactos.org)
13 /* INCLUDES *****************************************************************/
19 /* GLOBALS ******************************************************************/
21 /* FUNCTIONS ****************************************************************/
23 /***********************************************************************
24 * GetTempFileNameA (KERNEL32.@)
27 GetTempFileNameA(IN LPCSTR lpPathName
,
28 IN LPCSTR lpPrefixString
,
30 OUT LPSTR lpTempFileName
)
34 LPWSTR lpTempFileNameW
;
35 PUNICODE_STRING lpPathNameW
;
36 ANSI_STRING TempFileNameStringA
;
37 UNICODE_STRING lpPrefixStringW
, TempFileNameStringW
;
40 lpPathNameW
= Basep8BitStringToStaticUnicodeString(lpPathName
);
46 if (!Basep8BitStringToDynamicUnicodeString(&lpPrefixStringW
, lpPrefixString
))
51 lpTempFileNameW
= RtlAllocateHeap(RtlGetProcessHeap(), 0, MAX_PATH
* sizeof(WCHAR
));
54 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
55 RtlFreeUnicodeString(&lpPrefixStringW
);
60 ID
= GetTempFileNameW(lpPathNameW
->Buffer
, lpPrefixStringW
.Buffer
, uUnique
, lpTempFileNameW
);
63 RtlInitUnicodeString(&TempFileNameStringW
, lpTempFileNameW
);
64 TempFileNameStringA
.Buffer
= lpTempFileName
;
65 TempFileNameStringA
.MaximumLength
= MAX_PATH
;
67 Status
= BasepUnicodeStringTo8BitString(&TempFileNameStringA
, &TempFileNameStringW
, FALSE
);
68 if (!NT_SUCCESS(Status
))
70 BaseSetLastNTError(Status
);
76 RtlFreeUnicodeString(&lpPrefixStringW
);
77 RtlFreeHeap(RtlGetProcessHeap(), 0, lpTempFileNameW
);
81 /***********************************************************************
82 * GetTempFileNameW (KERNEL32.@)
85 GetTempFileNameW(IN LPCWSTR lpPathName
,
86 IN LPCWSTR lpPrefixString
,
88 OUT LPWSTR lpTempFileName
)
95 CSR_API_MESSAGE ApiMessage
;
96 DWORD FileAttributes
, LastError
;
97 UNICODE_STRING PathNameString
, PrefixString
;
98 static const WCHAR Ext
[] = { L
'.', 't', 'm', 'p', UNICODE_NULL
};
100 RtlInitUnicodeString(&PathNameString
, lpPathName
);
101 if (PathNameString
.Length
== 0 || PathNameString
.Buffer
[(PathNameString
.Length
/ sizeof(WCHAR
)) - 1] != L
'\\')
103 PathNameString
.Length
+= sizeof(WCHAR
);
106 /* lpTempFileName must be able to contain: PathName, Prefix (3), number(4), .tmp(4) & \0(1)
107 * See: http://msdn.microsoft.com/en-us/library/aa364991%28v=vs.85%29.aspx
109 if (PathNameString
.Length
> (MAX_PATH
- 3 - 4 - 4 - 1) * sizeof(WCHAR
))
111 SetLastError(ERROR_BUFFER_OVERFLOW
);
115 /* If PathName and TempFileName aren't the same buffer, move PathName to TempFileName */
116 if (lpPathName
!= lpTempFileName
)
118 memmove(lpTempFileName
, PathNameString
.Buffer
, PathNameString
.Length
);
121 /* PathName MUST BE a path. Check it */
122 lpTempFileName
[(PathNameString
.Length
/ sizeof(WCHAR
)) - 1] = UNICODE_NULL
;
123 FileAttributes
= GetFileAttributesW(lpTempFileName
);
124 if (FileAttributes
== INVALID_FILE_ATTRIBUTES
)
126 /* Append a '\' if necessary */
127 lpTempFileName
[(PathNameString
.Length
/ sizeof(WCHAR
)) - 1] = L
'\\';
128 lpTempFileName
[PathNameString
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
129 FileAttributes
= GetFileAttributesW(lpTempFileName
);
130 if (FileAttributes
== INVALID_FILE_ATTRIBUTES
)
132 SetLastError(ERROR_DIRECTORY
);
136 if (!(FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
138 SetLastError(ERROR_DIRECTORY
);
142 /* Make sure not to mix path & prefix */
143 lpTempFileName
[(PathNameString
.Length
/ sizeof(WCHAR
)) - 1] = L
'\\';
144 RtlInitUnicodeString(&PrefixString
, lpPrefixString
);
145 if (PrefixString
.Length
> 3 * sizeof(WCHAR
))
147 PrefixString
.Length
= 3 * sizeof(WCHAR
);
150 /* Append prefix to path */
151 TempFileName
= lpTempFileName
+ PathNameString
.Length
/ sizeof(WCHAR
);
152 memmove(TempFileName
, PrefixString
.Buffer
, PrefixString
.Length
);
153 TempFileName
+= PrefixString
.Length
/ sizeof(WCHAR
);
155 /* Then, generate filename */
158 /* If user didn't gave any ID, ask Csrss to give one */
161 CsrClientCallServer(&ApiMessage
, NULL
, MAKE_CSR_API(GET_TEMP_FILE
, CSR_NATIVE
), sizeof(CSR_API_MESSAGE
));
162 if (ApiMessage
.Data
.GetTempFile
.UniqueID
== 0)
168 ID
= ApiMessage
.Data
.GetTempFile
.UniqueID
;
175 /* Convert that ID to wchar */
176 RtlIntegerToChar(ID
, 0x10, sizeof(IDString
), IDString
);
180 *(TempFileName
++) = RtlAnsiCharToUnicodeChar(&Let
);
183 /* Append extension & UNICODE_NULL */
184 memmove(TempFileName
, Ext
, sizeof(Ext
));
186 /* If user provided its ID, just return */
192 /* Then, try to create file */
193 if (!RtlIsDosDeviceName_U(lpTempFileName
))
195 TempFile
= CreateFileW(lpTempFileName
,
200 FILE_ATTRIBUTE_NORMAL
,
202 if (TempFile
!= INVALID_HANDLE_VALUE
)
205 DPRINT("Temp file: %S\n", lpTempFileName
);
209 LastError
= GetLastError();
210 /* There is no need to recover from those errors, they would hit next step */
211 if (LastError
== ERROR_INVALID_PARAMETER
|| LastError
== ERROR_CANNOT_MAKE
||
212 LastError
== ERROR_WRITE_PROTECT
|| LastError
== ERROR_NETWORK_ACCESS_DENIED
||
213 LastError
== ERROR_DISK_FULL
|| LastError
== ERROR_INVALID_NAME
||
214 LastError
== ERROR_BAD_PATHNAME
|| LastError
== ERROR_NO_INHERITANCE
||
215 LastError
== ERROR_DISK_CORRUPT
||
216 (LastError
== ERROR_ACCESS_DENIED
&& NtCurrentTeb()->LastStatusValue
!= STATUS_FILE_IS_A_DIRECTORY
))
222 } while (Num
& 0xFFFF);
238 UNICODE_STRING ShortName
;
239 IO_STATUS_BLOCK IoStatusBlock
;
240 PFILE_NAME_INFORMATION FileNameInfo
;
242 if(IsConsoleHandle(hFile
))
244 SetLastError(ERROR_INVALID_HANDLE
);
250 SetLastError(ERROR_INVALID_PARAMETER
);
254 RtlInitUnicodeString(&ShortName
, lpShortName
);
256 NeededSize
= sizeof(FILE_NAME_INFORMATION
) + ShortName
.Length
+ sizeof(WCHAR
);
257 if(!(FileNameInfo
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, NeededSize
)))
259 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
263 FileNameInfo
->FileNameLength
= ShortName
.Length
;
264 RtlCopyMemory(FileNameInfo
->FileName
, ShortName
.Buffer
, ShortName
.Length
);
266 Status
= NtSetInformationFile(hFile
,
267 &IoStatusBlock
, //out
270 FileShortNameInformation
);
272 RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameInfo
);
273 if(!NT_SUCCESS(Status
))
275 BaseSetLastNTError(Status
);
295 if(IsConsoleHandle(hFile
))
297 SetLastError(ERROR_INVALID_HANDLE
);
303 SetLastError(ERROR_INVALID_PARAMETER
);
307 if (!(ShortNameW
= FilenameA2W(lpShortName
, FALSE
)))
310 return SetFileShortNameW(hFile
, ShortNameW
);
319 CheckNameLegalDOS8Dot3W(
321 LPSTR lpOemName OPTIONAL
,
322 DWORD OemNameSize OPTIONAL
,
323 PBOOL pbNameContainsSpaces OPTIONAL
,
328 ANSI_STRING AnsiName
;
331 (lpOemName
== NULL
&& OemNameSize
!= 0) ||
334 SetLastError(ERROR_INVALID_PARAMETER
);
338 if(lpOemName
!= NULL
)
340 AnsiName
.Buffer
= lpOemName
;
341 AnsiName
.MaximumLength
= (USHORT
)OemNameSize
* sizeof(CHAR
);
345 RtlInitUnicodeString(&Name
, lpName
);
347 *pbNameLegal
= RtlIsNameLegalDOS8Dot3(&Name
,
348 (lpOemName
? &AnsiName
: NULL
),
349 (BOOLEAN
*)pbNameContainsSpaces
);
360 CheckNameLegalDOS8Dot3A(
362 LPSTR lpOemName OPTIONAL
,
363 DWORD OemNameSize OPTIONAL
,
364 PBOOL pbNameContainsSpaces OPTIONAL
,
369 ANSI_STRING AnsiName
, AnsiInputName
;
373 (lpOemName
== NULL
&& OemNameSize
!= 0) ||
376 SetLastError(ERROR_INVALID_PARAMETER
);
380 if(lpOemName
!= NULL
)
382 AnsiName
.Buffer
= lpOemName
;
383 AnsiName
.MaximumLength
= (USHORT
)OemNameSize
* sizeof(CHAR
);
387 RtlInitAnsiString(&AnsiInputName
, (LPSTR
)lpName
);
389 Status
= RtlAnsiStringToUnicodeString(&Name
, &AnsiInputName
, TRUE
);
391 Status
= RtlOemStringToUnicodeString(&Name
, &AnsiInputName
, TRUE
);
393 if(!NT_SUCCESS(Status
))
395 BaseSetLastNTError(Status
);
399 *pbNameLegal
= RtlIsNameLegalDOS8Dot3(&Name
,
400 (lpOemName
? &AnsiName
: NULL
),
401 (BOOLEAN
*)pbNameContainsSpaces
);
403 RtlFreeUnicodeString(&Name
);