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