compatibility fixes
[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 SET_LARGE_INTEGER_LOW_PART(FilePosition.CurrentByteOffset,
155 GET_LARGE_INTEGER_LOW_PART(FilePosition.CurrentByteOffset) +
156 lDistanceToMove);
157 if (lpDistanceToMoveHigh != NULL)
158 {
159 SET_LARGE_INTEGER_HIGH_PART(FilePosition.CurrentByteOffset,
160 GET_LARGE_INTEGER_HIGH_PART(FilePosition.CurrentByteOffset) +
161 *lpDistanceToMoveHigh);
162 }
163 }
164 else if (dwMoveMethod == FILE_END)
165 {
166 NtQueryInformationFile(hFile,&IoStatusBlock,&FileEndOfFile, sizeof(FILE_END_OF_FILE_INFORMATION),FileEndOfFileInformation);
167 SET_LARGE_INTEGER_LOW_PART(FilePosition.CurrentByteOffset,
168 GET_LARGE_INTEGER_LOW_PART(FileEndOfFile.EndOfFile) -
169 lDistanceToMove);
170 if ( lpDistanceToMoveHigh != NULL )
171 {
172 SET_LARGE_INTEGER_HIGH_PART(FilePosition.CurrentByteOffset,
173 GET_LARGE_INTEGER_HIGH_PART(FileEndOfFile.EndOfFile) -
174 *lpDistanceToMoveHigh);
175 }
176 else
177 {
178 SET_LARGE_INTEGER_HIGH_PART(FilePosition.CurrentByteOffset,
179 GET_LARGE_INTEGER_HIGH_PART(FileEndOfFile.EndOfFile));
180 }
181 }
182 else if ( dwMoveMethod == FILE_BEGIN )
183 {
184 SET_LARGE_INTEGER_LOW_PART(FilePosition.CurrentByteOffset,
185 lDistanceToMove);
186 if ( lpDistanceToMoveHigh != NULL )
187 {
188 SET_LARGE_INTEGER_HIGH_PART(FilePosition.CurrentByteOffset,
189 *lpDistanceToMoveHigh);
190 }
191 else
192 {
193 SET_LARGE_INTEGER_HIGH_PART(FilePosition.CurrentByteOffset,
194 0);
195 }
196 }
197
198 errCode = NtSetInformationFile(hFile,
199 &IoStatusBlock,
200 &FilePosition,
201 sizeof(FILE_POSITION_INFORMATION),
202 FilePositionInformation);
203 if (!NT_SUCCESS(errCode))
204 {
205 SetLastError(RtlNtStatusToDosError(errCode));
206 return -1;
207 }
208
209 if (lpDistanceToMoveHigh != NULL)
210 {
211 *lpDistanceToMoveHigh = GET_LARGE_INTEGER_HIGH_PART(
212 FilePosition.CurrentByteOffset);
213 }
214 return GET_LARGE_INTEGER_LOW_PART(FilePosition.CurrentByteOffset);
215 }
216
217 DWORD STDCALL GetFileType(HANDLE hFile)
218 {
219 return FILE_TYPE_UNKNOWN;
220 }
221
222
223 DWORD STDCALL GetFileSize(HANDLE hFile,
224 LPDWORD lpFileSizeHigh)
225 {
226 NTSTATUS errCode;
227 FILE_STANDARD_INFORMATION FileStandard;
228 IO_STATUS_BLOCK IoStatusBlock;
229
230
231 errCode = NtQueryInformationFile(hFile,
232 &IoStatusBlock,
233 &FileStandard,
234 sizeof(FILE_STANDARD_INFORMATION),
235 FileStandardInformation);
236 if (!NT_SUCCESS(errCode))
237 {
238 CloseHandle(hFile);
239 SetLastError(RtlNtStatusToDosError(errCode));
240 if ( lpFileSizeHigh == NULL )
241 {
242 return -1;
243 }
244 else
245 {
246 return 0;
247 }
248 }
249 if ( lpFileSizeHigh != NULL )
250 *lpFileSizeHigh = GET_LARGE_INTEGER_HIGH_PART(FileStandard.AllocationSize);
251
252 CloseHandle(hFile);
253 return GET_LARGE_INTEGER_LOW_PART(FileStandard.AllocationSize);
254 }
255
256 DWORD STDCALL GetCompressedFileSizeA(LPCSTR lpFileName,
257 LPDWORD lpFileSizeHigh)
258 {
259 WCHAR FileNameW[MAX_PATH];
260 ULONG i;
261
262 i = 0;
263 while ((*lpFileName)!=0 && i < MAX_PATH)
264 {
265 FileNameW[i] = *lpFileName;
266 lpFileName++;
267 i++;
268 }
269 FileNameW[i] = 0;
270
271 return GetCompressedFileSizeW(FileNameW,lpFileSizeHigh);
272 }
273
274 DWORD STDCALL GetCompressedFileSizeW(LPCWSTR lpFileName,
275 LPDWORD lpFileSizeHigh)
276 {
277 FILE_COMPRESSION_INFORMATION FileCompression;
278 NTSTATUS errCode;
279 IO_STATUS_BLOCK IoStatusBlock;
280 HANDLE hFile;
281
282 hFile = CreateFileW(lpFileName,
283 GENERIC_READ,
284 FILE_SHARE_READ,
285 NULL,
286 OPEN_EXISTING,
287 FILE_ATTRIBUTE_NORMAL,
288 NULL);
289
290 errCode = NtQueryInformationFile(hFile,
291 &IoStatusBlock,
292 &FileCompression,
293 sizeof(FILE_COMPRESSION_INFORMATION),
294 FileCompressionInformation);
295 if (!NT_SUCCESS(errCode))
296 {
297 CloseHandle(hFile);
298 SetLastError(RtlNtStatusToDosError(errCode));
299 return 0;
300 }
301 CloseHandle(hFile);
302 return 0;
303 }
304
305
306
307 WINBOOL STDCALL GetFileInformationByHandle(HANDLE hFile,
308 LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
309 {
310 FILE_DIRECTORY_INFORMATION FileDirectory;
311 FILE_INTERNAL_INFORMATION FileInternal;
312 FILE_FS_VOLUME_INFORMATION FileFsVolume;
313 FILE_STANDARD_INFORMATION FileStandard;
314 NTSTATUS errCode;
315 IO_STATUS_BLOCK IoStatusBlock;
316
317 errCode = NtQueryInformationFile(hFile,
318 &IoStatusBlock,
319 &FileDirectory,
320 sizeof(FILE_DIRECTORY_INFORMATION),
321 FileDirectoryInformation);
322 if (!NT_SUCCESS(errCode))
323 {
324 SetLastError(RtlNtStatusToDosError(errCode));
325 return FALSE;
326 }
327 lpFileInformation->dwFileAttributes = (DWORD)FileDirectory.FileAttributes;
328 memcpy(&lpFileInformation->ftCreationTime,&FileDirectory.CreationTime,sizeof(LARGE_INTEGER));
329 memcpy(&lpFileInformation->ftLastAccessTime,&FileDirectory.LastAccessTime,sizeof(LARGE_INTEGER));
330 memcpy(&lpFileInformation->ftLastWriteTime, &FileDirectory.LastWriteTime,sizeof(LARGE_INTEGER));
331 lpFileInformation->nFileSizeHigh = GET_LARGE_INTEGER_HIGH_PART(FileDirectory.AllocationSize);
332 lpFileInformation->nFileSizeLow = GET_LARGE_INTEGER_LOW_PART(FileDirectory.AllocationSize);
333
334 errCode = NtQueryInformationFile(hFile,
335 &IoStatusBlock,
336 &FileInternal,
337 sizeof(FILE_INTERNAL_INFORMATION),
338 FileInternalInformation);
339 if (!NT_SUCCESS(errCode))
340 {
341 SetLastError(RtlNtStatusToDosError(errCode));
342 return FALSE;
343 }
344 lpFileInformation->nFileIndexHigh = GET_LARGE_INTEGER_HIGH_PART(FileInternal.IndexNumber);
345 lpFileInformation->nFileIndexLow = GET_LARGE_INTEGER_LOW_PART(FileInternal.IndexNumber);
346
347 errCode = NtQueryVolumeInformationFile(hFile,
348 &IoStatusBlock,
349 &FileFsVolume,
350 sizeof(FILE_FS_VOLUME_INFORMATION),
351 FileFsVolumeInformation);
352 if (!NT_SUCCESS(errCode))
353 {
354 SetLastError(RtlNtStatusToDosError(errCode));
355 return FALSE;
356 }
357 lpFileInformation->dwVolumeSerialNumber = FileFsVolume.VolumeSerialNumber;
358
359 errCode = NtQueryInformationFile(hFile,
360 &IoStatusBlock,
361 &FileStandard,
362 sizeof(FILE_STANDARD_INFORMATION),
363 FileStandardInformation);
364 if (!NT_SUCCESS(errCode))
365 {
366 CloseHandle(hFile);
367 SetLastError(RtlNtStatusToDosError(errCode));
368 return FALSE;
369 }
370 lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks;
371 CloseHandle(hFile);
372 return TRUE;
373 }
374
375
376
377
378
379
380 DWORD STDCALL GetFileAttributesA(LPCSTR lpFileName)
381 {
382 ULONG i;
383 WCHAR FileNameW[MAX_PATH];
384
385 i = 0;
386 while ((*lpFileName)!=0 && i < MAX_PATH)
387 {
388 FileNameW[i] = *lpFileName;
389 lpFileName++;
390 i++;
391 }
392 FileNameW[i] = 0;
393 return GetFileAttributesW(FileNameW);
394 }
395
396
397 DWORD STDCALL GetFileAttributesW(LPCWSTR lpFileName)
398 {
399 IO_STATUS_BLOCK IoStatusBlock;
400 FILE_BASIC_INFORMATION FileBasic;
401 HANDLE hFile;
402 NTSTATUS errCode;
403
404 hFile = CreateFileW(lpFileName,
405 GENERIC_READ,
406 FILE_SHARE_READ,
407 NULL,
408 OPEN_EXISTING,
409 FILE_ATTRIBUTE_NORMAL,
410 NULL);
411
412
413 errCode = NtQueryInformationFile(hFile,
414 &IoStatusBlock,
415 &FileBasic,
416 sizeof(FILE_BASIC_INFORMATION),
417 FileBasicInformation);
418 if (!NT_SUCCESS(errCode))
419 {
420 CloseHandle(hFile);
421 SetLastError(RtlNtStatusToDosError(errCode));
422 return 0;
423 }
424 CloseHandle(hFile);
425 return (DWORD)FileBasic.FileAttributes;
426 }
427
428 WINBOOL STDCALL SetFileAttributesA(LPCSTR lpFileName,
429 DWORD dwFileAttributes)
430 {
431 ULONG i;
432 WCHAR FileNameW[MAX_PATH];
433 i = 0;
434 while ((*lpFileName)!=0 && i < MAX_PATH)
435 {
436 FileNameW[i] = *lpFileName;
437 lpFileName++;
438 i++;
439 }
440 FileNameW[i] = 0;
441 return SetFileAttributesW(FileNameW, dwFileAttributes);
442 }
443
444
445 WINBOOL STDCALL SetFileAttributesW(LPCWSTR lpFileName,
446 DWORD dwFileAttributes)
447 {
448 IO_STATUS_BLOCK IoStatusBlock;
449 FILE_BASIC_INFORMATION FileBasic;
450 HANDLE hFile;
451 NTSTATUS errCode;
452
453 hFile = CreateFileW(lpFileName,
454 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
455 FILE_SHARE_READ,
456 NULL,
457 OPEN_EXISTING,
458 FILE_ATTRIBUTE_NORMAL,
459 NULL);
460
461 errCode = NtQueryInformationFile(hFile,
462 &IoStatusBlock,
463 &FileBasic,
464 sizeof(FILE_BASIC_INFORMATION),
465 FileBasicInformation);
466 if (!NT_SUCCESS(errCode))
467 {
468 CloseHandle(hFile);
469 SetLastError(RtlNtStatusToDosError(errCode));
470 return FALSE;
471 }
472 FileBasic.FileAttributes = dwFileAttributes;
473 errCode = NtSetInformationFile(hFile,
474 &IoStatusBlock,
475 &FileBasic,
476 sizeof(FILE_BASIC_INFORMATION),
477 FileBasicInformation);
478 if (!NT_SUCCESS(errCode))
479 {
480 CloseHandle(hFile);
481 SetLastError(RtlNtStatusToDosError(errCode));
482 return FALSE;
483 }
484 CloseHandle(hFile);
485 return TRUE;
486 }
487
488
489
490
491
492 UINT STDCALL GetTempFileNameA(LPCSTR lpPathName,
493 LPCSTR lpPrefixString,
494 UINT uUnique,
495 LPSTR lpTempFileName)
496 {
497 HANDLE hFile;
498 UINT unique = uUnique;
499
500 if (lpPathName == NULL)
501 return 0;
502
503 if (uUnique == 0)
504 uUnique = GetCurrentTime();
505 /*
506 * sprintf(lpTempFileName,"%s\\%c%.3s%4.4x%s",
507 * lpPathName,'~',lpPrefixString,uUnique,".tmp");
508 */
509 if (unique)
510 return uUnique;
511
512 while ((hFile = CreateFileA(lpTempFileName, GENERIC_WRITE, 0, NULL,
513 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
514 0)) == INVALID_HANDLE_VALUE)
515 {
516 // wsprintfA(lpTempFileName,"%s\\%c%.3s%4.4x%s",
517 // lpPathName,'~',lpPrefixString,++uUnique,".tmp");
518 }
519
520 CloseHandle((HANDLE)hFile);
521 return uUnique;
522 }
523
524
525 UINT STDCALL GetTempFileNameW(LPCWSTR lpPathName,
526 LPCWSTR lpPrefixString,
527 UINT uUnique,
528 LPWSTR lpTempFileName)
529 {
530 HANDLE hFile;
531 UINT unique = uUnique;
532
533 if (lpPathName == NULL)
534 return 0;
535
536 if (uUnique == 0)
537 uUnique = GetCurrentTime();
538
539 // swprintf(lpTempFileName,L"%s\\%c%.3s%4.4x%s",
540 // lpPathName,'~',lpPrefixString,uUnique,L".tmp");
541
542 if (unique)
543 return uUnique;
544
545 while ((hFile = CreateFileW(lpTempFileName, GENERIC_WRITE, 0, NULL,
546 CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
547 0)) == INVALID_HANDLE_VALUE)
548 {
549 // wsprintfW(lpTempFileName,L"%s\\%c%.3s%4.4x%s",
550 // lpPathName,'~',lpPrefixString,++uUnique,L".tmp");
551 }
552
553 CloseHandle((HANDLE)hFile);
554 return uUnique;
555 }
556
557 WINBOOL STDCALL GetFileTime(HANDLE hFile,
558 LPFILETIME lpCreationTime,
559 LPFILETIME lpLastAccessTime,
560 LPFILETIME lpLastWriteTime)
561 {
562 IO_STATUS_BLOCK IoStatusBlock;
563 FILE_BASIC_INFORMATION FileBasic;
564 NTSTATUS errCode;
565
566 errCode = NtQueryInformationFile(hFile,
567 &IoStatusBlock,
568 &FileBasic,
569 sizeof(FILE_BASIC_INFORMATION),
570 FileBasicInformation);
571 if (!NT_SUCCESS(errCode))
572 {
573 SetLastError(RtlNtStatusToDosError(errCode));
574 return FALSE;
575 }
576 memcpy(lpCreationTime,&FileBasic.CreationTime,sizeof(FILETIME));
577 memcpy(lpLastAccessTime,&FileBasic.LastAccessTime,sizeof(FILETIME));
578 memcpy(lpLastWriteTime,&FileBasic.LastWriteTime,sizeof(FILETIME));
579 return TRUE;
580 }
581
582 WINBOOL STDCALL SetFileTime(HANDLE hFile,
583 CONST FILETIME *lpCreationTime,
584 CONST FILETIME *lpLastAccessTime,
585 CONST FILETIME *lpLastWriteTime)
586 {
587 FILE_BASIC_INFORMATION FileBasic;
588 IO_STATUS_BLOCK IoStatusBlock;
589 NTSTATUS errCode;
590
591 memcpy(&FileBasic.CreationTime,lpCreationTime,sizeof(FILETIME));
592 memcpy(&FileBasic.LastAccessTime,lpLastAccessTime,sizeof(FILETIME));
593 memcpy(&FileBasic.LastWriteTime,lpLastWriteTime,sizeof(FILETIME));
594
595 // shoud i initialize changetime ???
596
597 errCode = NtSetInformationFile(hFile,
598 &IoStatusBlock,
599 &FileBasic,
600 sizeof(FILE_BASIC_INFORMATION),
601 FileBasicInformation);
602 if (!NT_SUCCESS(errCode))
603 {
604 SetLastError(RtlNtStatusToDosError(errCode));
605 return FALSE;
606 }
607
608 return TRUE;
609 }
610
611 WINBOOL STDCALL SetEndOfFile(HANDLE hFile)
612 {
613 int x = -1;
614 DWORD Num;
615 return WriteFile(hFile,&x,1,&Num,NULL);
616 }