bb42e50761a7085ca88a0422934900bf85f33148
[reactos.git] / reactos / lib / kernel32 / file / file.c
1 /*
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 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7 * GetTempFileName is modified from WINE [ Alexandre Juiliard ]
8 * UPDATE HISTORY:
9 * Created 01/11/98
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <windows.h>
15 #include <ddk/ntddk.h>
16 #include <wchar.h>
17 #include <string.h>
18
19 #define NDEBUG
20 #include <kernel32/kernel32.h>
21
22 #define LPPROGRESS_ROUTINE void*
23
24 /* GLOBALS ******************************************************************/
25
26 static BOOLEAN bIsFileApiAnsi; // set the file api to ansi or oem
27
28 /* FUNCTIONS ****************************************************************/
29
30 VOID STDCALL SetFileApisToOEM(VOID)
31 {
32 bIsFileApiAnsi = FALSE;
33 }
34
35
36 VOID STDCALL SetFileApisToANSI(VOID)
37 {
38 bIsFileApiAnsi = TRUE;
39 }
40
41
42 WINBOOL STDCALL AreFileApisANSI(VOID)
43 {
44 return(bIsFileApiAnsi);
45 }
46
47
48 HFILE STDCALL OpenFile(LPCSTR lpFileName,
49 LPOFSTRUCT lpReOpenBuff,
50 UINT uStyle)
51 {
52 NTSTATUS errCode;
53 HANDLE FileHandle = NULL;
54 UNICODE_STRING FileNameString;
55 WCHAR FileNameW[MAX_PATH];
56 WCHAR PathNameW[MAX_PATH];
57 ULONG i;
58 OBJECT_ATTRIBUTES ObjectAttributes;
59 IO_STATUS_BLOCK IoStatusBlock;
60 WCHAR *FilePart;
61 ULONG Len;
62
63 if (lpReOpenBuff == NULL)
64 {
65 return FALSE;
66 }
67
68 i = 0;
69 while ((*lpFileName)!=0 && i < MAX_PATH)
70 {
71 FileNameW[i] = *lpFileName;
72 lpFileName++;
73 i++;
74 }
75 FileNameW[i] = 0;
76
77 Len = SearchPathW(NULL,FileNameW,NULL,MAX_PATH,PathNameW,&FilePart);
78 if ( Len == 0 )
79 return (HFILE)NULL;
80
81 if ( Len > MAX_PATH )
82 return (HFILE)NULL;
83
84 FileNameString.Length = lstrlenW(PathNameW)*sizeof(WCHAR);
85 FileNameString.Buffer = PathNameW;
86 FileNameString.MaximumLength = FileNameString.Length+sizeof(WCHAR);
87
88 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
89 ObjectAttributes.RootDirectory = NULL;
90 ObjectAttributes.ObjectName = &FileNameString;
91 ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT;
92 ObjectAttributes.SecurityDescriptor = NULL;
93 ObjectAttributes.SecurityQualityOfService = NULL;
94
95 // FILE_SHARE_READ
96 // FILE_NO_INTERMEDIATE_BUFFERING
97
98 if ((uStyle & OF_PARSE) == OF_PARSE )
99 return (HFILE)NULL;
100
101 errCode = NtOpenFile(&FileHandle,
102 GENERIC_READ|SYNCHRONIZE,
103 &ObjectAttributes,
104 &IoStatusBlock,
105 FILE_SHARE_READ,
106 FILE_NON_DIRECTORY_FILE);
107
108 lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode);
109
110 if (!NT_SUCCESS(errCode))
111 {
112 SetLastError(RtlNtStatusToDosError(errCode));
113 return (HFILE)INVALID_HANDLE_VALUE;
114 }
115
116 return (HFILE)FileHandle;
117 }
118
119
120 WINBOOL STDCALL FlushFileBuffers(HANDLE hFile)
121 {
122 NTSTATUS errCode;
123 IO_STATUS_BLOCK IoStatusBlock;
124
125 errCode = NtFlushBuffersFile(hFile,
126 &IoStatusBlock);
127 if (!NT_SUCCESS(errCode))
128 {
129 SetLastError(RtlNtStatusToDosError(errCode));
130 return(FALSE);
131 }
132 return(TRUE);
133 }
134
135
136 DWORD STDCALL SetFilePointer(HANDLE hFile,
137 LONG lDistanceToMove,
138 PLONG lpDistanceToMoveHigh,
139 DWORD dwMoveMethod)
140 {
141 FILE_POSITION_INFORMATION FilePosition;
142 FILE_END_OF_FILE_INFORMATION FileEndOfFile;
143 NTSTATUS errCode;
144 IO_STATUS_BLOCK IoStatusBlock;
145 LARGE_INTEGER Distance;
146
147 DPRINT("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
148 hFile,lDistanceToMove,dwMoveMethod);
149
150 Distance.u.LowPart = lDistanceToMove;
151 Distance.u.HighPart = (lpDistanceToMoveHigh) ? *lpDistanceToMoveHigh : 0;
152
153 if (dwMoveMethod == FILE_CURRENT)
154 {
155 NtQueryInformationFile(hFile,
156 &IoStatusBlock,
157 &FilePosition,
158 sizeof(FILE_POSITION_INFORMATION),
159 FilePositionInformation);
160 FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
161 }
162 else if (dwMoveMethod == FILE_END)
163 {
164 NtQueryInformationFile(hFile,
165 &IoStatusBlock,
166 &FileEndOfFile,
167 sizeof(FILE_END_OF_FILE_INFORMATION),
168 FileEndOfFileInformation);
169 FilePosition.CurrentByteOffset.QuadPart =
170 FileEndOfFile.EndOfFile.QuadPart - Distance.QuadPart;
171 }
172 else if ( dwMoveMethod == FILE_BEGIN )
173 {
174 FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
175 }
176
177 errCode = NtSetInformationFile(hFile,
178 &IoStatusBlock,
179 &FilePosition,
180 sizeof(FILE_POSITION_INFORMATION),
181 FilePositionInformation);
182 if (!NT_SUCCESS(errCode))
183 {
184 SetLastError(RtlNtStatusToDosError(errCode));
185 return -1;
186 }
187
188 if (lpDistanceToMoveHigh != NULL)
189 {
190 *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
191 }
192 return FilePosition.CurrentByteOffset.u.LowPart;
193 }
194
195
196 DWORD STDCALL GetFileType(HANDLE hFile)
197 {
198 return FILE_TYPE_UNKNOWN;
199 }
200
201
202 DWORD STDCALL GetFileSize(HANDLE hFile,
203 LPDWORD lpFileSizeHigh)
204 {
205 NTSTATUS errCode;
206 FILE_STANDARD_INFORMATION FileStandard;
207 IO_STATUS_BLOCK IoStatusBlock;
208
209 errCode = NtQueryInformationFile(hFile,
210 &IoStatusBlock,
211 &FileStandard,
212 sizeof(FILE_STANDARD_INFORMATION),
213 FileStandardInformation);
214 if (!NT_SUCCESS(errCode))
215 {
216 SetLastError(RtlNtStatusToDosError(errCode));
217 if ( lpFileSizeHigh == NULL )
218 {
219 return -1;
220 }
221 else
222 {
223 return 0;
224 }
225 }
226 if ( lpFileSizeHigh != NULL )
227 *lpFileSizeHigh = FileStandard.AllocationSize.u.HighPart;
228
229 return FileStandard.AllocationSize.u.LowPart;
230 }
231
232
233 DWORD STDCALL GetCompressedFileSizeA(LPCSTR lpFileName,
234 LPDWORD lpFileSizeHigh)
235 {
236 WCHAR FileNameW[MAX_PATH];
237 ULONG i;
238
239 i = 0;
240 while ((*lpFileName)!=0 && i < MAX_PATH)
241 {
242 FileNameW[i] = *lpFileName;
243 lpFileName++;
244 i++;
245 }
246 FileNameW[i] = 0;
247
248 return GetCompressedFileSizeW(FileNameW,lpFileSizeHigh);
249 }
250
251
252 DWORD STDCALL GetCompressedFileSizeW(LPCWSTR lpFileName,
253 LPDWORD lpFileSizeHigh)
254 {
255 FILE_COMPRESSION_INFORMATION FileCompression;
256 NTSTATUS errCode;
257 IO_STATUS_BLOCK IoStatusBlock;
258 HANDLE hFile;
259
260 hFile = CreateFileW(lpFileName,
261 GENERIC_READ,
262 FILE_SHARE_READ,
263 NULL,
264 OPEN_EXISTING,
265 FILE_ATTRIBUTE_NORMAL,
266 NULL);
267
268 errCode = NtQueryInformationFile(hFile,
269 &IoStatusBlock,
270 &FileCompression,
271 sizeof(FILE_COMPRESSION_INFORMATION),
272 FileCompressionInformation);
273 if (!NT_SUCCESS(errCode))
274 {
275 CloseHandle(hFile);
276 SetLastError(RtlNtStatusToDosError(errCode));
277 return 0;
278 }
279 CloseHandle(hFile);
280 return 0;
281 }
282
283
284 WINBOOL STDCALL GetFileInformationByHandle(HANDLE hFile,
285 LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
286 {
287 FILE_DIRECTORY_INFORMATION FileDirectory;
288 FILE_INTERNAL_INFORMATION FileInternal;
289 FILE_FS_VOLUME_INFORMATION FileFsVolume;
290 FILE_STANDARD_INFORMATION FileStandard;
291 NTSTATUS errCode;
292 IO_STATUS_BLOCK IoStatusBlock;
293
294 errCode = NtQueryInformationFile(hFile,
295 &IoStatusBlock,
296 &FileDirectory,
297 sizeof(FILE_DIRECTORY_INFORMATION),
298 FileDirectoryInformation);
299 if (!NT_SUCCESS(errCode))
300 {
301 SetLastError(RtlNtStatusToDosError(errCode));
302 return FALSE;
303 }
304
305 lpFileInformation->dwFileAttributes = (DWORD)FileDirectory.FileAttributes;
306 memcpy(&lpFileInformation->ftCreationTime,&FileDirectory.CreationTime,sizeof(LARGE_INTEGER));
307 memcpy(&lpFileInformation->ftLastAccessTime,&FileDirectory.LastAccessTime,sizeof(LARGE_INTEGER));
308 memcpy(&lpFileInformation->ftLastWriteTime, &FileDirectory.LastWriteTime,sizeof(LARGE_INTEGER));
309 lpFileInformation->nFileSizeHigh = FileDirectory.AllocationSize.u.HighPart;
310 lpFileInformation->nFileSizeLow = FileDirectory.AllocationSize.u.LowPart;
311
312 errCode = NtQueryInformationFile(hFile,
313 &IoStatusBlock,
314 &FileInternal,
315 sizeof(FILE_INTERNAL_INFORMATION),
316 FileInternalInformation);
317 if (!NT_SUCCESS(errCode))
318 {
319 SetLastError(RtlNtStatusToDosError(errCode));
320 return FALSE;
321 }
322
323 lpFileInformation->nFileIndexHigh = FileInternal.IndexNumber.u.HighPart;
324 lpFileInformation->nFileIndexLow = FileInternal.IndexNumber.u.LowPart;
325
326 errCode = NtQueryVolumeInformationFile(hFile,
327 &IoStatusBlock,
328 &FileFsVolume,
329 sizeof(FILE_FS_VOLUME_INFORMATION),
330 FileFsVolumeInformation);
331 if (!NT_SUCCESS(errCode))
332 {
333 SetLastError(RtlNtStatusToDosError(errCode));
334 return FALSE;
335 }
336
337 lpFileInformation->dwVolumeSerialNumber = FileFsVolume.VolumeSerialNumber;
338
339 errCode = NtQueryInformationFile(hFile,
340 &IoStatusBlock,
341 &FileStandard,
342 sizeof(FILE_STANDARD_INFORMATION),
343 FileStandardInformation);
344 if (!NT_SUCCESS(errCode))
345 {
346 SetLastError(RtlNtStatusToDosError(errCode));
347 return FALSE;
348 }
349
350 lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks;
351
352 return TRUE;
353 }
354
355
356 DWORD STDCALL GetFileAttributesA(LPCSTR lpFileName)
357 {
358 ULONG i;
359 WCHAR FileNameW[MAX_PATH];
360
361 i = 0;
362 while ((*lpFileName)!=0 && i < MAX_PATH)
363 {
364 FileNameW[i] = *lpFileName;
365 lpFileName++;
366 i++;
367 }
368 FileNameW[i] = 0;
369 return GetFileAttributesW(FileNameW);
370 }
371
372
373 DWORD STDCALL GetFileAttributesW(LPCWSTR lpFileName)
374 {
375 IO_STATUS_BLOCK IoStatusBlock;
376 FILE_BASIC_INFORMATION FileBasic;
377 HANDLE hFile;
378 NTSTATUS errCode;
379
380 hFile = CreateFileW(lpFileName,
381 FILE_READ_ATTRIBUTES,
382 FILE_SHARE_READ,
383 NULL,
384 OPEN_EXISTING,
385 FILE_ATTRIBUTE_NORMAL,
386 NULL);
387
388
389 errCode = NtQueryInformationFile(hFile,
390 &IoStatusBlock,
391 &FileBasic,
392 sizeof(FILE_BASIC_INFORMATION),
393 FileBasicInformation);
394 if (!NT_SUCCESS(errCode))
395 {
396 CloseHandle(hFile);
397 SetLastError(RtlNtStatusToDosError(errCode));
398 return 0xFFFFFFFF;
399 }
400 CloseHandle(hFile);
401 return (DWORD)FileBasic.FileAttributes;
402 }
403
404
405 WINBOOL STDCALL SetFileAttributesA(LPCSTR lpFileName,
406 DWORD dwFileAttributes)
407 {
408 ULONG i;
409 WCHAR FileNameW[MAX_PATH];
410 i = 0;
411 while ((*lpFileName)!=0 && i < MAX_PATH)
412 {
413 FileNameW[i] = *lpFileName;
414 lpFileName++;
415 i++;
416 }
417 FileNameW[i] = 0;
418 return SetFileAttributesW(FileNameW, dwFileAttributes);
419 }
420
421
422 WINBOOL STDCALL SetFileAttributesW(LPCWSTR lpFileName,
423 DWORD dwFileAttributes)
424 {
425 IO_STATUS_BLOCK IoStatusBlock;
426 FILE_BASIC_INFORMATION FileBasic;
427 HANDLE hFile;
428 NTSTATUS errCode;
429
430 hFile = CreateFileW(lpFileName,
431 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
432 FILE_SHARE_READ,
433 NULL,
434 OPEN_EXISTING,
435 FILE_ATTRIBUTE_NORMAL,
436 NULL);
437
438 errCode = NtQueryInformationFile(hFile,
439 &IoStatusBlock,
440 &FileBasic,
441 sizeof(FILE_BASIC_INFORMATION),
442 FileBasicInformation);
443 if (!NT_SUCCESS(errCode))
444 {
445 CloseHandle(hFile);
446 SetLastError(RtlNtStatusToDosError(errCode));
447 return FALSE;
448 }
449 FileBasic.FileAttributes = dwFileAttributes;
450 errCode = NtSetInformationFile(hFile,
451 &IoStatusBlock,
452 &FileBasic,
453 sizeof(FILE_BASIC_INFORMATION),
454 FileBasicInformation);
455 if (!NT_SUCCESS(errCode))
456 {
457 CloseHandle(hFile);
458 SetLastError(RtlNtStatusToDosError(errCode));
459 return FALSE;
460 }
461 CloseHandle(hFile);
462 return TRUE;
463 }
464
465
466 UINT STDCALL GetTempFileNameA(LPCSTR lpPathName,
467 LPCSTR lpPrefixString,
468 UINT uUnique,
469 LPSTR lpTempFileName)
470 {
471 HANDLE hFile;
472 UINT unique = uUnique;
473
474 if (lpPathName == NULL)
475 return 0;
476
477 if (uUnique == 0)
478 uUnique = GetCurrentTime();
479 /*
480 * sprintf(lpTempFileName,"%s\\%c%.3s%4.4x%s",
481 * lpPathName,'~',lpPrefixString,uUnique,".tmp");
482 */
483 if (unique)
484 return uUnique;
485
486 while ((hFile = CreateFileA(lpTempFileName, GENERIC_WRITE, 0, NULL,
487 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
488 0)) == INVALID_HANDLE_VALUE)
489 {
490 // wsprintfA(lpTempFileName,"%s\\%c%.3s%4.4x%s",
491 // lpPathName,'~',lpPrefixString,++uUnique,".tmp");
492 }
493
494 CloseHandle((HANDLE)hFile);
495 return uUnique;
496 }
497
498
499 UINT STDCALL GetTempFileNameW(LPCWSTR lpPathName,
500 LPCWSTR lpPrefixString,
501 UINT uUnique,
502 LPWSTR lpTempFileName)
503 {
504 HANDLE hFile;
505 UINT unique = uUnique;
506
507 if (lpPathName == NULL)
508 return 0;
509
510 if (uUnique == 0)
511 uUnique = GetCurrentTime();
512
513 // swprintf(lpTempFileName,L"%s\\%c%.3s%4.4x%s",
514 // lpPathName,'~',lpPrefixString,uUnique,L".tmp");
515
516 if (unique)
517 return uUnique;
518
519 while ((hFile = CreateFileW(lpTempFileName, GENERIC_WRITE, 0, NULL,
520 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
521 0)) == INVALID_HANDLE_VALUE)
522 {
523 // wsprintfW(lpTempFileName,L"%s\\%c%.3s%4.4x%s",
524 // lpPathName,'~',lpPrefixString,++uUnique,L".tmp");
525 }
526
527 CloseHandle((HANDLE)hFile);
528 return uUnique;
529 }
530
531
532 WINBOOL STDCALL GetFileTime(HANDLE hFile,
533 LPFILETIME lpCreationTime,
534 LPFILETIME lpLastAccessTime,
535 LPFILETIME lpLastWriteTime)
536 {
537 IO_STATUS_BLOCK IoStatusBlock;
538 FILE_BASIC_INFORMATION FileBasic;
539 NTSTATUS errCode;
540
541 errCode = NtQueryInformationFile(hFile,
542 &IoStatusBlock,
543 &FileBasic,
544 sizeof(FILE_BASIC_INFORMATION),
545 FileBasicInformation);
546 if (!NT_SUCCESS(errCode))
547 {
548 SetLastError(RtlNtStatusToDosError(errCode));
549 return FALSE;
550 }
551
552 memcpy(lpCreationTime,&FileBasic.CreationTime,sizeof(FILETIME));
553 memcpy(lpLastAccessTime,&FileBasic.LastAccessTime,sizeof(FILETIME));
554 memcpy(lpLastWriteTime,&FileBasic.LastWriteTime,sizeof(FILETIME));
555
556 return TRUE;
557 }
558
559
560 WINBOOL STDCALL SetFileTime(HANDLE hFile,
561 CONST FILETIME *lpCreationTime,
562 CONST FILETIME *lpLastAccessTime,
563 CONST FILETIME *lpLastWriteTime)
564 {
565 FILE_BASIC_INFORMATION FileBasic;
566 IO_STATUS_BLOCK IoStatusBlock;
567 NTSTATUS errCode;
568
569 memcpy(&FileBasic.CreationTime,lpCreationTime,sizeof(FILETIME));
570 memcpy(&FileBasic.LastAccessTime,lpLastAccessTime,sizeof(FILETIME));
571 memcpy(&FileBasic.LastWriteTime,lpLastWriteTime,sizeof(FILETIME));
572
573 // shoud i initialize changetime ???
574
575 errCode = NtSetInformationFile(hFile,
576 &IoStatusBlock,
577 &FileBasic,
578 sizeof(FILE_BASIC_INFORMATION),
579 FileBasicInformation);
580 if (!NT_SUCCESS(errCode))
581 {
582 SetLastError(RtlNtStatusToDosError(errCode));
583 return FALSE;
584 }
585
586 return TRUE;
587 }
588
589
590 WINBOOL STDCALL SetEndOfFile(HANDLE hFile)
591 {
592 int x = -1;
593 DWORD Num;
594 return WriteFile(hFile,&x,1,&Num,NULL);
595 }