2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/file/file.c
5 * PURPOSE: Directory functions
6 * PROGRAMMERS: Ariadne (ariadne@xs4all.nl)
7 * Pierre Schweitzer (pierre.schweitzer@reactos.org)
12 /* INCLUDES *****************************************************************/
18 /* GLOBALS ******************************************************************/
20 /* FUNCTIONS ****************************************************************/
22 /***********************************************************************
23 * GetTempFileNameA (KERNEL32.@)
26 GetTempFileNameA(IN LPCSTR lpPathName
,
27 IN LPCSTR lpPrefixString
,
29 OUT LPSTR lpTempFileName
)
33 LPWSTR lpTempFileNameW
;
34 PUNICODE_STRING lpPathNameW
;
35 ANSI_STRING TempFileNameStringA
;
36 UNICODE_STRING lpPrefixStringW
, TempFileNameStringW
;
39 lpPathNameW
= Basep8BitStringToStaticUnicodeString(lpPathName
);
45 if (!Basep8BitStringToDynamicUnicodeString(&lpPrefixStringW
, lpPrefixString
))
50 lpTempFileNameW
= RtlAllocateHeap(RtlGetProcessHeap(), 0, MAX_PATH
* sizeof(WCHAR
));
53 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
54 RtlFreeUnicodeString(&lpPrefixStringW
);
59 ID
= GetTempFileNameW(lpPathNameW
->Buffer
, lpPrefixStringW
.Buffer
, uUnique
, lpTempFileNameW
);
62 RtlInitUnicodeString(&TempFileNameStringW
, lpTempFileNameW
);
63 TempFileNameStringA
.Buffer
= lpTempFileName
;
64 TempFileNameStringA
.MaximumLength
= MAX_PATH
;
66 Status
= BasepUnicodeStringTo8BitString(&TempFileNameStringA
, &TempFileNameStringW
, FALSE
);
67 if (!NT_SUCCESS(Status
))
69 BaseSetLastNTError(Status
);
75 RtlFreeUnicodeString(&lpPrefixStringW
);
76 RtlFreeHeap(RtlGetProcessHeap(), 0, lpTempFileNameW
);
80 /***********************************************************************
81 * GetTempFileNameW (KERNEL32.@)
84 GetTempFileNameW(IN LPCWSTR lpPathName
,
85 IN LPCWSTR lpPrefixString
,
87 OUT LPWSTR lpTempFileName
)
94 BASE_API_MESSAGE ApiMessage
;
95 PBASE_GET_TEMP_FILE GetTempFile
= &ApiMessage
.Data
.GetTempFileRequest
;
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((PCSR_API_MESSAGE
)&ApiMessage
,
163 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX
, BasepGetTempFile
),
164 sizeof(BASE_GET_TEMP_FILE
));
165 if (GetTempFile
->UniqueID
== 0)
171 ID
= GetTempFile
->UniqueID
;
178 /* Convert that ID to wchar */
179 RtlIntegerToChar(ID
, 0x10, sizeof(IDString
), IDString
);
183 *(TempFileName
++) = RtlAnsiCharToUnicodeChar(&Let
);
186 /* Append extension & UNICODE_NULL */
187 memmove(TempFileName
, Ext
, sizeof(Ext
));
189 /* If user provided its ID, just return */
195 /* Then, try to create file */
196 if (!RtlIsDosDeviceName_U(lpTempFileName
))
198 TempFile
= CreateFileW(lpTempFileName
,
203 FILE_ATTRIBUTE_NORMAL
,
205 if (TempFile
!= INVALID_HANDLE_VALUE
)
208 DPRINT("Temp file: %S\n", lpTempFileName
);
212 LastError
= GetLastError();
213 /* There is no need to recover from those errors, they would hit next step */
214 if (LastError
== ERROR_INVALID_PARAMETER
|| LastError
== ERROR_CANNOT_MAKE
||
215 LastError
== ERROR_WRITE_PROTECT
|| LastError
== ERROR_NETWORK_ACCESS_DENIED
||
216 LastError
== ERROR_DISK_FULL
|| LastError
== ERROR_INVALID_NAME
||
217 LastError
== ERROR_BAD_PATHNAME
|| LastError
== ERROR_NO_INHERITANCE
||
218 LastError
== ERROR_DISK_CORRUPT
||
219 (LastError
== ERROR_ACCESS_DENIED
&& NtCurrentTeb()->LastStatusValue
!= STATUS_FILE_IS_A_DIRECTORY
))
225 } while (Num
& 0xFFFF);
241 UNICODE_STRING ShortName
;
242 IO_STATUS_BLOCK IoStatusBlock
;
243 PFILE_NAME_INFORMATION FileNameInfo
;
245 if(IsConsoleHandle(hFile
))
247 SetLastError(ERROR_INVALID_HANDLE
);
253 SetLastError(ERROR_INVALID_PARAMETER
);
257 RtlInitUnicodeString(&ShortName
, lpShortName
);
259 NeededSize
= sizeof(FILE_NAME_INFORMATION
) + ShortName
.Length
+ sizeof(WCHAR
);
260 if(!(FileNameInfo
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, NeededSize
)))
262 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
266 FileNameInfo
->FileNameLength
= ShortName
.Length
;
267 RtlCopyMemory(FileNameInfo
->FileName
, ShortName
.Buffer
, ShortName
.Length
);
269 Status
= NtSetInformationFile(hFile
,
270 &IoStatusBlock
, //out
273 FileShortNameInformation
);
275 RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameInfo
);
276 if(!NT_SUCCESS(Status
))
278 BaseSetLastNTError(Status
);
297 if(IsConsoleHandle(hFile
))
299 SetLastError(ERROR_INVALID_HANDLE
);
305 SetLastError(ERROR_INVALID_PARAMETER
);
309 if (!(ShortNameW
= FilenameA2W(lpShortName
, FALSE
)))
312 return SetFileShortNameW(hFile
, ShortNameW
);
321 CheckNameLegalDOS8Dot3W(
323 LPSTR lpOemName OPTIONAL
,
324 DWORD OemNameSize OPTIONAL
,
325 PBOOL pbNameContainsSpaces OPTIONAL
,
330 ANSI_STRING AnsiName
;
333 (lpOemName
== NULL
&& OemNameSize
!= 0) ||
336 SetLastError(ERROR_INVALID_PARAMETER
);
340 if(lpOemName
!= NULL
)
342 AnsiName
.Buffer
= lpOemName
;
343 AnsiName
.MaximumLength
= (USHORT
)OemNameSize
* sizeof(CHAR
);
347 RtlInitUnicodeString(&Name
, lpName
);
349 *pbNameLegal
= RtlIsNameLegalDOS8Dot3(&Name
,
350 (lpOemName
? &AnsiName
: NULL
),
351 (BOOLEAN
*)pbNameContainsSpaces
);
362 CheckNameLegalDOS8Dot3A(
364 LPSTR lpOemName OPTIONAL
,
365 DWORD OemNameSize OPTIONAL
,
366 PBOOL pbNameContainsSpaces OPTIONAL
,
371 ANSI_STRING AnsiName
, AnsiInputName
;
375 (lpOemName
== NULL
&& OemNameSize
!= 0) ||
378 SetLastError(ERROR_INVALID_PARAMETER
);
382 if(lpOemName
!= NULL
)
384 AnsiName
.Buffer
= lpOemName
;
385 AnsiName
.MaximumLength
= (USHORT
)OemNameSize
* sizeof(CHAR
);
389 RtlInitAnsiString(&AnsiInputName
, (LPSTR
)lpName
);
391 Status
= RtlAnsiStringToUnicodeString(&Name
, &AnsiInputName
, TRUE
);
393 Status
= RtlOemStringToUnicodeString(&Name
, &AnsiInputName
, TRUE
);
395 if(!NT_SUCCESS(Status
))
397 BaseSetLastNTError(Status
);
401 *pbNameLegal
= RtlIsNameLegalDOS8Dot3(&Name
,
402 (lpOemName
? &AnsiName
: NULL
),
403 (BOOLEAN
*)pbNameContainsSpaces
);
405 RtlFreeUnicodeString(&Name
);