diff -r 000000000000 -r 6474c204b198 xpcom/io/FileUtilsWin.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xpcom/io/FileUtilsWin.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_FileUtilsWin_h +#define mozilla_FileUtilsWin_h + +#include + +#include "mozilla/Scoped.h" +#include "nsStringGlue.h" + +namespace mozilla { + +inline bool +NtPathToDosPath(const nsAString& aNtPath, nsAString& aDosPath) +{ + aDosPath.Truncate(); + if (aNtPath.IsEmpty()) { + return true; + } + NS_NAMED_LITERAL_STRING(symLinkPrefix, "\\??\\"); + uint32_t ntPathLen = aNtPath.Length(); + uint32_t symLinkPrefixLen = symLinkPrefix.Length(); + if (ntPathLen >= 6 && aNtPath.CharAt(5) == L':' && + ntPathLen >= symLinkPrefixLen && + Substring(aNtPath, 0, symLinkPrefixLen).Equals(symLinkPrefix)) { + // Symbolic link for DOS device. Just strip off the prefix. + aDosPath = aNtPath; + aDosPath.Cut(0, 4); + return true; + } + nsAutoString logicalDrives; + DWORD len = 0; + while(true) { + len = GetLogicalDriveStringsW(len, reinterpret_cast(logicalDrives.BeginWriting())); + if (!len) { + return false; + } else if (len > logicalDrives.Length()) { + logicalDrives.SetLength(len); + } else { + break; + } + } + const char16_t* cur = logicalDrives.BeginReading(); + const char16_t* end = logicalDrives.EndReading(); + nsString targetPath; + targetPath.SetLength(MAX_PATH); + wchar_t driveTemplate[] = L" :"; + do { + // Unfortunately QueryDosDevice doesn't support the idiom for querying the + // output buffer size, so it may require retries. + driveTemplate[0] = *cur; + DWORD targetPathLen = 0; + SetLastError(ERROR_SUCCESS); + while (true) { + targetPathLen = QueryDosDeviceW(driveTemplate, reinterpret_cast(targetPath.BeginWriting()), + targetPath.Length()); + if (targetPathLen || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + break; + } + targetPath.SetLength(targetPath.Length() * 2); + } + if (targetPathLen) { + // Need to use wcslen here because targetPath contains embedded NULL chars + size_t firstTargetPathLen = wcslen(targetPath.get()); + const char16_t* pathComponent = aNtPath.BeginReading() + + firstTargetPathLen; + bool found = _wcsnicmp(char16ptr_t(aNtPath.BeginReading()), targetPath.get(), + firstTargetPathLen) == 0 && + *pathComponent == L'\\'; + if (found) { + aDosPath = driveTemplate; + aDosPath += pathComponent; + return true; + } + } + // Advance to the next NUL character in logicalDrives + while (*cur++); + } while (cur != end); + // Code for handling UNC paths would go here, if eventually required. +#if defined(DEBUG) + NS_NAMED_LITERAL_STRING(deviceMupPrefix, "\\Device\\Mup\\"); + uint32_t deviceMupPrefixLen = deviceMupPrefix.Length(); + if (ntPathLen >= deviceMupPrefixLen && + Substring(aNtPath, 0, deviceMupPrefixLen).Equals(deviceMupPrefix)) { + NS_WARNING("UNC paths not yet supported in NtPathToDosPath"); + } +#endif // defined(DEBUG) + return false; +} + +bool +HandleToFilename(HANDLE aHandle, const LARGE_INTEGER& aOffset, + nsAString& aFilename); + +} // namespace mozilla + +#endif // mozilla_FileUtilsWin_h