Skip to content

Commit

Permalink
Remove NT Path prefix if provided path was not NT prefixed
Browse files Browse the repository at this point in the history
  • Loading branch information
ianhattendorf committed Jan 16, 2020
1 parent a44e799 commit 2afdf0c
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 28 deletions.
3 changes: 2 additions & 1 deletion includes/win32/Watcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
class Watcher
{
public:
Watcher(std::shared_ptr<EventQueue> queue, HANDLE dirHandle, const std::wstring &path);
Watcher(std::shared_ptr<EventQueue> queue, HANDLE dirHandle, const std::wstring &path, bool pathWasNtPrefixed);
~Watcher();

bool isRunning() const { return mRunning; }
Expand Down Expand Up @@ -42,6 +42,7 @@ class Watcher
const std::wstring mPath;
std::shared_ptr<EventQueue> mQueue;
HANDLE mDirectoryHandle;
bool mPathWasNtPrefixed;

std::vector<BYTE> mReadBuffer, mWriteBuffer;
OVERLAPPED mOverlapped;
Expand Down
55 changes: 30 additions & 25 deletions src/win32/Controller.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
#include "../includes/win32/Controller.h"

static std::wstring convertMultiByteToWideCharNTPath(const std::string &multiByte) {
static bool isNtPath(const std::wstring &path) {
return path.rfind(L"\\\\?\\", 0) == 0 || path.rfind(L"\\??\\", 0) == 0;
}

static std::wstring prefixWithNtPath(const std::wstring &path) {
const ULONG widePathLength = GetFullPathNameW(path.c_str(), 0, nullptr, nullptr);
if (widePathLength == 0) {
return path;
}

std::wstring ntPathString;
ntPathString.resize(widePathLength - 1);
if (GetFullPathNameW(path.c_str(), widePathLength, &(ntPathString[0]), nullptr) != widePathLength - 1) {
return path;
}

return ntPathString.rfind(L"\\\\", 0) == 0
? ntPathString.replace(0, 2, L"\\\\?\\UNC\\")
: ntPathString.replace(0, 0, L"\\\\?\\");
}

static std::wstring convertMultiByteToWideChar(const std::string &multiByte) {
const int wlen = MultiByteToWideChar(CP_UTF8, 0, multiByte.data(), -1, 0, 0);

if (wlen == 0) {
Expand All @@ -15,28 +36,7 @@ static std::wstring convertMultiByteToWideCharNTPath(const std::string &multiByt
return std::wstring();
}

if (wideString.rfind(L"\\\\?\\", 0) == 0 || wideString.rfind(L"\\??\\", 0) == 0) {
// We already have an NT Path
return wideString;
}

const ULONG widePathLength = GetFullPathNameW(wideString.c_str(), 0, nullptr, nullptr);
if (widePathLength == 0) {
return wideString;
}

std::wstring pathString;
pathString.resize(widePathLength - 1);

if (GetFullPathNameW(wideString.c_str(), widePathLength, &(pathString[0]), nullptr) != widePathLength - 1) {
// Failed to get full path name
return wideString;
}

// We return an NT Path to support paths > MAX_PATH
return pathString.rfind(L"\\\\", 0) == 0
? pathString.replace(0, 2, L"\\\\?\\UNC\\")
: pathString.replace(0, 0, L"\\\\?\\");
return wideString;
}

HANDLE Controller::openDirectory(const std::wstring &path) {
Expand All @@ -57,14 +57,19 @@ HANDLE Controller::openDirectory(const std::wstring &path) {
Controller::Controller(std::shared_ptr<EventQueue> queue, const std::string &path)
: mDirectoryHandle(INVALID_HANDLE_VALUE)
{
auto widePath = convertMultiByteToWideCharNTPath(path);
auto widePath = convertMultiByteToWideChar(path);
const bool isNt = isNtPath(widePath);
if (!isNt) {
// We convert to an NT Path to support paths > MAX_PATH
widePath = prefixWithNtPath(widePath);
}
mDirectoryHandle = openDirectory(widePath);

if (mDirectoryHandle == INVALID_HANDLE_VALUE) {
return;
}

mWatcher.reset(new Watcher(queue, mDirectoryHandle, widePath));
mWatcher.reset(new Watcher(queue, mDirectoryHandle, widePath, isNt));
}

Controller::~Controller() {
Expand Down
20 changes: 18 additions & 2 deletions src/win32/Watcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

#include <sstream>

static
void stripNTPrefix(std::wstring &path) {
if (path.rfind(L"\\\\?\\UNC\\", 0) != std::wstring::npos) {
path.replace(0, 7, L"\\");
} else if (path.rfind(L"\\\\?\\", 0) != std::wstring::npos) {
path.erase(0, 4);
}
}

static
std::wstring getWStringFileName(LPWSTR cFileName, DWORD length) {
LPWSTR nullTerminatedFileName = new WCHAR[length + 1]();
Expand All @@ -24,6 +33,12 @@ std::string Watcher::getUTF8Directory(std::wstring path) {
}

std::wstring uft16DirectoryString = utf16DirectoryStream.str();
if (!mPathWasNtPrefixed) {
// If we were the ones that prefixed the path, we should strip it
// before returning it to the user
stripNTPrefix(uft16DirectoryString);
}

int utf8length = WideCharToMultiByte(
CP_UTF8,
0,
Expand Down Expand Up @@ -89,11 +104,12 @@ std::string getUTF8FileName(std::wstring path) {
return utf8Directory;
}

Watcher::Watcher(std::shared_ptr<EventQueue> queue, HANDLE dirHandle, const std::wstring &path)
Watcher::Watcher(std::shared_ptr<EventQueue> queue, HANDLE dirHandle, const std::wstring &path, bool pathWasNtPrefixed)
: mRunning(false),
mDirectoryHandle(dirHandle),
mQueue(queue),
mPath(path)
mPath(path),
mPathWasNtPrefixed(pathWasNtPrefixed)
{
ZeroMemory(&mOverlapped, sizeof(OVERLAPPED));
mOverlapped.hEvent = this;
Expand Down

0 comments on commit 2afdf0c

Please sign in to comment.