VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/win32/fileio-win32.cpp@ 1581

Last change on this file since 1581 was 1581, checked in by vboxsync, 18 years ago

r=bird: Too verbose comments that just repeated the code (fixed).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 22.3 KB
Line 
1/* $Id: fileio-win32.cpp 1581 2007-03-20 20:21:21Z vboxsync $ */
2/** @file
3 * InnoTek Portable Runtime - File I/O, native implementation for the Windows host platform.
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP RTLOGGROUP_DIR
27#include <Windows.h>
28
29#include <iprt/file.h>
30#include <iprt/path.h>
31#include <iprt/assert.h>
32#include <iprt/string.h>
33#include <iprt/err.h>
34#include <iprt/log.h>
35#include "internal/file.h"
36#include "internal/fs.h"
37#include "internal/path.h"
38
39
40/*******************************************************************************
41* Defined Constants And Macros *
42*******************************************************************************/
43/** @def RT_DONT_CONVERT_FILENAMES
44 * Define this to pass UTF-8 unconverted to the kernel. */
45#ifdef __DOXYGEN__
46# define RT_DONT_CONVERT_FILENAMES 1
47#endif
48
49
50/**
51 * This is wrapper around the ugly SetFilePointer api.
52 *
53 * It's equivalent to SetFilePointerEx which we so unfortunately cannot use because of
54 * it not being present in NT4 GA.
55 *
56 * @returns Success indicator. Extended error information obtainable using GetLastError().
57 * @param File Filehandle.
58 * @param offSeek Offset to seek.
59 * @param poffNew Where to store the new file offset. NULL allowed.
60 * @param uMethod Seek method. (The windows one!)
61 */
62inline bool MySetFilePointer(RTFILE File, uint64_t offSeek, uint64_t *poffNew, unsigned uMethod)
63{
64 LARGE_INTEGER off;
65 off.QuadPart = offSeek;
66#if 1
67 off.LowPart = SetFilePointer((HANDLE)File, off.LowPart, &off.HighPart, uMethod);
68 bool fRc = off.LowPart != INVALID_SET_FILE_POINTER;
69#else
70 bool fRc = SetFilePointerEx((HANDLE)File, off, &off, uMethod);
71#endif
72 if (fRc && poffNew)
73 *poffNew = off.QuadPart;
74 return fRc;
75}
76
77
78/**
79 * This is a helper to check if an attempt was made to grow a file beyond the
80 * limit of the filesystem.
81 *
82 * @returns true for file size limit exceeded.
83 * @param File Filehandle.
84 * @param offSeek Offset to seek.
85 */
86DECLINLINE(bool) IsBeyondLimit(RTFILE File, uint64_t offSeek, unsigned uMethod)
87{
88 bool fIsBeyondLimit = false;
89
90 /*
91 * Get the current file position and try set the new one.
92 * If it fails with a seek error it's because we hit the file system limit.
93 */
94 uint64_t offCurrent;
95 if (MySetFilePointer(File, 0, &offCurrent, FILE_CURRENT))
96 {
97 if (!MySetFilePointer(File, offSeek, NULL, uMethod))
98 fIsBeyondLimit = GetLastError() == ERROR_SEEK;
99 else /* Restore file pointer on success. */
100 MySetFilePointer(File, offCurrent, NULL, FILE_BEGIN);
101 }
102
103 return fIsBeyondLimit;
104}
105
106
107RTR3DECL(int) RTFileOpen(PRTFILE pFile, const char *pszFilename, unsigned fOpen)
108{
109 /*
110 * Validate input.
111 */
112 if (!pFile)
113 {
114 AssertMsgFailed(("Invalid pFile\n"));
115 return VERR_INVALID_PARAMETER;
116 }
117 *pFile = NIL_RTFILE;
118 if (!pszFilename)
119 {
120 AssertMsgFailed(("Invalid pszFilename\n"));
121 return VERR_INVALID_PARAMETER;
122 }
123
124 /*
125 * Merge forced open flags and validate them.
126 */
127 int rc = rtFileRecalcAndValidateFlags(&fOpen);
128 if (RT_FAILURE(rc))
129 return rc;
130
131 /*
132 * Determine disposition, access, share mode, creation flags, and security attributes
133 * for the CreateFile API call.
134 */
135 DWORD dwCreationDisposition;
136 switch (fOpen & RTFILE_O_ACTION_MASK)
137 {
138 case RTFILE_O_OPEN:
139 dwCreationDisposition = fOpen & RTFILE_O_TRUNCATE ? TRUNCATE_EXISTING : OPEN_EXISTING;
140 break;
141 case RTFILE_O_OPEN_CREATE:
142 dwCreationDisposition = OPEN_ALWAYS;
143 break;
144 case RTFILE_O_CREATE:
145 dwCreationDisposition = CREATE_NEW;
146 break;
147 case RTFILE_O_CREATE_REPLACE:
148 dwCreationDisposition = CREATE_ALWAYS;
149 break;
150 default:
151 AssertMsgFailed(("Impossible fOpen=%#x\n", fOpen));
152 return VERR_INVALID_PARAMETER;
153 }
154
155 DWORD dwDesiredAccess;
156 switch (fOpen & RTFILE_O_ACCESS_MASK)
157 {
158 case RTFILE_O_READ: dwDesiredAccess = GENERIC_READ; break;
159 case RTFILE_O_WRITE: dwDesiredAccess = GENERIC_WRITE; break;
160 case RTFILE_O_READWRITE: dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; break;
161 default:
162 AssertMsgFailed(("Impossible fOpen=%#x\n", fOpen));
163 return VERR_INVALID_PARAMETER;
164 }
165
166 DWORD dwShareMode;
167 Assert(RTFILE_O_DENY_READWRITE == RTFILE_O_DENY_ALL && !RTFILE_O_DENY_NONE);
168 switch (fOpen & RTFILE_O_DENY_MASK)
169 {
170 case RTFILE_O_DENY_NONE: dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; break;
171 case RTFILE_O_DENY_READ: dwShareMode = FILE_SHARE_WRITE; break;
172 case RTFILE_O_DENY_WRITE: dwShareMode = FILE_SHARE_READ; break;
173 case RTFILE_O_DENY_READWRITE: dwShareMode = 0; break;
174
175 case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_NONE: dwShareMode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE; break;
176 case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_READ: dwShareMode = FILE_SHARE_DELETE | FILE_SHARE_WRITE; break;
177 case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_WRITE: dwShareMode = FILE_SHARE_DELETE | FILE_SHARE_READ; break;
178 case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_READWRITE:dwShareMode = FILE_SHARE_DELETE; break;
179 default:
180 AssertMsgFailed(("Impossible fOpen=%#x\n", fOpen));
181 return VERR_INVALID_PARAMETER;
182 }
183
184 SECURITY_ATTRIBUTES SecurityAttributes;
185 PSECURITY_ATTRIBUTES pSecurityAttributes = NULL;
186 if (fOpen & RTFILE_O_INHERIT)
187 {
188 SecurityAttributes.nLength = sizeof(SecurityAttributes);
189 SecurityAttributes.lpSecurityDescriptor = NULL;
190 SecurityAttributes.bInheritHandle = TRUE;
191 pSecurityAttributes = &SecurityAttributes;
192 }
193
194 DWORD dwFlagsAndAttributes;
195 dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
196 if (fOpen & RTFILE_O_WRITE_THROUGH)
197 dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH;
198
199 /*
200 * Open/Create the file.
201 */
202#ifdef RT_DONT_CONVERT_FILENAMES
203 HANDLE hFile = CreateFile(pszFilename,
204 dwDesiredAccess,
205 dwShareMode,
206 pSecurityAttributes,
207 dwCreationDisposition,
208 dwFlagsAndAttributes,
209 NULL);
210 if (hFile == INVALID_HANDLE_VALUE)
211 return RTErrConvertFromWin32(GetLastError());
212
213#else
214 PRTUCS2 pwszFilename;
215 rc = RTStrToUtf16(pszFilename, &pwszFilename);
216 if (RT_FAILURE(rc))
217 return rc;
218
219 HANDLE hFile = CreateFileW(pwszFilename,
220 dwDesiredAccess,
221 dwShareMode,
222 pSecurityAttributes,
223 dwCreationDisposition,
224 dwFlagsAndAttributes,
225 NULL);
226 if (hFile == INVALID_HANDLE_VALUE)
227 {
228 rc = RTErrConvertFromWin32(GetLastError()); /* get error first! */
229 RTUtf16Free(pwszFilename);
230 return rc;
231 }
232 RTUtf16Free(pwszFilename);
233#endif
234
235 /*
236 * Do we need to truncate the file?
237 */
238 if ( (fOpen & (RTFILE_O_TRUNCATE | RTFILE_O_ACTION_MASK))
239 == (RTFILE_O_TRUNCATE | RTFILE_O_OPEN_CREATE))
240 {
241 if (!SetEndOfFile(hFile))
242 {
243 rc = RTErrConvertFromWin32(GetLastError()); /* get error first! */
244 CloseHandle(hFile);
245 return rc;
246 }
247 }
248
249 *pFile = (RTFILE)hFile;
250 Assert((HANDLE)*pFile == hFile);
251 return VINF_SUCCESS;
252}
253
254
255RTR3DECL(int) RTFileClose(RTFILE File)
256{
257 if (CloseHandle((HANDLE)File))
258 return VINF_SUCCESS;
259 return RTErrConvertFromWin32(GetLastError());
260}
261
262
263RTR3DECL(int) RTFileSeek(RTFILE File, int64_t offSeek, unsigned uMethod, uint64_t *poffActual)
264{
265 static ULONG aulSeekRecode[] =
266 {
267 FILE_BEGIN,
268 FILE_CURRENT,
269 FILE_END,
270 };
271
272 /*
273 * Validate input.
274 */
275 if (uMethod > RTFILE_SEEK_END)
276 {
277 AssertMsgFailed(("Invalid uMethod=%d\n", uMethod));
278 return VERR_INVALID_PARAMETER;
279 }
280
281 /*
282 * Execute the seek.
283 */
284 if (MySetFilePointer(File, offSeek, poffActual, aulSeekRecode[uMethod]))
285 return VINF_SUCCESS;
286 return RTErrConvertFromWin32(GetLastError());
287}
288
289
290RTR3DECL(int) RTFileRead(RTFILE File, void *pvBuf, unsigned cbToRead, unsigned *pcbRead)
291{
292 if (cbToRead <= 0)
293 return VINF_SUCCESS;
294
295 ULONG cbRead = 0;
296 if (ReadFile((HANDLE)File, pvBuf, cbToRead, &cbRead, NULL))
297 {
298 if (pcbRead)
299 /* Caller can handle partial reads. */
300 *pcbRead = cbRead;
301 else
302 {
303 /* Caller expects everything to be read. */
304 while (cbToRead > cbRead)
305 {
306 ULONG cbReadPart = 0;
307 if (!ReadFile((HANDLE)File, (char*)pvBuf + cbRead, cbToRead - cbRead, &cbReadPart, NULL))
308 return RTErrConvertFromWin32(GetLastError());
309 if (cbReadPart == 0)
310 return VERR_EOF;
311 cbRead += cbReadPart;
312 }
313 }
314 return VINF_SUCCESS;
315 }
316 return RTErrConvertFromWin32(GetLastError());
317}
318
319
320RTR3DECL(int) RTFileWrite(RTFILE File, const void *pvBuf, unsigned cbToWrite, unsigned *pcbWritten)
321{
322 if (cbToWrite <= 0)
323 return VINF_SUCCESS;
324
325 ULONG cbWritten = 0;
326 if (WriteFile((HANDLE)File, pvBuf, cbToWrite, &cbWritten, NULL))
327 {
328 if (pcbWritten)
329 /* Caller can handle partial writes. */
330 *pcbWritten = cbWritten;
331 else
332 {
333 /* Caller expects everything to be written. */
334 while (cbToWrite > cbWritten)
335 {
336 ULONG cbWrittenPart = 0;
337 if (!WriteFile((HANDLE)File, (char*)pvBuf + cbWritten, cbToWrite - cbWritten, &cbWrittenPart, NULL))
338 {
339 int rc = RTErrConvertFromWin32(GetLastError());
340 if ( rc == VERR_DISK_FULL
341 && IsBeyondLimit(File, cbToWrite - cbWritten, FILE_CURRENT)
342 )
343 rc = VERR_FILE_TOO_BIG;
344 return rc;
345 }
346 if (cbWrittenPart == 0)
347 return VERR_WRITE_ERROR;
348 cbWritten += cbWrittenPart;
349 }
350 }
351 return VINF_SUCCESS;
352 }
353 int rc = RTErrConvertFromWin32(GetLastError());
354 if ( rc == VERR_DISK_FULL
355 && IsBeyondLimit(File, cbToWrite - cbWritten, FILE_CURRENT)
356 )
357 rc = VERR_FILE_TOO_BIG;
358 return rc;
359}
360
361
362RTR3DECL(int) RTFileFlush(RTFILE File)
363{
364 int rc;
365
366 if (FlushFileBuffers((HANDLE)File) == FALSE)
367 {
368 rc = GetLastError();
369 Log(("FlushFileBuffers failed with %d\n", rc));
370 return RTErrConvertFromWin32(rc);
371 }
372 return VINF_SUCCESS;
373}
374
375
376RTR3DECL(int) RTFileSetSize(RTFILE File, uint64_t cbSize)
377{
378 /*
379 * Get current file pointer.
380 */
381 int rc;
382 uint64_t offCurrent;
383 if (MySetFilePointer(File, 0, &offCurrent, FILE_CURRENT))
384 {
385 /*
386 * Set new file pointer.
387 */
388 if (MySetFilePointer(File, cbSize, NULL, FILE_BEGIN))
389 {
390 /* file pointer setted */
391 if (SetEndOfFile((HANDLE)File))
392 {
393 /*
394 * Restore file pointer and return.
395 * If the old pointer was beyond the new file end, ignore failure.
396 */
397 if ( MySetFilePointer(File, offCurrent, NULL, FILE_BEGIN)
398 || offCurrent > cbSize)
399 return VINF_SUCCESS;
400 }
401
402 /*
403 * Failed, try restore file pointer.
404 */
405 rc = GetLastError();
406 MySetFilePointer(File, offCurrent, NULL, FILE_BEGIN);
407 }
408 else
409 rc = GetLastError();
410 }
411 else
412 rc = GetLastError();
413
414 return RTErrConvertFromWin32(rc);
415}
416
417
418RTR3DECL(int) RTFileGetSize(RTFILE File, uint64_t *pcbSize)
419{
420 ULARGE_INTEGER Size;
421 Size.LowPart = GetFileSize((HANDLE)File, &Size.HighPart);
422 if (Size.LowPart != INVALID_FILE_SIZE)
423 {
424 *pcbSize = Size.QuadPart;
425 return VINF_SUCCESS;
426 }
427
428 /* error exit */
429 return RTErrConvertFromWin32(GetLastError());
430}
431
432
433RTR3DECL(bool) RTFileIsValid(RTFILE File)
434{
435 if (File != NIL_RTFILE)
436 {
437 DWORD dwType = GetFileType((HANDLE)File);
438 switch (dwType)
439 {
440 case FILE_TYPE_CHAR:
441 case FILE_TYPE_DISK:
442 case FILE_TYPE_PIPE:
443 case FILE_TYPE_REMOTE:
444 return true;
445
446 case FILE_TYPE_UNKNOWN:
447 if (GetLastError() == NO_ERROR)
448 return true;
449 break;
450 }
451 }
452 return false;
453}
454
455
456#define LOW_DWORD(u64) ((DWORD)u64)
457#define HIGH_DWORD(u64) (((DWORD *)&u64)[1])
458
459RTR3DECL(int) RTFileLock(RTFILE File, unsigned fLock, int64_t offLock, uint64_t cbLock)
460{
461 Assert(offLock >= 0);
462
463 /* Check arguments. */
464 if (fLock & ~RTFILE_LOCK_MASK)
465 {
466 AssertMsgFailed(("Invalid fLock=%08X\n", fLock));
467 return VERR_INVALID_PARAMETER;
468 }
469
470 /* Prepare flags. */
471 Assert(RTFILE_LOCK_WRITE);
472 DWORD dwFlags = (fLock & RTFILE_LOCK_WRITE) ? LOCKFILE_EXCLUSIVE_LOCK : 0;
473 Assert(RTFILE_LOCK_WAIT);
474 if (!(fLock & RTFILE_LOCK_WAIT))
475 dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
476
477 /* Windows structure. */
478 OVERLAPPED Overlapped;
479 memset(&Overlapped, 0, sizeof(Overlapped));
480 Overlapped.Offset = LOW_DWORD(offLock);
481 Overlapped.OffsetHigh = HIGH_DWORD(offLock);
482
483 /* Note: according to Microsoft, LockFileEx API call is available starting from NT 3.5 */
484 if (LockFileEx((HANDLE)File, dwFlags, 0, LOW_DWORD(cbLock), HIGH_DWORD(cbLock), &Overlapped))
485 return VINF_SUCCESS;
486
487 return RTErrConvertFromWin32(GetLastError());
488}
489
490
491RTR3DECL(int) RTFileChangeLock(RTFILE File, unsigned fLock, int64_t offLock, uint64_t cbLock)
492{
493 Assert(offLock >= 0);
494
495 /* Check arguments. */
496 if (fLock & ~RTFILE_LOCK_MASK)
497 {
498 AssertMsgFailed(("Invalid fLock=%08X\n", fLock));
499 return VERR_INVALID_PARAMETER;
500 }
501
502 /* Remove old lock. */
503 int rc = RTFileUnlock(File, offLock, cbLock);
504 if (RT_FAILURE(rc))
505 return rc;
506
507 /* Set new lock. */
508 rc = RTFileLock(File, fLock, offLock, cbLock);
509 if (RT_SUCCESS(rc))
510 return rc;
511
512 /* Try to restore old lock. */
513 unsigned fLockOld = (fLock & RTFILE_LOCK_WRITE) ? fLock & ~RTFILE_LOCK_WRITE : fLock | RTFILE_LOCK_WRITE;
514 rc = RTFileLock(File, fLockOld, offLock, cbLock);
515 if (RT_SUCCESS(rc))
516 return VERR_FILE_LOCK_VIOLATION;
517 else
518 return VERR_FILE_LOCK_LOST;
519}
520
521
522RTR3DECL(int) RTFileUnlock(RTFILE File, int64_t offLock, uint64_t cbLock)
523{
524 Assert(offLock >= 0);
525
526 if (UnlockFile((HANDLE)File, LOW_DWORD(offLock), HIGH_DWORD(offLock), LOW_DWORD(cbLock), HIGH_DWORD(cbLock)))
527 return VINF_SUCCESS;
528
529 return RTErrConvertFromWin32(GetLastError());
530}
531
532
533
534RTR3DECL(int) RTFileQueryInfo(RTFILE File, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs)
535{
536 /*
537 * Validate input.
538 */
539 if (File == NIL_RTFILE)
540 {
541 AssertMsgFailed(("Invalid File=%RTfile\n", File));
542 return VERR_INVALID_PARAMETER;
543 }
544 if (!pObjInfo)
545 {
546 AssertMsgFailed(("Invalid pObjInfo=%p\n", pObjInfo));
547 return VERR_INVALID_PARAMETER;
548 }
549 if ( enmAdditionalAttribs < RTFSOBJATTRADD_NOTHING
550 || enmAdditionalAttribs > RTFSOBJATTRADD_LAST)
551 {
552 AssertMsgFailed(("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs));
553 return VERR_INVALID_PARAMETER;
554 }
555
556 /*
557 * Query file info.
558 */
559 BY_HANDLE_FILE_INFORMATION Data;
560 if (!GetFileInformationByHandle((HANDLE)File, &Data))
561 return RTErrConvertFromWin32(GetLastError());
562
563 /*
564 * Setup the returned data.
565 */
566 pObjInfo->cbObject = ((uint64_t)Data.nFileSizeHigh << 32)
567 | (uint64_t)Data.nFileSizeLow;
568 pObjInfo->cbAllocated = pObjInfo->cbObject;
569
570 Assert(sizeof(uint64_t) == sizeof(Data.ftCreationTime));
571 RTTimeSpecSetNtTime(&pObjInfo->BirthTime, *(uint64_t *)&Data.ftCreationTime);
572 RTTimeSpecSetNtTime(&pObjInfo->AccessTime, *(uint64_t *)&Data.ftLastAccessTime);
573 RTTimeSpecSetNtTime(&pObjInfo->ModificationTime, *(uint64_t *)&Data.ftLastWriteTime);
574 pObjInfo->ChangeTime = pObjInfo->ModificationTime;
575
576 pObjInfo->Attr.fMode = rtFsModeFromDos((Data.dwFileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT, "", 0);
577
578 /*
579 * Requested attributes (we cannot provide anything actually).
580 */
581 switch (enmAdditionalAttribs)
582 {
583 case RTFSOBJATTRADD_EASIZE:
584 pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_EASIZE;
585 pObjInfo->Attr.u.EASize.cb = 0;
586 break;
587
588 case RTFSOBJATTRADD_UNIX:
589 pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX;
590 pObjInfo->Attr.u.Unix.uid = ~0U;
591 pObjInfo->Attr.u.Unix.gid = ~0U;
592 pObjInfo->Attr.u.Unix.cHardlinks = Data.nNumberOfLinks ? Data.nNumberOfLinks : 1;
593 pObjInfo->Attr.u.Unix.INodeIdDevice = 0;
594 pObjInfo->Attr.u.Unix.INodeId = 0;
595 pObjInfo->Attr.u.Unix.fFlags = 0;
596 pObjInfo->Attr.u.Unix.GenerationId = 0;
597 pObjInfo->Attr.u.Unix.Device = 0;
598 break;
599
600 case RTFSOBJATTRADD_NOTHING:
601 pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_NOTHING;
602 break;
603
604 default:
605 AssertMsgFailed(("Impossible!\n"));
606 return VERR_INTERNAL_ERROR;
607 }
608
609 return VINF_SUCCESS;
610}
611
612
613RTR3DECL(int) RTFileSetTimes(RTFILE File, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
614 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
615{
616 if (!pAccessTime && !pModificationTime && !pBirthTime)
617 return VINF_SUCCESS; /* NOP */
618
619 FILETIME CreationTimeFT;
620 PFILETIME pCreationTimeFT = NULL;
621 if (pBirthTime)
622 pCreationTimeFT = RTTimeSpecGetNtFileTime(pBirthTime, &CreationTimeFT);
623
624 FILETIME LastAccessTimeFT;
625 PFILETIME pLastAccessTimeFT = NULL;
626 if (pAccessTime)
627 pLastAccessTimeFT = RTTimeSpecGetNtFileTime(pAccessTime, &LastAccessTimeFT);
628
629 FILETIME LastWriteTimeFT;
630 PFILETIME pLastWriteTimeFT = NULL;
631 if (pModificationTime)
632 pLastWriteTimeFT = RTTimeSpecGetNtFileTime(pModificationTime, &LastWriteTimeFT);
633
634 int rc = VINF_SUCCESS;
635 if (!SetFileTime((HANDLE)File, pCreationTimeFT, pLastAccessTimeFT, pLastWriteTimeFT))
636 {
637 DWORD Err = GetLastError();
638 rc = RTErrConvertFromWin32(Err);
639 Log(("RTFileSetTimes(%RTfile, %p, %p, %p, %p): SetFileTime failed with lasterr %d (%Vrc)\n",
640 File, pAccessTime, pModificationTime, pChangeTime, pBirthTime, Err, rc));
641 }
642 return rc;
643}
644
645
646RTR3DECL(int) RTFileSetMode(RTFILE File, RTFMODE fMode)
647{
648 /** @todo darn. this needs a full path; probably must be done if the file is closed
649 * It's quite possible that there is an NT API for this. NtSetInformationFile() for instance. */
650 return VINF_SUCCESS;
651}
652
653
654RTR3DECL(int) RTFileDelete(const char *pszFilename)
655{
656#ifdef RT_DONT_CONVERT_FILENAMES
657 if (DeleteFile(pszFilename))
658 return VINF_SUCCESS;
659 return RTErrConvertFromWin32(GetLastError());
660
661#else
662 PRTUTF16 pwszFilename;
663 int rc = RTStrToUtf16(pszFilename, &pwszFilename);
664 if (RT_SUCCESS(rc))
665 {
666 if (!DeleteFileW(pwszFilename))
667 rc = RTErrConvertFromWin32(GetLastError());
668 RTUtf16Free(pwszFilename);
669 }
670
671 return rc;
672#endif
673}
674
675
676RTDECL(int) RTFileRename(const char *pszSrc, const char *pszDst, unsigned fRename)
677{
678 /*
679 * Validate input.
680 */
681 AssertMsgReturn(VALID_PTR(pszSrc), ("%p\n", pszSrc), VERR_INVALID_POINTER);
682 AssertMsgReturn(VALID_PTR(pszDst), ("%p\n", pszDst), VERR_INVALID_POINTER);
683 AssertMsgReturn(!(fRename & ~RTPATHRENAME_FLAGS_REPLACE), ("%#x\n", fRename), VERR_INVALID_PARAMETER);
684
685 /*
686 * Hand it on to the worker.
687 */
688 int rc = rtPathWin32MoveRename(pszSrc, pszDst,
689 fRename & RTPATHRENAME_FLAGS_REPLACE ? MOVEFILE_REPLACE_EXISTING : 0,
690 RTFS_TYPE_FILE);
691
692 LogFlow(("RTFileMove(%p:{%s}, %p:{%s}, %#x): returns %Rrc\n",
693 pszSrc, pszSrc, pszDst, pszDst, fRename, rc));
694 return rc;
695
696}
697
698
699RTDECL(int) RTFileMove(const char *pszSrc, const char *pszDst, unsigned fMove)
700{
701 /*
702 * Validate input.
703 */
704 AssertMsgReturn(VALID_PTR(pszSrc), ("%p\n", pszSrc), VERR_INVALID_POINTER);
705 AssertMsgReturn(VALID_PTR(pszDst), ("%p\n", pszDst), VERR_INVALID_POINTER);
706 AssertMsgReturn(!(fMove & ~RTFILEMOVE_FLAGS_REPLACE), ("%#x\n", fMove), VERR_INVALID_PARAMETER);
707
708 /*
709 * Hand it on to the worker.
710 */
711 int rc = rtPathWin32MoveRename(pszSrc, pszDst,
712 fMove & RTFILEMOVE_FLAGS_REPLACE
713 ? MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING
714 : MOVEFILE_COPY_ALLOWED,
715 RTFS_TYPE_FILE);
716
717 LogFlow(("RTFileMove(%p:{%s}, %p:{%s}, %#x): returns %Rrc\n",
718 pszSrc, pszSrc, pszDst, pszDst, fMove, rc));
719 return rc;
720}
721
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette