Qt 4.8
qfilesystemengine_win.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qfilesystemengine_p.h"
43 
44 #define _POSIX_
45 #include "qplatformdefs.h"
46 #include "qabstractfileengine.h"
47 #include "private/qfsfileengine_p.h"
48 #include <private/qsystemlibrary_p.h>
49 #include <qdebug.h>
50 
51 #include "qfile.h"
52 #include "qdir.h"
53 #include "private/qmutexpool_p.h"
54 #include "qvarlengtharray.h"
55 #include "qdatetime.h"
56 #include "qt_windows.h"
57 
58 #if !defined(Q_OS_WINCE)
59 # include <sys/types.h>
60 # include <direct.h>
61 # include <winioctl.h>
62 #else
63 # include <types.h>
64 #endif
65 #include <objbase.h>
66 #include <shlobj.h>
67 #include <initguid.h>
68 #include <accctrl.h>
69 #include <ctype.h>
70 #include <limits.h>
71 #define SECURITY_WIN32
72 #include <security.h>
73 
74 #ifndef SPI_GETPLATFORMTYPE
75 #define SPI_GETPLATFORMTYPE 257
76 #endif
77 
78 #ifndef PATH_MAX
79 #define PATH_MAX FILENAME_MAX
80 #endif
81 
82 #ifndef _INTPTR_T_DEFINED
83 #ifdef _WIN64
84 typedef __int64 intptr_t;
85 #else
86 #ifdef _W64
87 typedef _W64 int intptr_t;
88 #else
89 typedef INT_PTR intptr_t;
90 #endif
91 #endif
92 #define _INTPTR_T_DEFINED
93 #endif
94 
95 #ifndef INVALID_FILE_ATTRIBUTES
96 # define INVALID_FILE_ATTRIBUTES (DWORD (-1))
97 #endif
98 
99 #if !defined(Q_OS_WINCE)
100 # if !defined(REPARSE_DATA_BUFFER_HEADER_SIZE)
101 typedef struct _REPARSE_DATA_BUFFER {
102  ULONG ReparseTag;
103  USHORT ReparseDataLength;
104  USHORT Reserved;
105  union {
106  struct {
107  USHORT SubstituteNameOffset;
108  USHORT SubstituteNameLength;
109  USHORT PrintNameOffset;
110  USHORT PrintNameLength;
111  ULONG Flags;
112  WCHAR PathBuffer[1];
113  } SymbolicLinkReparseBuffer;
114  struct {
115  USHORT SubstituteNameOffset;
116  USHORT SubstituteNameLength;
117  USHORT PrintNameOffset;
118  USHORT PrintNameLength;
119  WCHAR PathBuffer[1];
120  } MountPointReparseBuffer;
121  struct {
122  UCHAR DataBuffer[1];
123  } GenericReparseBuffer;
124  };
125 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
126 # define REPARSE_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer)
127 # endif // !defined(REPARSE_DATA_BUFFER_HEADER_SIZE)
128 
129 # ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE
130 # define MAXIMUM_REPARSE_DATA_BUFFER_SIZE 16384
131 # endif
132 # ifndef IO_REPARSE_TAG_SYMLINK
133 # define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
134 # endif
135 # ifndef FSCTL_GET_REPARSE_POINT
136 # define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
137 # endif
138 #endif // !defined(Q_OS_WINCE)
139 
141 
143 
144 #if defined(Q_OS_WINCE)
146 // As none of the functions we try to resolve do exist on Windows CE
147 // we use QT_NO_LIBRARY to shorten everything up a little bit.
148 #define QT_NO_LIBRARY 1
149 #endif
150 
151 #if !defined(QT_NO_LIBRARY)
153 typedef DWORD (WINAPI *PtrGetNamedSecurityInfoW)(LPWSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION, PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*);
154 static PtrGetNamedSecurityInfoW ptrGetNamedSecurityInfoW = 0;
155 typedef BOOL (WINAPI *PtrLookupAccountSidW)(LPCWSTR, PSID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE);
156 static PtrLookupAccountSidW ptrLookupAccountSidW = 0;
157 typedef VOID (WINAPI *PtrBuildTrusteeWithSidW)(PTRUSTEE_W, PSID);
158 static PtrBuildTrusteeWithSidW ptrBuildTrusteeWithSidW = 0;
159 typedef DWORD (WINAPI *PtrGetEffectiveRightsFromAclW)(PACL, PTRUSTEE_W, OUT PACCESS_MASK);
160 static PtrGetEffectiveRightsFromAclW ptrGetEffectiveRightsFromAclW = 0;
161 typedef BOOL (WINAPI *PtrGetUserProfileDirectoryW)(HANDLE, LPWSTR, LPDWORD);
162 static PtrGetUserProfileDirectoryW ptrGetUserProfileDirectoryW = 0;
163 typedef BOOL (WINAPI *PtrGetVolumePathNamesForVolumeNameW)(LPCWSTR,LPWSTR,DWORD,PDWORD);
164 static PtrGetVolumePathNamesForVolumeNameW ptrGetVolumePathNamesForVolumeNameW = 0;
166 
167 static TRUSTEE_W currentUserTrusteeW;
168 static TRUSTEE_W worldTrusteeW;
169 static PSID currentUserSID = 0;
170 static PSID worldSID = 0;
171 
172 /*
173  Deletes the allocated SIDs during global static cleanup
174 */
175 class SidCleanup
176 {
177 public:
178  ~SidCleanup();
179 };
180 
181 SidCleanup::~SidCleanup()
182 {
183  qFree(currentUserSID);
184  currentUserSID = 0;
185 
186  // worldSID was allocated with AllocateAndInitializeSid so it needs to be freed with FreeSid
187  if (worldSID) {
188  ::FreeSid(worldSID);
189  worldSID = 0;
190  }
191 }
192 
193 Q_GLOBAL_STATIC(SidCleanup, initSidCleanup)
194 
195 static void resolveLibs()
196 {
197  static bool triedResolve = false;
198  if (!triedResolve) {
199  // need to resolve the security info functions
200 
201  // protect initialization
202 #ifndef QT_NO_THREAD
203  QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
204  // check triedResolve again, since another thread may have already
205  // done the initialization
206  if (triedResolve) {
207  // another thread did initialize the security function pointers,
208  // so we shouldn't do it again.
209  return;
210  }
211 #endif
212 
213 #if !defined(Q_OS_WINCE)
214  QSystemLibrary advapi32(QLatin1String("advapi32"));
215  if (advapi32.load()) {
216  ptrGetNamedSecurityInfoW = (PtrGetNamedSecurityInfoW)advapi32.resolve("GetNamedSecurityInfoW");
217  ptrLookupAccountSidW = (PtrLookupAccountSidW)advapi32.resolve("LookupAccountSidW");
218  ptrBuildTrusteeWithSidW = (PtrBuildTrusteeWithSidW)advapi32.resolve("BuildTrusteeWithSidW");
219  ptrGetEffectiveRightsFromAclW = (PtrGetEffectiveRightsFromAclW)advapi32.resolve("GetEffectiveRightsFromAclW");
220  }
221  if (ptrBuildTrusteeWithSidW) {
222  // Create TRUSTEE for current user
223  HANDLE hnd = ::GetCurrentProcess();
224  HANDLE token = 0;
225  initSidCleanup();
226  if (::OpenProcessToken(hnd, TOKEN_QUERY, &token)) {
227  DWORD retsize = 0;
228  // GetTokenInformation requires a buffer big enough for the TOKEN_USER struct and
229  // the SID struct. Since the SID struct can have variable number of subauthorities
230  // tacked at the end, its size is variable. Obtain the required size by first
231  // doing a dummy GetTokenInformation call.
232  ::GetTokenInformation(token, TokenUser, 0, 0, &retsize);
233  if (retsize) {
234  void *tokenBuffer = qMalloc(retsize);
235  if (::GetTokenInformation(token, TokenUser, tokenBuffer, retsize, &retsize)) {
236  PSID tokenSid = reinterpret_cast<PTOKEN_USER>(tokenBuffer)->User.Sid;
237  DWORD sidLen = ::GetLengthSid(tokenSid);
238  currentUserSID = reinterpret_cast<PSID>(qMalloc(sidLen));
239  if (::CopySid(sidLen, currentUserSID, tokenSid))
240  ptrBuildTrusteeWithSidW(&currentUserTrusteeW, currentUserSID);
241  }
242  qFree(tokenBuffer);
243  }
244  ::CloseHandle(token);
245  }
246 
247  typedef BOOL (WINAPI *PtrAllocateAndInitializeSid)(PSID_IDENTIFIER_AUTHORITY, BYTE, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, PSID*);
248  PtrAllocateAndInitializeSid ptrAllocateAndInitializeSid = (PtrAllocateAndInitializeSid)advapi32.resolve("AllocateAndInitializeSid");
249  if (ptrAllocateAndInitializeSid) {
250  // Create TRUSTEE for Everyone (World)
251  SID_IDENTIFIER_AUTHORITY worldAuth = { SECURITY_WORLD_SID_AUTHORITY };
252  if (ptrAllocateAndInitializeSid(&worldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &worldSID))
253  ptrBuildTrusteeWithSidW(&worldTrusteeW, worldSID);
254  }
255  }
256 
257  QSystemLibrary userenv(QLatin1String("userenv"));
258  if (userenv.load())
259  ptrGetUserProfileDirectoryW = (PtrGetUserProfileDirectoryW)userenv.resolve("GetUserProfileDirectoryW");
260 
261  QSystemLibrary kernel32(QLatin1String("kernel32"));
262  if (kernel32.load())
263  ptrGetVolumePathNamesForVolumeNameW = (PtrGetVolumePathNamesForVolumeNameW)kernel32.resolve("GetVolumePathNamesForVolumeNameW");
264 #endif
265  triedResolve = true;
266  }
267 }
268 #endif // QT_NO_LIBRARY
269 
270 typedef DWORD (WINAPI *PtrNetShareEnum)(LPWSTR, DWORD, LPBYTE*, DWORD, LPDWORD, LPDWORD, LPDWORD);
272 typedef DWORD (WINAPI *PtrNetApiBufferFree)(LPVOID);
274 typedef struct _SHARE_INFO_1 {
275  LPWSTR shi1_netname;
276  DWORD shi1_type;
277  LPWSTR shi1_remark;
278 } SHARE_INFO_1;
279 
280 
281 static bool resolveUNCLibs()
282 {
283  static bool triedResolve = false;
284  if (!triedResolve) {
285 #ifndef QT_NO_THREAD
286  QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
287  if (triedResolve) {
289  }
290 #endif
291 
292 #if !defined(Q_OS_WINCE)
293  QSystemLibrary netapi32(QLatin1String("Netapi32"));
294  if (netapi32.load()) {
295  ptrNetShareEnum = (PtrNetShareEnum)netapi32.resolve("NetShareEnum");
296  ptrNetApiBufferFree = (PtrNetApiBufferFree)netapi32.resolve("NetApiBufferFree");
297  }
298 #endif
299  triedResolve = true;
300  }
302 }
303 
305 {
306  QString result;
307 #if !defined(Q_OS_WINCE)
308  HANDLE handle = CreateFile((wchar_t*)link.nativeFilePath().utf16(),
309  FILE_READ_EA,
310  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
311  0,
312  OPEN_EXISTING,
313  FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
314  0);
315  if (handle != INVALID_HANDLE_VALUE) {
316  DWORD bufsize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
317  REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER*)qMalloc(bufsize);
318  DWORD retsize = 0;
319  if (::DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, 0, 0, rdb, bufsize, &retsize, 0)) {
320  if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
321  int length = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
322  int offset = rdb->MountPointReparseBuffer.SubstituteNameOffset / sizeof(wchar_t);
323  const wchar_t* PathBuffer = &rdb->MountPointReparseBuffer.PathBuffer[offset];
324  result = QString::fromWCharArray(PathBuffer, length);
325  } else if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
326  int length = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
327  int offset = rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t);
328  const wchar_t* PathBuffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[offset];
329  result = QString::fromWCharArray(PathBuffer, length);
330  }
331  // cut-off "//?/" and "/??/"
332  if (result.size() > 4 && result.at(0) == QLatin1Char('\\') && result.at(2) == QLatin1Char('?') && result.at(3) == QLatin1Char('\\'))
333  result = result.mid(4);
334  }
335  qFree(rdb);
336  CloseHandle(handle);
337 
338 #if !defined(QT_NO_LIBRARY)
339  resolveLibs();
340  if (ptrGetVolumePathNamesForVolumeNameW) {
341  QRegExp matchVolName(QLatin1String("^Volume\\{([a-z]|[0-9]|-)+\\}\\\\"), Qt::CaseInsensitive);
342  if(matchVolName.indexIn(result) == 0) {
343  DWORD len;
344  wchar_t buffer[MAX_PATH];
345  QString volumeName = result.mid(0, matchVolName.matchedLength()).prepend(QLatin1String("\\\\?\\"));
346  if(ptrGetVolumePathNamesForVolumeNameW((wchar_t*)volumeName.utf16(), buffer, MAX_PATH, &len) != 0)
347  result.replace(0,matchVolName.matchedLength(), QString::fromWCharArray(buffer));
348  }
349  }
350 #endif
351  }
352 #else
353  Q_UNUSED(link);
354 #endif // Q_OS_WINCE
355  return result;
356 }
357 
358 static QString readLink(const QFileSystemEntry &link)
359 {
360 #if !defined(Q_OS_WINCE)
361 #if !defined(QT_NO_LIBRARY) && !defined(Q_CC_MWERKS)
362  QString ret;
363 
364  bool neededCoInit = false;
365  IShellLink *psl; // pointer to IShellLink i/f
366  WIN32_FIND_DATA wfd;
367  wchar_t szGotPath[MAX_PATH];
368 
369  // Get pointer to the IShellLink interface.
370  HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *)&psl);
371 
372  if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized
373  neededCoInit = true;
374  CoInitialize(NULL);
375  hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
376  IID_IShellLink, (LPVOID *)&psl);
377  }
378  if (SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface.
379  IPersistFile *ppf;
380  hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
381  if (SUCCEEDED(hres)) {
382  hres = ppf->Load((LPOLESTR)link.nativeFilePath().utf16(), STGM_READ);
383  //The original path of the link is retrieved. If the file/folder
384  //was moved, the return value still have the old path.
385  if (SUCCEEDED(hres)) {
386  if (psl->GetPath(szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY) == NOERROR)
387  ret = QString::fromWCharArray(szGotPath);
388  }
389  ppf->Release();
390  }
391  psl->Release();
392  }
393  if (neededCoInit)
394  CoUninitialize();
395 
396  return ret;
397 #else
398  Q_UNUSED(link);
399  return QString();
400 #endif // QT_NO_LIBRARY
401 #else
402  wchar_t target[MAX_PATH];
403  QString result;
404  if (SHGetShortcutTarget((wchar_t*)QFileInfo(link.filePath()).absoluteFilePath().replace(QLatin1Char('/'),QLatin1Char('\\')).utf16(), target, MAX_PATH)) {
405  result = QString::fromWCharArray(target);
406  if (result.startsWith(QLatin1Char('"')))
407  result.remove(0,1);
408  if (result.endsWith(QLatin1Char('"')))
409  result.remove(result.size()-1,1);
410  }
411  return result;
412 #endif // Q_OS_WINCE
413 }
414 
415 static bool uncShareExists(const QString &server)
416 {
417  // This code assumes the UNC path is always like \\?\UNC\server...
418  QStringList parts = server.split(QLatin1Char('\\'), QString::SkipEmptyParts);
419  if (parts.count() >= 3) {
420  QStringList shares;
421  if (QFileSystemEngine::uncListSharesOnServer(QLatin1String("\\\\") + parts.at(2), &shares))
422  return parts.count() >= 4 ? shares.contains(parts.at(3), Qt::CaseInsensitive) : true;
423  }
424  return false;
425 }
426 
427 static inline bool getFindData(QString path, WIN32_FIND_DATA &findData)
428 {
429  // path should not end with a trailing slash
430  while (path.endsWith(QLatin1Char('\\')))
431  path.chop(1);
432 
433  // can't handle drives
434  if (!path.endsWith(QLatin1Char(':'))) {
435  HANDLE hFind = ::FindFirstFile((wchar_t*)path.utf16(), &findData);
436  if (hFind != INVALID_HANDLE_VALUE) {
437  ::FindClose(hFind);
438  return true;
439  }
440  }
441 
442  return false;
443 }
444 
446 {
447  if (resolveUNCLibs()) {
448  SHARE_INFO_1 *BufPtr, *p;
449  DWORD res;
450  DWORD er = 0, tr = 0, resume = 0, i;
451  do {
452  res = ptrNetShareEnum((wchar_t*)server.utf16(), 1, (LPBYTE *)&BufPtr, DWORD(-1), &er, &tr, &resume);
453  if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) {
454  p = BufPtr;
455  for (i = 1; i <= er; ++i) {
456  if (list && p->shi1_type == 0)
458  p++;
459  }
460  }
461  ptrNetApiBufferFree(BufPtr);
462  } while (res == ERROR_MORE_DATA);
463  return res == ERROR_SUCCESS;
464  }
465  return false;
466 }
467 
469 {
470  data.size_ = 0;
471  data.fileAttribute_ = 0;
472  data.creationTime_ = FILETIME();
473  data.lastAccessTime_ = FILETIME();
474  data.lastWriteTime_ = FILETIME();
475 }
476 
478 {
479  return false;
480 }
481 
482 //static
485 {
488 
489  QString ret;
490  if (data.isLnkFile())
491  ret = readLink(link);
492  else if (data.isLink())
493  ret = readSymLink(link);
494  return QFileSystemEntry(ret);
495 }
496 
497 //static
499 {
502 
503  if (data.exists())
504  return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath()));
505  else
506  return QFileSystemEntry();
507 }
508 
509 //static
511 {
512  // can be //server or //server/share
513  QString absPath;
514 #if !defined(Q_OS_WINCE)
515  QVarLengthArray<wchar_t, MAX_PATH> buf(qMax(MAX_PATH, path.size() + 1));
516  wchar_t *fileName = 0;
517  DWORD retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName);
518  if (retLen > (DWORD)buf.size()) {
519  buf.resize(retLen);
520  retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName);
521  }
522  if (retLen != 0)
523  absPath = QString::fromWCharArray(buf.data(), retLen);
524 #else
525  if (path.startsWith(QLatin1Char('/')) || path.startsWith(QLatin1Char('\\')))
526  absPath = QDir::toNativeSeparators(path);
527  else
528  absPath = QDir::toNativeSeparators(QDir::cleanPath(qfsPrivateCurrentDir + QLatin1Char('/') + path));
529 #endif
530  // This is really ugly, but GetFullPathName strips off whitespace at the end.
531  // If you for instance write ". " in the lineedit of QFileDialog,
532  // (which is an invalid filename) this function will strip the space off and viola,
533  // the file is later reported as existing. Therefore, we re-add the whitespace that
534  // was at the end of path in order to keep the filename invalid.
535  if (!path.isEmpty() && path.at(path.size() - 1) == QLatin1Char(' '))
536  absPath.append(QLatin1Char(' '));
537  return absPath;
538 }
539 
540 //static
542 {
543  QString ret;
544 
545  if (!entry.isRelative()) {
546 #if !defined(Q_OS_WINCE)
547  if (entry.isAbsolute() && entry.isClean()) {
548  ret = entry.filePath();
549  } else {
550  ret = QDir::fromNativeSeparators(nativeAbsoluteFilePath(entry.filePath()));
551  }
552 #else
553  ret = entry.filePath();
554 #endif
555  } else {
556  ret = QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + entry.filePath());
557  }
558 
559  // The path should be absolute at this point.
560  // From the docs :
561  // Absolute paths begin with the directory separator "/"
562  // (optionally preceded by a drive specification under Windows).
563  if (ret.at(0) != QLatin1Char('/')) {
564  Q_ASSERT(ret.length() >= 2);
565  Q_ASSERT(ret.at(0).isLetter());
566  Q_ASSERT(ret.at(1) == QLatin1Char(':'));
567 
568  // Force uppercase drive letters.
569  ret[0] = ret.at(0).toUpper();
570  }
572 }
573 
574 //static
576 {
577  QString name;
578 #if !defined(QT_NO_LIBRARY)
579  extern int qt_ntfs_permission_lookup;
580  if((qt_ntfs_permission_lookup > 0) && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)) {
581  resolveLibs();
582  if (ptrGetNamedSecurityInfoW && ptrLookupAccountSidW) {
583  PSID pOwner = 0;
584  PSECURITY_DESCRIPTOR pSD;
585  if (ptrGetNamedSecurityInfoW((wchar_t*)entry.nativeFilePath().utf16(), SE_FILE_OBJECT,
586  own == QAbstractFileEngine::OwnerGroup ? GROUP_SECURITY_INFORMATION : OWNER_SECURITY_INFORMATION,
587  own == QAbstractFileEngine::OwnerUser ? &pOwner : 0, own == QAbstractFileEngine::OwnerGroup ? &pOwner : 0,
588  0, 0, &pSD) == ERROR_SUCCESS) {
589  DWORD lowner = 64;
590  DWORD ldomain = 64;
592  QVarLengthArray<wchar_t, 64> domain(ldomain);
593  SID_NAME_USE use = SidTypeUnknown;
594  // First call, to determine size of the strings (with '\0').
595  if (!ptrLookupAccountSidW(NULL, pOwner, (LPWSTR)owner.data(), &lowner,
596  (LPWSTR)domain.data(), &ldomain, (SID_NAME_USE*)&use)) {
597  if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
598  if (lowner > (DWORD)owner.size())
599  owner.resize(lowner);
600  if (ldomain > (DWORD)domain.size())
601  domain.resize(ldomain);
602  // Second call, try on resized buf-s
603  if (!ptrLookupAccountSidW(NULL, pOwner, (LPWSTR)owner.data(), &lowner,
604  (LPWSTR)domain.data(), &ldomain, (SID_NAME_USE*)&use)) {
605  lowner = 0;
606  }
607  } else {
608  lowner = 0;
609  }
610  }
611  if (lowner != 0)
612  name = QString::fromWCharArray(owner.data());
613  LocalFree(pSD);
614  }
615  }
616  }
617 #else
618  Q_UNUSED(entry);
619  Q_UNUSED(own);
620 #endif
621  return name;
622 }
623 
624 //static
626  QFileSystemMetaData::MetaDataFlags what)
627 {
628 #if !defined(QT_NO_LIBRARY)
630  resolveLibs();
631  if(ptrGetNamedSecurityInfoW && ptrBuildTrusteeWithSidW && ptrGetEffectiveRightsFromAclW) {
632  enum { ReadMask = 0x00000001, WriteMask = 0x00000002, ExecMask = 0x00000020 };
633 
634  QString fname = entry.filePath();
635  PSID pOwner = 0;
636  PSID pGroup = 0;
637  PACL pDacl;
638  PSECURITY_DESCRIPTOR pSD;
639  DWORD res = ptrGetNamedSecurityInfoW((wchar_t*)fname.utf16(), SE_FILE_OBJECT,
640  OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
641  &pOwner, &pGroup, &pDacl, 0, &pSD);
642  if(res == ERROR_SUCCESS) {
643  ACCESS_MASK access_mask;
644  TRUSTEE_W trustee;
645  if (what & QFileSystemMetaData::UserPermissions) { // user
647  if(ptrGetEffectiveRightsFromAclW(pDacl, &currentUserTrusteeW, &access_mask) != ERROR_SUCCESS)
648  access_mask = (ACCESS_MASK)-1;
649  if(access_mask & ReadMask)
651  if(access_mask & WriteMask)
653  if(access_mask & ExecMask)
655  }
656  if (what & QFileSystemMetaData::OwnerPermissions) { // owner
658  ptrBuildTrusteeWithSidW(&trustee, pOwner);
659  if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS)
660  access_mask = (ACCESS_MASK)-1;
661  if(access_mask & ReadMask)
663  if(access_mask & WriteMask)
665  if(access_mask & ExecMask)
667  }
668  if (what & QFileSystemMetaData::GroupPermissions) { // group
670  ptrBuildTrusteeWithSidW(&trustee, pGroup);
671  if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS)
672  access_mask = (ACCESS_MASK)-1;
673  if(access_mask & ReadMask)
675  if(access_mask & WriteMask)
677  if(access_mask & ExecMask)
679  }
680  if (what & QFileSystemMetaData::OtherPermissions) { // other (world)
682  if(ptrGetEffectiveRightsFromAclW(pDacl, &worldTrusteeW, &access_mask) != ERROR_SUCCESS)
683  access_mask = (ACCESS_MASK)-1; // ###
684  if(access_mask & ReadMask)
686  if(access_mask & WriteMask)
688  if(access_mask & ExecMask)
690  }
691  LocalFree(pSD);
692  }
693  }
694  } else
695 #endif
696  {
697  //### what to do with permissions if we don't use NTFS
698  // for now just add all permissions and what about exe missions ??
699  // also qt_ntfs_permission_lookup is now not set by default ... should it ?
703 
704  if (!(data.fileAttribute_ & FILE_ATTRIBUTE_READONLY)) {
708  }
709 
710  QString fname = entry.filePath();
711  QString ext = fname.right(4).toLower();
712  if (data.isDirectory() ||
713  ext == QLatin1String(".exe") || ext == QLatin1String(".com") || ext == QLatin1String(".bat") ||
714  ext == QLatin1String(".pif") || ext == QLatin1String(".cmd")) {
717  }
720  // calculate user permissions
722  if (::_waccess((wchar_t*)entry.nativeFilePath().utf16(), R_OK) == 0)
725  }
727  if (::_waccess((wchar_t*)entry.nativeFilePath().utf16(), W_OK) == 0)
730  }
731  }
732 
733  return data.hasFlags(what);
734 }
735 
737 {
738  bool entryExists = false;
739  DWORD fileAttrib = 0;
740 #if !defined(Q_OS_WINCE)
741  if (fname.isDriveRoot()) {
742  // a valid drive ??
743  DWORD drivesBitmask = ::GetLogicalDrives();
744  int drivebit = 1 << (fname.filePath().at(0).toUpper().unicode() - QLatin1Char('A').unicode());
745  if (drivesBitmask & drivebit) {
746  fileAttrib = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM;
747  entryExists = true;
748  }
749  } else {
750 #endif
751  const QString &path = fname.nativeFilePath();
752  bool is_dir = false;
753  if (path.startsWith(QLatin1String("\\\\?\\UNC"))) {
754  // UNC - stat doesn't work for all cases (Windows bug)
755  int s = path.indexOf(path.at(0),7);
756  if (s > 0) {
757  // "\\?\UNC\server\..."
758  s = path.indexOf(path.at(0),s+1);
759  if (s > 0) {
760  // "\\?\UNC\server\share\..."
761  if (s == path.size() - 1) {
762  // "\\?\UNC\server\share\"
763  is_dir = true;
764  } else {
765  // "\\?\UNC\server\share\notfound"
766  }
767  } else {
768  // "\\?\UNC\server\share"
769  is_dir = true;
770  }
771  } else {
772  // "\\?\UNC\server"
773  is_dir = true;
774  }
775  }
776  if (is_dir && uncShareExists(path)) {
777  // looks like a UNC dir, is a dir.
778  fileAttrib = FILE_ATTRIBUTE_DIRECTORY;
779  entryExists = true;
780  }
781 #if !defined(Q_OS_WINCE)
782  }
783 #endif
784  if (entryExists)
785  data.fillFromFileAttribute(fileAttrib);
786  return entryExists;
787 }
788 
789 static bool tryFindFallback(const QFileSystemEntry &fname, QFileSystemMetaData &data)
790 {
791  bool filledData = false;
792  // This assumes the last call to a Windows API failed.
793  int errorCode = GetLastError();
794  if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) {
795  WIN32_FIND_DATA findData;
796  if (getFindData(fname.nativeFilePath(), findData)
797  && findData.dwFileAttributes != INVALID_FILE_ATTRIBUTES) {
798  data.fillFromFindData(findData, true, fname.isDriveRoot());
799  filledData = true;
800  }
801  }
802  return filledData;
803 }
804 
805 #if !defined(Q_OS_WINCE)
806 //static
808  QFileSystemMetaData::MetaDataFlags what)
809 {
810  HANDLE fHandle = (HANDLE)_get_osfhandle(fd);
811  if (fHandle != INVALID_HANDLE_VALUE) {
812  return fillMetaData(fHandle, data, what);
813  }
814  return false;
815 }
816 #endif
817 
818 //static
820  QFileSystemMetaData::MetaDataFlags what)
821 {
822  data.entryFlags &= ~what;
823  clearWinStatData(data);
824  BY_HANDLE_FILE_INFORMATION fileInfo;
826  if (GetFileInformationByHandle(fHandle , &fileInfo)) {
827  data.fillFromFindInfo(fileInfo);
828  }
829  SetErrorMode(oldmode);
830  return data.hasFlags(what);
831 }
832 
833 static bool isDirPath(const QString &dirPath, bool *existed);
834 
835 //static
837  QFileSystemMetaData::MetaDataFlags what)
838 {
840  data.entryFlags &= ~what;
841 
842  QFileSystemEntry fname;
844  // Check for ".lnk": Directories named ".lnk" should be skipped, corrupted
845  // link files should still be detected as links.
846  const QString origFilePath = entry.filePath();
847  if (origFilePath.endsWith(QLatin1String(".lnk")) && !isDirPath(origFilePath, 0)) {
849  fname = QFileSystemEntry(readLink(entry));
850  } else {
851  fname = entry;
852  }
853 
854  if (fname.isEmpty()) {
855  data.knownFlagsMask |= what;
856  clearWinStatData(data);
857  return false;
858  }
859 
862  clearWinStatData(data);
863  WIN32_FIND_DATA findData;
864  // The memory structure for WIN32_FIND_DATA is same as WIN32_FILE_ATTRIBUTE_DATA
865  // for all members used by fillFindData().
866  bool ok = ::GetFileAttributesEx((wchar_t*)fname.nativeFilePath().utf16(), GetFileExInfoStandard,
867  reinterpret_cast<WIN32_FILE_ATTRIBUTE_DATA *>(&findData));
868  if (ok) {
869  data.fillFromFindData(findData, false, fname.isDriveRoot());
870  } else {
871  if (!tryFindFallback(fname, data))
872  tryDriveUNCFallback(fname, data);
873  }
874  SetErrorMode(oldmode);
875  }
876 
878  fillPermissions(fname, data, what);
879  if ((what & QFileSystemMetaData::LinkType)
880  && data.missingFlags(QFileSystemMetaData::LinkType)) {
882  if (data.fileAttribute_ & FILE_ATTRIBUTE_REPARSE_POINT) {
883  WIN32_FIND_DATA findData;
884  if (getFindData(fname.nativeFilePath(), findData))
885  data.fillFromFindData(findData, true);
886  }
887  }
888  data.knownFlagsMask |= what;
889  return data.hasFlags(what);
890 }
891 
892 static inline bool mkDir(const QString &path)
893 {
894 #if defined(Q_OS_WINCE)
895  // Unfortunately CreateDirectory returns true for paths longer than
896  // 256, but does not create a directory. It starts to fail, when
897  // path length > MAX_PATH, which is 260 usually on CE.
898  // This only happens on a Windows Mobile device. Windows CE seems
899  // not to be affected by this.
900  static int platformId = 0;
901  if (platformId == 0) {
902  wchar_t platformString[64];
903  if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(platformString)/sizeof(*platformString),platformString,0)) {
904  if (0 == wcscmp(platformString, L"PocketPC") || 0 == wcscmp(platformString, L"Smartphone"))
905  platformId = 1;
906  else
907  platformId = 2;
908  }
909  }
910  if (platformId == 1 && QFSFileEnginePrivate::longFileName(path).size() > 256)
911  return false;
912 #endif
913  return ::CreateDirectory((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), 0);
914 }
915 
916 static inline bool rmDir(const QString &path)
917 {
918  return ::RemoveDirectory((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16());
919 }
920 
921 static bool isDirPath(const QString &dirPath, bool *existed)
922 {
923  QString path = dirPath;
924  if (path.length() == 2 && path.at(1) == QLatin1Char(':'))
925  path += QLatin1Char('\\');
926 
927  DWORD fileAttrib = ::GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16());
928  if (fileAttrib == INVALID_FILE_ATTRIBUTES) {
929  int errorCode = GetLastError();
930  if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) {
931  WIN32_FIND_DATA findData;
932  if (getFindData(QFSFileEnginePrivate::longFileName(path), findData))
933  fileAttrib = findData.dwFileAttributes;
934  }
935  }
936 
937  if (existed)
938  *existed = fileAttrib != INVALID_FILE_ATTRIBUTES;
939 
940  if (fileAttrib == INVALID_FILE_ATTRIBUTES)
941  return false;
942 
943  return fileAttrib & FILE_ATTRIBUTE_DIRECTORY;
944 }
945 
946 //static
947 bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents)
948 {
949  QString dirName = entry.filePath();
950  if (createParents) {
951  dirName = QDir::toNativeSeparators(QDir::cleanPath(dirName));
952  // We spefically search for / so \ would break it..
953  int oldslash = -1;
954  if (dirName.startsWith(QLatin1String("\\\\"))) {
955  // Don't try to create the root path of a UNC path;
956  // CreateDirectory() will just return ERROR_INVALID_NAME.
957  for (int i = 0; i < dirName.size(); ++i) {
958  if (dirName.at(i) != QDir::separator()) {
959  oldslash = i;
960  break;
961  }
962  }
963  if (oldslash != -1)
964  oldslash = dirName.indexOf(QDir::separator(), oldslash);
965  }
966  for (int slash=0; slash != -1; oldslash = slash) {
967  slash = dirName.indexOf(QDir::separator(), oldslash+1);
968  if (slash == -1) {
969  if (oldslash == dirName.length())
970  break;
971  slash = dirName.length();
972  }
973  if (slash) {
974  QString chunk = dirName.left(slash);
975  bool existed = false;
976  if (!isDirPath(chunk, &existed)) {
977  if (!existed) {
978  if (!mkDir(chunk))
979  return false;
980  } else {
981  return false;
982  }
983  }
984  }
985  }
986  return true;
987  }
988  return mkDir(entry.filePath());
989 }
990 
991 //static
992 bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents)
993 {
994  QString dirName = entry.filePath();
995  if (removeEmptyParents) {
996  dirName = QDir::toNativeSeparators(QDir::cleanPath(dirName));
997  for (int oldslash = 0, slash=dirName.length(); slash > 0; oldslash = slash) {
998  QString chunk = dirName.left(slash);
999  if (chunk.length() == 2 && chunk.at(0).isLetter() && chunk.at(1) == QLatin1Char(':'))
1000  break;
1001  if (!isDirPath(chunk, 0))
1002  return false;
1003  if (!rmDir(chunk))
1004  return oldslash != 0;
1005  slash = dirName.lastIndexOf(QDir::separator(), oldslash-1);
1006  }
1007  return true;
1008  }
1009  return rmDir(entry.filePath());
1010 }
1011 
1012 //static
1014 {
1015 #if defined(Q_OS_WINCE)
1016  QString ret = QLatin1String("/");
1017 #elif defined(Q_FS_FAT)
1018  QString ret = QString::fromLatin1(qgetenv("SystemDrive").constData());
1019  if (ret.isEmpty())
1020  ret = QLatin1String("c:");
1021  ret.append(QLatin1Char('/'));
1022 #elif defined(Q_OS_OS2EMX)
1023  char dir[4];
1024  _abspath(dir, QLatin1String("/"), _MAX_PATH);
1025  QString ret(dir);
1026 #endif
1027  return ret;
1028 }
1029 
1030 //static
1032 {
1033  QString ret;
1034 #if !defined(QT_NO_LIBRARY)
1035  resolveLibs();
1036  if (ptrGetUserProfileDirectoryW) {
1037  HANDLE hnd = ::GetCurrentProcess();
1038  HANDLE token = 0;
1039  BOOL ok = ::OpenProcessToken(hnd, TOKEN_QUERY, &token);
1040  if (ok) {
1041  DWORD dwBufferSize = 0;
1042  // First call, to determine size of the strings (with '\0').
1043  ok = ptrGetUserProfileDirectoryW(token, NULL, &dwBufferSize);
1044  if (!ok && dwBufferSize != 0) { // We got the required buffer size
1045  wchar_t *userDirectory = new wchar_t[dwBufferSize];
1046  // Second call, now we can fill the allocated buffer.
1047  ok = ptrGetUserProfileDirectoryW(token, userDirectory, &dwBufferSize);
1048  if (ok)
1049  ret = QString::fromWCharArray(userDirectory);
1050  delete [] userDirectory;
1051  }
1052  ::CloseHandle(token);
1053  }
1054  }
1055 #endif
1056  if (ret.isEmpty() || !QFile::exists(ret)) {
1057  ret = QString::fromLocal8Bit(qgetenv("USERPROFILE").constData());
1058  if (ret.isEmpty() || !QFile::exists(ret)) {
1059  ret = QString::fromLocal8Bit(qgetenv("HOMEDRIVE").constData())
1060  + QString::fromLocal8Bit(qgetenv("HOMEPATH").constData());
1061  if (ret.isEmpty() || !QFile::exists(ret)) {
1062  ret = QString::fromLocal8Bit(qgetenv("HOME").constData());
1063  if (ret.isEmpty() || !QFile::exists(ret)) {
1064 #if defined(Q_OS_WINCE)
1065  ret = QLatin1String("\\My Documents");
1066  if (!QFile::exists(ret))
1067 #endif
1068  ret = rootPath();
1069  }
1070  }
1071  }
1072  }
1073  return QDir::fromNativeSeparators(ret);
1074 }
1075 
1077 {
1078  QString ret;
1079  wchar_t tempPath[MAX_PATH];
1080  DWORD len = GetTempPath(MAX_PATH, tempPath);
1081  if (len)
1082  ret = QString::fromWCharArray(tempPath, len);
1083  if (!ret.isEmpty()) {
1084  while (ret.endsWith(QLatin1Char('\\')))
1085  ret.chop(1);
1086  ret = QDir::fromNativeSeparators(ret);
1087  }
1088  if (ret.isEmpty()) {
1089 #if !defined(Q_OS_WINCE)
1090  ret = QLatin1String("C:/tmp");
1091 #else
1092  ret = QLatin1String("/Temp");
1093 #endif
1094  } else if (ret.length() >= 2 && ret[1] == QLatin1Char(':'))
1095  ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters.
1096  return ret;
1097 }
1098 
1100 {
1101  QFileSystemMetaData meta;
1103  if(!(meta.exists() && meta.isDirectory()))
1104  return false;
1105 
1106 #if !defined(Q_OS_WINCE)
1107  //TODO: this should really be using nativeFilePath(), but that returns a path in long format \\?\c:\foo
1108  //which causes many problems later on when it's returned through currentPath()
1109  return ::SetCurrentDirectory(reinterpret_cast<const wchar_t*>(QDir::toNativeSeparators(entry.filePath()).utf16())) != 0;
1110 #else
1111  qfsPrivateCurrentDir = entry.filePath();
1112  return true;
1113 #endif
1114 }
1115 
1117 {
1118  QString ret;
1119 #if !defined(Q_OS_WINCE)
1120  DWORD size = 0;
1121  wchar_t currentName[PATH_MAX];
1122  size = ::GetCurrentDirectory(PATH_MAX, currentName);
1123  if (size != 0) {
1124  if (size > PATH_MAX) {
1125  wchar_t *newCurrentName = new wchar_t[size];
1126  if (::GetCurrentDirectory(PATH_MAX, newCurrentName) != 0)
1127  ret = QString::fromWCharArray(newCurrentName, size);
1128  delete [] newCurrentName;
1129  } else {
1130  ret = QString::fromWCharArray(currentName, size);
1131  }
1132  }
1133  if (ret.length() >= 2 && ret[1] == QLatin1Char(':'))
1134  ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters.
1135 #else
1136  //TODO - a race condition exists when using currentPath / setCurrentPath from multiple threads
1137  if (qfsPrivateCurrentDir.isEmpty())
1138  qfsPrivateCurrentDir = QCoreApplication::applicationDirPath();
1139 
1140  ret = qfsPrivateCurrentDir;
1141 #endif
1143 }
1144 
1145 //static
1147 {
1148  Q_ASSERT(false);
1149  Q_UNUSED(source)
1150  Q_UNUSED(target)
1151  Q_UNUSED(error)
1152 
1153  return false; // TODO implement; - code needs to be moved from qfsfileengine_win.cpp
1154 }
1155 
1156 //static
1157 bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
1158 {
1159  bool ret = ::CopyFile((wchar_t*)source.nativeFilePath().utf16(),
1160  (wchar_t*)target.nativeFilePath().utf16(), true) != 0;
1161  if(!ret)
1162  error = QSystemError(::GetLastError(), QSystemError::NativeError);
1163  return ret;
1164 }
1165 
1166 //static
1167 bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
1168 {
1169  bool ret = ::MoveFile((wchar_t*)source.nativeFilePath().utf16(),
1170  (wchar_t*)target.nativeFilePath().utf16()) != 0;
1171  if(!ret)
1172  error = QSystemError(::GetLastError(), QSystemError::NativeError);
1173  return ret;
1174 }
1175 
1176 //static
1178 {
1179  bool ret = ::DeleteFile((wchar_t*)entry.nativeFilePath().utf16()) != 0;
1180  if(!ret)
1181  error = QSystemError(::GetLastError(), QSystemError::NativeError);
1182  return ret;
1183 }
1184 
1185 //static
1186 bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error,
1187  QFileSystemMetaData *data)
1188 {
1189  Q_UNUSED(data);
1190  int mode = 0;
1191 
1192  if (permissions & QFile::ReadOwner || permissions & QFile::ReadUser
1193  || permissions & QFile::ReadGroup || permissions & QFile::ReadOther)
1194  mode |= _S_IREAD;
1195  if (permissions & QFile::WriteOwner || permissions & QFile::WriteUser
1196  || permissions & QFile::WriteGroup || permissions & QFile::WriteOther)
1197  mode |= _S_IWRITE;
1198 
1199  if (mode == 0) // not supported
1200  return false;
1201 
1202  bool ret = (::_wchmod((wchar_t*)entry.nativeFilePath().utf16(), mode) == 0);
1203  if(!ret)
1205  return ret;
1206 }
1207 
1208 static inline QDateTime fileTimeToQDateTime(const FILETIME *time)
1209 {
1210  QDateTime ret;
1211 
1212 #if defined(Q_OS_WINCE)
1213  SYSTEMTIME systime;
1214  FILETIME ftime;
1215  systime.wYear = 1970;
1216  systime.wMonth = 1;
1217  systime.wDay = 1;
1218  systime.wHour = 0;
1219  systime.wMinute = 0;
1220  systime.wSecond = 0;
1221  systime.wMilliseconds = 0;
1222  systime.wDayOfWeek = 4;
1223  SystemTimeToFileTime(&systime, &ftime);
1224  unsigned __int64 acttime = (unsigned __int64)time->dwHighDateTime << 32 | time->dwLowDateTime;
1225  FileTimeToSystemTime(time, &systime);
1226  unsigned __int64 time1970 = (unsigned __int64)ftime.dwHighDateTime << 32 | ftime.dwLowDateTime;
1227  unsigned __int64 difftime = acttime - time1970;
1228  difftime /= 10000000;
1229  ret.setTime_t((unsigned int)difftime);
1230 #else
1231  SYSTEMTIME sTime, lTime;
1232  FileTimeToSystemTime(time, &sTime);
1233  SystemTimeToTzSpecificLocalTime(0, &sTime, &lTime);
1234  ret.setDate(QDate(lTime.wYear, lTime.wMonth, lTime.wDay));
1235  ret.setTime(QTime(lTime.wHour, lTime.wMinute, lTime.wSecond, lTime.wMilliseconds));
1236 #endif
1237 
1238  return ret;
1239 }
1240 
1242 {
1243  return fileTimeToQDateTime(&creationTime_);
1244 }
1246 {
1247  return fileTimeToQDateTime(&lastWriteTime_);
1248 }
1250 {
1251  return fileTimeToQDateTime(&lastAccessTime_);
1252 }
1253 
static QString fromWCharArray(const wchar_t *, int size=-1)
Returns a copy of the string, where the encoding of string depends on the size of wchar...
Definition: qstring.cpp:1019
static bool fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data, QFileSystemMetaData::MetaDataFlags what)
void resize(int size)
#define _S_IREAD
#define _waccess(a, b)
void fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo)
void fillFromFileAttribute(DWORD fileAttribute, bool isDriveRoot=false)
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
static bool setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data=0)
static QString fromLocal8Bit(const char *, int size=-1)
Returns a QString initialized with the first size characters of the 8-bit string str.
Definition: qstring.cpp:4245
bool isLetter() const
Returns true if the character is a letter (Letter_* categories); otherwise returns false...
Definition: qchar.cpp:653
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
#define BYTE
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
The QRegExp class provides pattern matching using regular expressions.
Definition: qregexp.h:61
ushort unicode() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qchar.h:251
#define error(msg)
Q_CORE_EXPORT void qFree(void *ptr)
Definition: qmalloc.cpp:58
QString & replace(int i, int len, QChar after)
Definition: qstring.cpp:2005
void chop(int n)
Removes n characters from the end of the string.
Definition: qstring.cpp:4623
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
#define SEM_FAILCRITICALERRORS
int matchedLength() const
Returns the length of the last matched string, or -1 if there was no match.
Definition: qregexp.cpp:4193
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
#define QT_END_INCLUDE_NAMESPACE
This macro is equivalent to QT_BEGIN_NAMESPACE.
Definition: qglobal.h:92
The QDate class provides date functions.
Definition: qdatetime.h:55
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
Q_CORE_EXPORT void * qMalloc(size_t size)
Definition: qmalloc.cpp:53
bool isAbsolute() const
static const WinVersion WindowsVersion
the version of the Windows operating system on which the application is run (Windows only) ...
Definition: qglobal.h:1613
The QString class provides a Unicode character string.
Definition: qstring.h:83
static QString currentPath()
Returns the absolute path of the application&#39;s current directory.
Definition: qdir.cpp:1875
static QWidget * owner
QDateTime modificationTime() const
static bool mkDir(const QString &path)
static bool tryDriveUNCFallback(const QFileSystemEntry &fname, QFileSystemMetaData &data)
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static PtrNetApiBufferFree ptrNetApiBufferFree
void fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType=false, bool isDriveRoot=false)
bool load(bool onlySystemDirectory=true)
#define CoInitialize(x)
static QChar separator()
Returns the native directory separator: "/" under Unix (including Mac OS X) and "\\" under Windows...
Definition: qdir.cpp:1831
static bool uncListSharesOnServer(const QString &server, QStringList *list)
static QString longFileName(const QString &path)
struct _SHARE_INFO_1 SHARE_INFO_1
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
#define _wchmod(a, b)
static QFileSystemEntry currentPath()
NativePath nativeFilePath() const
Q_CORE_EXPORT int qt_ntfs_permission_lookup
bool exists() const
Returns true if the file specified by fileName() exists; otherwise returns false. ...
Definition: qfile.cpp:626
#define IO_REPARSE_TAG_SYMLINK
static QString readLink(const QFileSystemEntry &link)
static bool resolveUNCLibs()
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
static QString applicationDirPath()
Returns the directory that contains the application executable.
The QTime class provides clock time functions.
Definition: qdatetime.h:148
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static QFileSystemEntry absoluteName(const QFileSystemEntry &entry)
static bool removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents)
static bool renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
void setTime_t(uint secsSince1Jan1970UTC)
Sets the date and time given the number of seconds that have passed since 1970-01-01T00:00:00, Coordinated Universal Time (Qt::UTC).
Definition: qdatetime.cpp:2566
void setDate(const QDate &date)
Sets the date part of this datetime to date.
Definition: qdatetime.cpp:2399
int indexIn(const QString &str, int offset=0, CaretMode caretMode=CaretAtZero) const
Attempts to find a match in str from position offset (0 by default).
Definition: qregexp.cpp:4136
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
int size() const
Returns the number of characters in this string.
Definition: qstring.h:102
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
void setTime(const QTime &time)
Sets the time part of this datetime to time.
Definition: qdatetime.cpp:2416
#define SPI_GETPLATFORMTYPE
const char * name
#define Q_GLOBAL_STATIC(TYPE, NAME)
Declares a global static variable with the given type and name.
Definition: qglobal.h:1968
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
static bool isDirPath(const QString &dirPath, bool *existed)
static void resolveLibs()
static const char * data(const QByteArray &arr)
DWORD(WINAPI * PtrNetShareEnum)(LPWSTR, DWORD, LPBYTE *, DWORD, LPDWORD, LPDWORD, LPDWORD)
static bool tryFindFallback(const QFileSystemEntry &fname, QFileSystemMetaData &data)
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:2838
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
QChar toUpper() const
Returns the uppercase equivalent if the character is lowercase or titlecase; otherwise returns the ch...
Definition: qchar.cpp:1287
QBool contains(const QString &str, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the list contains the string str; otherwise returns false.
Definition: qstringlist.h:172
static PtrNetShareEnum ptrNetShareEnum
static QString qfsPrivateCurrentDir
QString right(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n rightmost characters of the string.
Definition: qstring.cpp:3682
bool hasFlags(MetaDataFlags flags) const
void * HANDLE
Definition: qnamespace.h:1671
static bool fillPermissions(const QFileSystemEntry &entry, QFileSystemMetaData &data, QFileSystemMetaData::MetaDataFlags what)
static QString cleanPath(const QString &path)
Removes all multiple directory separators "/" and resolves any "."s or ".."s found in the path...
Definition: qdir.cpp:2082
static QString nativeAbsoluteFilePath(const QString &path)
static QFileSystemEntry getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data)
#define PATH_MAX
static bool rmDir(const QString &path)
static bool getFindData(QString path, WIN32_FIND_DATA &findData)
static bool createDirectory(const QFileSystemEntry &entry, bool createParents)
ushort unicode() const
Converts a Latin-1 character to an 16-bit-encoded Unicode representation of the character.
Definition: qchar.h:64
#define SetErrorMode(a)
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
static bool setCurrentPath(const QFileSystemEntry &entry)
static QAuServer & server()
Definition: qsound.cpp:79
long HRESULT
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
void * resolve(const char *symbol)
static bool createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
QString & append(QChar c)
Definition: qstring.cpp:1777
The QDateTime class provides date and time functions.
Definition: qdatetime.h:216
static bool uncShareExists(const QString &server)
#define Q_CORE_EXPORT
Definition: qglobal.h:1449
int lastIndexOf(QChar c, int from=-1, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:3000
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
static bool removeFile(const QFileSystemEntry &entry, QSystemError &error)
bool isDriveRoot() const
QString toLower() const Q_REQUIRED_RESULT
Returns a lowercase copy of the string.
Definition: qstring.cpp:5389
MetaDataFlags missingFlags(MetaDataFlags flags)
#define SEM_NOOPENFILEERRORBOX
QString filePath() const
#define QT_BEGIN_INCLUDE_NAMESPACE
This macro is equivalent to QT_END_NAMESPACE.
Definition: qglobal.h:91
static QString owner(const QFileSystemEntry &entry, QAbstractFileEngine::FileOwner own)
static bool copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
bool isRelative() const
QDateTime creationTime() const
#define INVALID_FILE_ATTRIBUTES
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
DWORD(WINAPI * PtrNetApiBufferFree)(LPVOID)
static QString fromNativeSeparators(const QString &pathName)
Returns pathName using &#39;/&#39; as file separator.
Definition: qdir.cpp:848
static QString readSymLink(const QFileSystemEntry &link)
#define _S_IWRITE
QString & remove(int i, int len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
Definition: qstring.cpp:1867
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition: qstring.cpp:3796
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:60
static QString toNativeSeparators(const QString &pathName)
Returns pathName with the &#39;/&#39; separators converted to separators that are appropriate for the underly...
Definition: qdir.cpp:812
Flags
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
static QString fileName(const QString &fileUrl)
static QMutex * globalInstanceGet(const void *address)
Returns a QMutex from the global mutex pool.
Definition: qmutexpool.cpp:150
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
static QDateTime fileTimeToQDateTime(const FILETIME *time)
static void clearWinStatData(QFileSystemMetaData &data)
int size() const
int errno
static QFileSystemEntry canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
const ushort * utf16() const
Returns the QString as a &#39;\0\&#39;-terminated array of unsigned shorts.
Definition: qstring.cpp:5290
INT_PTR intptr_t