From 13b127edb8a0ae289a3ffb8a734aacbfce88f54b Mon Sep 17 00:00:00 2001 From: Matthieu Gallien Date: Tue, 19 Mar 2024 11:33:24 +0100 Subject: [PATCH 1/6] add logs to the files explorer integration DLL Signed-off-by: Matthieu Gallien --- .../NCContextMenu/NCClientInterface.cpp | 29 ++++++++++++++----- .../windows/NCContextMenu/NCClientInterface.h | 5 ++-- .../windows/NCContextMenu/NCContextMenu.cpp | 20 +++++++++++-- .../windows/NCContextMenu/NCContextMenu.h | 8 ++++- .../windows/NCOverlays/NCOverlay.cpp | 10 ++++--- .../windows/NCOverlays/NCOverlay.h | 6 ++-- .../windows/NCUtil/CommunicationSocket.cpp | 4 ++- .../windows/NCUtil/CommunicationSocket.h | 3 +- .../windows/NCUtil/RemotePathChecker.cpp | 8 ++--- .../windows/NCUtil/RemotePathChecker.h | 7 +++-- 10 files changed, 73 insertions(+), 27 deletions(-) diff --git a/shell_integration/windows/NCContextMenu/NCClientInterface.cpp b/shell_integration/windows/NCContextMenu/NCClientInterface.cpp index 4c5d665139aae..ebb28b965791a 100644 --- a/shell_integration/windows/NCContextMenu/NCClientInterface.cpp +++ b/shell_integration/windows/NCContextMenu/NCClientInterface.cpp @@ -26,44 +26,55 @@ #include #include #include +#include +#include using namespace std; #define PIPE_TIMEOUT 5*1000 //ms -NCClientInterface::ContextMenuInfo NCClientInterface::FetchInfo(const std::wstring &files) +NCClientInterface::ContextMenuInfo NCClientInterface::FetchInfo(const std::wstring &files, std::ofstream &logger) { auto pipename = CommunicationSocket::DefaultPipePath(); CommunicationSocket socket; if (!WaitNamedPipe(pipename.data(), PIPE_TIMEOUT)) { + logger << "error with WaitNamedPipe" << std::endl; return {}; } if (!socket.Connect(pipename)) { + logger << "error with Connect" << std::endl; return {}; } - socket.SendMsg(L"GET_STRINGS:CONTEXT_MENU_TITLE\n"); - socket.SendMsg((L"GET_MENU_ITEMS:" + files + L"\n").data()); + socket.SendMsg(L"GET_STRINGS:CONTEXT_MENU_TITLE\n", logger); + socket.SendMsg((L"GET_MENU_ITEMS:" + files + L"\n").data(), logger); ContextMenuInfo info; std::wstring response; int sleptCount = 0; + constexpr auto noReplyTimeout = 20; constexpr auto replyTimeout = 200; bool receivedReplyFromDesktopClient = false; while ((!receivedReplyFromDesktopClient && sleptCount < noReplyTimeout) || (receivedReplyFromDesktopClient && sleptCount < replyTimeout)) { + logger << "trying to read a line" << std::endl; + if (socket.ReadLine(&response)) { + logger << "received: " << converter.to_bytes(response) << std::endl; if (StringUtil::begins_with(response, wstring(L"REGISTER_PATH:"))) { + logger << "received: REGISTER_PATH" << std::endl; wstring responsePath = response.substr(14); // length of REGISTER_PATH info.watchedDirectories.push_back(responsePath); } else if (StringUtil::begins_with(response, wstring(L"STRING:"))) { + logger << "received: STRING" << std::endl; wstring stringName, stringValue; if (!StringUtil::extractChunks(response, stringName, stringValue)) continue; if (stringName == L"CONTEXT_MENU_TITLE") info.contextMenuTitle = move(stringValue); } else if (StringUtil::begins_with(response, wstring(L"MENU_ITEM:"))) { + logger << "received: MENU_ITEM" << std::endl; wstring commandName, flags, title; if (!StringUtil::extractChunks(response, commandName, flags, title)) continue; @@ -72,18 +83,22 @@ NCClientInterface::ContextMenuInfo NCClientInterface::FetchInfo(const std::wstri receivedReplyFromDesktopClient = true; continue; } else if (StringUtil::begins_with(response, wstring(L"GET_MENU_ITEMS:END"))) { + logger << "received: GET_MENU_ITEMS:END" << std::endl; break; // Stop once we completely received the last sent request + } else { + logger << "received: another reply" << std::endl; } - } - else { + } else { + logger << "received nothing" << std::endl; Sleep(50); ++sleptCount; } } + return info; } -void NCClientInterface::SendRequest(const wchar_t *verb, const std::wstring &path) +void NCClientInterface::SendRequest(const wchar_t *verb, const std::wstring &path, std::ofstream &logger) { auto pipename = CommunicationSocket::DefaultPipePath(); @@ -95,5 +110,5 @@ void NCClientInterface::SendRequest(const wchar_t *verb, const std::wstring &pat return; } - socket.SendMsg((verb + (L":" + path + L"\n")).data()); + socket.SendMsg((verb + (L":" + path + L"\n")).data(), logger); } diff --git a/shell_integration/windows/NCContextMenu/NCClientInterface.h b/shell_integration/windows/NCContextMenu/NCClientInterface.h index a76cab5af7f76..c0d145c38c03d 100644 --- a/shell_integration/windows/NCContextMenu/NCClientInterface.h +++ b/shell_integration/windows/NCContextMenu/NCClientInterface.h @@ -37,6 +37,7 @@ #include #include #include +#include class CommunicationSocket; @@ -52,8 +53,8 @@ class NCClientInterface }; std::vector menuItems; }; - static ContextMenuInfo FetchInfo(const std::wstring &files); - static void SendRequest(const wchar_t *verb, const std::wstring &path); + static ContextMenuInfo FetchInfo(const std::wstring &files, std::ofstream &logger); + static void SendRequest(const wchar_t *verb, const std::wstring &path, std::ofstream &logger); }; #endif //ABSTRACTSOCKETHANDLER_H diff --git a/shell_integration/windows/NCContextMenu/NCContextMenu.cpp b/shell_integration/windows/NCContextMenu/NCContextMenu.cpp index b35576900fe7a..72f91cc347649 100644 --- a/shell_integration/windows/NCContextMenu/NCContextMenu.cpp +++ b/shell_integration/windows/NCContextMenu/NCContextMenu.cpp @@ -21,16 +21,22 @@ #include #include +#include +#include + extern long g_cDllRef; NCContextMenu::NCContextMenu(void) : m_cRef(1) { InterlockedIncrement(&g_cDllRef); + m_logger.open("c:\\test.log"); + m_logger << "hello world" << std::endl; } NCContextMenu::~NCContextMenu(void) { + m_logger << "NCContextMenu::~NCContextMenu" << std::endl; InterlockedDecrement(&g_cDllRef); } @@ -39,6 +45,7 @@ NCContextMenu::~NCContextMenu(void) // Query to the interface the component supported. IFACEMETHODIMP NCContextMenu::QueryInterface(REFIID riid, void **ppv) { + m_logger << "NCContextMenu::QueryInterface" << std::endl; static const QITAB qit[] = { QITABENT(NCContextMenu, IContextMenu), @@ -51,12 +58,14 @@ IFACEMETHODIMP NCContextMenu::QueryInterface(REFIID riid, void **ppv) // Increase the reference count for an interface on an object. IFACEMETHODIMP_(ULONG) NCContextMenu::AddRef() { + m_logger << "NCContextMenu::AddRef" << std::endl; return InterlockedIncrement(&m_cRef); } // Decrease the reference count for an interface on an object. IFACEMETHODIMP_(ULONG) NCContextMenu::Release() { + m_logger << "NCContextMenu::Release" << std::endl; ULONG cRef = InterlockedDecrement(&m_cRef); if (0 == cRef) { delete this; @@ -74,6 +83,7 @@ IFACEMETHODIMP_(ULONG) NCContextMenu::Release() IFACEMETHODIMP NCContextMenu::Initialize( LPCITEMIDLIST, LPDATAOBJECT pDataObj, HKEY) { + m_logger << "NCContextMenu::Initialize" << std::endl; m_selectedFiles.clear(); if (!pDataObj) { @@ -129,17 +139,20 @@ void InsertSeperator(HMENU hMenu, UINT indexMenu) IFACEMETHODIMP NCContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) { + m_logger << "NCContextMenu::QueryContextMenu" << std::endl; // If uFlags include CMF_DEFAULTONLY then we should not do anything. if (CMF_DEFAULTONLY & uFlags) { return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0)); } - m_info = NCClientInterface::FetchInfo(m_selectedFiles); + m_info = NCClientInterface::FetchInfo(m_selectedFiles, m_logger); if (m_info.menuItems.empty()) { + m_logger << "NCContextMenu::QueryContextMenu " << "empty info" << std::endl; return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0)); } + m_logger << "NCContextMenu::QueryContextMenu" << "insert separator" << std::endl; InsertSeperator(hMenu, indexMenu++); HMENU hSubmenu = CreateMenu(); @@ -153,6 +166,7 @@ IFACEMETHODIMP NCContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT if (!InsertMenuItem(hMenu, indexMenu++, TRUE, &mii)) return HRESULT_FROM_WIN32(GetLastError()); } + m_logger << "NCContextMenu::QueryContextMenu" << "insert separator" << std::endl; InsertSeperator(hMenu, indexMenu++); UINT indexSubMenu = 0; @@ -179,6 +193,7 @@ IFACEMETHODIMP NCContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT IFACEMETHODIMP NCContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici) { + m_logger << "NCContextMenu::InvokeCommand" << std::endl; std::wstring command; CMINVOKECOMMANDINFOEX *piciEx = nullptr; @@ -215,13 +230,14 @@ IFACEMETHODIMP NCContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici) return E_FAIL; } - NCClientInterface::SendRequest(command.data(), m_selectedFiles); + NCClientInterface::SendRequest(command.data(), m_selectedFiles, m_logger); return S_OK; } IFACEMETHODIMP NCContextMenu::GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax) { + m_logger << "NCContextMenu::GetCommandString" << std::endl; if (idCommand < m_info.menuItems.size() && uFlags == GCS_VERBW) { return StringCchCopyW(reinterpret_cast(pszName), cchMax, m_info.menuItems[idCommand].command.data()); diff --git a/shell_integration/windows/NCContextMenu/NCContextMenu.h b/shell_integration/windows/NCContextMenu/NCContextMenu.h index b5b2a3eb7f8f0..730b4d4eee6a6 100644 --- a/shell_integration/windows/NCContextMenu/NCContextMenu.h +++ b/shell_integration/windows/NCContextMenu/NCContextMenu.h @@ -16,9 +16,13 @@ #define NCCONTEXTMENU_H #pragma once +#include "NCClientInterface.h" + #include // For IShellExtInit and IContextMenu + #include -#include "NCClientInterface.h" +#include +#include class NCContextMenu : public IShellExtInit, public IContextMenu { @@ -48,6 +52,8 @@ class NCContextMenu : public IShellExtInit, public IContextMenu // The name of the selected files (separated by '\x1e') std::wstring m_selectedFiles; NCClientInterface::ContextMenuInfo m_info; + + std::ofstream m_logger; }; #endif //NCCONTEXTMENU_H diff --git a/shell_integration/windows/NCOverlays/NCOverlay.cpp b/shell_integration/windows/NCOverlays/NCOverlay.cpp index a70f38b23248d..9d983b3966041 100644 --- a/shell_integration/windows/NCOverlays/NCOverlay.cpp +++ b/shell_integration/windows/NCOverlays/NCOverlay.cpp @@ -35,22 +35,24 @@ namespace { unique_ptr s_instance; -RemotePathChecker *getGlobalChecker() +RemotePathChecker *getGlobalChecker(ofstream &logger) { // On Vista we'll run into issue #2680 if we try to create the thread+pipe connection // on any DllGetClassObject of our registered classes. // Work around the issue by creating the static RemotePathChecker only once actually needed. static once_flag s_onceFlag; - call_once(s_onceFlag, [] { s_instance.reset(new RemotePathChecker); }); + call_once(s_onceFlag, [&logger] { s_instance.reset(new RemotePathChecker{logger}); }); return s_instance.get(); } } -NCOverlay::NCOverlay(int state) +NCOverlay::NCOverlay(int state) : _referenceCount(1) , _state(state) { + m_logger.open("c:\\testOverlay.log"); + m_logger << "hello world" << std::endl; } NCOverlay::~NCOverlay(void) @@ -120,7 +122,7 @@ IFACEMETHODIMP NCOverlay::GetPriority(int *pPriority) IFACEMETHODIMP NCOverlay::IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib) { - RemotePathChecker* checker = getGlobalChecker(); + RemotePathChecker* checker = getGlobalChecker(m_logger); std::shared_ptr> watchedDirectories = checker->WatchedDirectories(); if (watchedDirectories->empty()) { diff --git a/shell_integration/windows/NCOverlays/NCOverlay.h b/shell_integration/windows/NCOverlays/NCOverlay.h index 688a6b0950287..45966c9f51d88 100644 --- a/shell_integration/windows/NCOverlays/NCOverlay.h +++ b/shell_integration/windows/NCOverlays/NCOverlay.h @@ -18,12 +18,13 @@ #pragma once #include +#include class NCOverlay : public IShellIconOverlayIdentifier { public: - NCOverlay(int state); + explicit NCOverlay(int state); IFACEMETHODIMP_(ULONG) AddRef(); IFACEMETHODIMP GetOverlayInfo(PWSTR pwszIconFile, int cchMax, int *pIndex, DWORD *pdwFlags); @@ -38,6 +39,7 @@ class NCOverlay : public IShellIconOverlayIdentifier private: long _referenceCount; int _state; + std::ofstream m_logger; }; -#endif \ No newline at end of file +#endif diff --git a/shell_integration/windows/NCUtil/CommunicationSocket.cpp b/shell_integration/windows/NCUtil/CommunicationSocket.cpp index 6f9cdbb983c63..06232675df089 100644 --- a/shell_integration/windows/NCUtil/CommunicationSocket.cpp +++ b/shell_integration/windows/NCUtil/CommunicationSocket.cpp @@ -81,8 +81,10 @@ bool CommunicationSocket::Connect(const std::wstring &pipename) return true; } -bool CommunicationSocket::SendMsg(const wchar_t* message) const +bool CommunicationSocket::SendMsg(const wchar_t* message, std::ofstream &logger) const { + logger << "CommunicationSocket::SendMsg: " << (*message) << std::endl; + auto utf8_msg = StringUtil::toUtf8(message); DWORD numBytesWritten = 0; diff --git a/shell_integration/windows/NCUtil/CommunicationSocket.h b/shell_integration/windows/NCUtil/CommunicationSocket.h index bc55c2d933de2..0b631a849670f 100644 --- a/shell_integration/windows/NCUtil/CommunicationSocket.h +++ b/shell_integration/windows/NCUtil/CommunicationSocket.h @@ -21,6 +21,7 @@ #include #include +#include #include class __declspec(dllexport) CommunicationSocket @@ -34,7 +35,7 @@ class __declspec(dllexport) CommunicationSocket bool Connect(const std::wstring& pipename); bool Close(); - bool SendMsg(const wchar_t*) const; + bool SendMsg(const wchar_t*, std::ofstream &logger) const; bool ReadLine(std::wstring*); HANDLE Event() { return _pipe; } diff --git a/shell_integration/windows/NCUtil/RemotePathChecker.cpp b/shell_integration/windows/NCUtil/RemotePathChecker.cpp index 5d004d567d286..e61725dd58b76 100644 --- a/shell_integration/windows/NCUtil/RemotePathChecker.cpp +++ b/shell_integration/windows/NCUtil/RemotePathChecker.cpp @@ -30,7 +30,7 @@ using namespace std; // This code is run in a thread -void RemotePathChecker::workerThreadLoop() +void RemotePathChecker::workerThreadLoop(ofstream &logger) { auto pipename = CommunicationSocket::DefaultPipePath(); bool connected = false; @@ -62,7 +62,7 @@ void RemotePathChecker::workerThreadLoop() lock.unlock(); if (!asked.count(filePath)) { asked.insert(filePath); - socket.SendMsg(wstring(L"RETRIEVE_FILE_STATUS:" + filePath + L'\n').data()); + socket.SendMsg(wstring(L"RETRIEVE_FILE_STATUS:" + filePath + L'\n').data(), logger); } lock.lock(); } @@ -162,12 +162,12 @@ void RemotePathChecker::workerThreadLoop() -RemotePathChecker::RemotePathChecker() +RemotePathChecker::RemotePathChecker(ofstream &logger) : _stop(false) , _watchedDirectories(make_shared>()) , _connected(false) , _newQueries(CreateEvent(nullptr, FALSE, FALSE, nullptr)) - , _thread([this]{ this->workerThreadLoop(); }) + , _thread([this, &logger]{ this->workerThreadLoop(logger); }) { } diff --git a/shell_integration/windows/NCUtil/RemotePathChecker.h b/shell_integration/windows/NCUtil/RemotePathChecker.h index 134138f137244..63afba079f928 100644 --- a/shell_integration/windows/NCUtil/RemotePathChecker.h +++ b/shell_integration/windows/NCUtil/RemotePathChecker.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #pragma once @@ -36,7 +37,7 @@ class RemotePathChecker { StateWarning, StateNone }; - RemotePathChecker(); + explicit RemotePathChecker(std::ofstream &logger); ~RemotePathChecker(); std::shared_ptr> WatchedDirectories() const; bool IsMonitoredPath(const wchar_t* filePath, int* state); @@ -64,7 +65,7 @@ class RemotePathChecker { HANDLE _newQueries; std::thread _thread; - void workerThreadLoop(); + void workerThreadLoop(std::ofstream &logger); }; -#endif \ No newline at end of file +#endif From 93b9a1371870feecf1373c14a447f683e16fb3c7 Mon Sep 17 00:00:00 2001 From: Camila Ayres Date: Thu, 10 Oct 2024 14:41:45 +0200 Subject: [PATCH 2/6] Fix add logs compilation. Signed-off-by: Camila Ayres --- shell_integration/windows/NCContextMenu/NCClientInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell_integration/windows/NCContextMenu/NCClientInterface.cpp b/shell_integration/windows/NCContextMenu/NCClientInterface.cpp index ebb28b965791a..80b9f1ea892b0 100644 --- a/shell_integration/windows/NCContextMenu/NCClientInterface.cpp +++ b/shell_integration/windows/NCContextMenu/NCClientInterface.cpp @@ -60,7 +60,7 @@ NCClientInterface::ContextMenuInfo NCClientInterface::FetchInfo(const std::wstri logger << "trying to read a line" << std::endl; if (socket.ReadLine(&response)) { - logger << "received: " << converter.to_bytes(response) << std::endl; + logger << "received: " << StringUtil::toUtf8(response.c_str()) << std::endl; if (StringUtil::begins_with(response, wstring(L"REGISTER_PATH:"))) { logger << "received: REGISTER_PATH" << std::endl; wstring responsePath = response.substr(14); // length of REGISTER_PATH From e727fcabd8bcece8a3f893f7db49c0b5e6b2fab5 Mon Sep 17 00:00:00 2001 From: Camila Ayres Date: Thu, 10 Oct 2024 16:30:45 +0200 Subject: [PATCH 3/6] Stop thread loop when socket message fails to send. Signed-off-by: Camila Ayres --- shell_integration/windows/NCUtil/RemotePathChecker.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/shell_integration/windows/NCUtil/RemotePathChecker.cpp b/shell_integration/windows/NCUtil/RemotePathChecker.cpp index e61725dd58b76..3ac1baa815592 100644 --- a/shell_integration/windows/NCUtil/RemotePathChecker.cpp +++ b/shell_integration/windows/NCUtil/RemotePathChecker.cpp @@ -62,7 +62,11 @@ void RemotePathChecker::workerThreadLoop(ofstream &logger) lock.unlock(); if (!asked.count(filePath)) { asked.insert(filePath); - socket.SendMsg(wstring(L"RETRIEVE_FILE_STATUS:" + filePath + L'\n').data(), logger); + if (!socket.SendMsg(wstring(L"RETRIEVE_FILE_STATUS:" + filePath + L'\n').data(), logger)) { + _stop = true; + logger << "stopping thread" << std::endl; + break; + } } lock.lock(); } From 2fb16976b99ab55b939e7a9b2252b06fd80ea559 Mon Sep 17 00:00:00 2001 From: Camila Ayres Date: Thu, 10 Oct 2024 16:38:23 +0200 Subject: [PATCH 4/6] stop loop when response is empty. Signed-off-by: Camila Ayres --- .../windows/NCUtil/RemotePathChecker.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/shell_integration/windows/NCUtil/RemotePathChecker.cpp b/shell_integration/windows/NCUtil/RemotePathChecker.cpp index 3ac1baa815592..f6367f1efcdfd 100644 --- a/shell_integration/windows/NCUtil/RemotePathChecker.cpp +++ b/shell_integration/windows/NCUtil/RemotePathChecker.cpp @@ -73,7 +73,16 @@ void RemotePathChecker::workerThreadLoop(ofstream &logger) } std::wstring response; - while (!_stop && socket.ReadLine(&response)) { + while (!_stop) { + if (!socket.ReadLine(&response)) { + socket.Close(); + break; + } + + if (response.empty()) { + break; + } + if (StringUtil::begins_with(response, wstring(L"REGISTER_PATH:"))) { wstring responsePath = response.substr(14); // length of REGISTER_PATH: From c8985829755e8b489edd3202ace1232a00de8b4f Mon Sep 17 00:00:00 2001 From: Camila Ayres Date: Thu, 10 Oct 2024 20:31:44 +0200 Subject: [PATCH 5/6] Better error handling + log messages. Signed-off-by: Camila Ayres --- .../NCContextMenu/NCClientInterface.cpp | 2 +- .../windows/NCUtil/CommunicationSocket.cpp | 57 ++++++++++++------- .../windows/NCUtil/CommunicationSocket.h | 8 ++- .../windows/NCUtil/RemotePathChecker.cpp | 9 ++- 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/shell_integration/windows/NCContextMenu/NCClientInterface.cpp b/shell_integration/windows/NCContextMenu/NCClientInterface.cpp index 80b9f1ea892b0..4b06b987d3c9a 100644 --- a/shell_integration/windows/NCContextMenu/NCClientInterface.cpp +++ b/shell_integration/windows/NCContextMenu/NCClientInterface.cpp @@ -59,7 +59,7 @@ NCClientInterface::ContextMenuInfo NCClientInterface::FetchInfo(const std::wstri while ((!receivedReplyFromDesktopClient && sleptCount < noReplyTimeout) || (receivedReplyFromDesktopClient && sleptCount < replyTimeout)) { logger << "trying to read a line" << std::endl; - if (socket.ReadLine(&response)) { + if (socket.ReadLine(&response, logger)) { logger << "received: " << StringUtil::toUtf8(response.c_str()) << std::endl; if (StringUtil::begins_with(response, wstring(L"REGISTER_PATH:"))) { logger << "received: REGISTER_PATH" << std::endl; diff --git a/shell_integration/windows/NCUtil/CommunicationSocket.cpp b/shell_integration/windows/NCUtil/CommunicationSocket.cpp index 06232675df089..60d7bd4e923db 100644 --- a/shell_integration/windows/NCUtil/CommunicationSocket.cpp +++ b/shell_integration/windows/NCUtil/CommunicationSocket.cpp @@ -28,6 +28,8 @@ using namespace std; namespace { +constexpr DWORD timeoutC = 100; + std::wstring getUserName() { DWORD len = DEFAULT_BUFLEN; TCHAR buf[DEFAULT_BUFLEN]; @@ -52,6 +54,7 @@ std::wstring CommunicationSocket::DefaultPipePath() CommunicationSocket::CommunicationSocket() : _pipe(INVALID_HANDLE_VALUE) { + _overlapped.hEvent = CreateEventW(nullptr, TRUE, FALSE, nullptr); } CommunicationSocket::~CommunicationSocket() @@ -72,7 +75,7 @@ bool CommunicationSocket::Close() bool CommunicationSocket::Connect(const std::wstring &pipename) { - _pipe = CreateFile(pipename.data(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); + _pipe = CreateFile(pipename.data(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr); if (_pipe == INVALID_HANDLE_VALUE) { return false; @@ -88,23 +91,29 @@ bool CommunicationSocket::SendMsg(const wchar_t* message, std::ofstream &logger) auto utf8_msg = StringUtil::toUtf8(message); DWORD numBytesWritten = 0; - auto result = WriteFile( _pipe, utf8_msg.c_str(), DWORD(utf8_msg.size()), &numBytesWritten, nullptr); - if (result) { - return true; - } else { - const_cast(this)->Close(); + if (!WriteFile(_pipe, utf8_msg.c_str(), static_cast(utf8_msg.size()), &numBytesWritten, &_overlapped)) { + if (GetLastError() == ERROR_IO_PENDING) { - return false; + if (WaitForSingleObject(_overlapped.hEvent, timeoutC) != WAIT_OBJECT_0) { + logger << "SendMsg timed out" << std::endl; + return false; + } + + if (!GetOverlappedResult(_pipe, &_overlapped, &numBytesWritten, FALSE)) { + logger << "GetOverlappedResult failed" << std::endl; + return false; + } + + } } + + return true; } -bool CommunicationSocket::ReadLine(wstring* response) +bool CommunicationSocket::ReadLine(wstring* response, std::ofstream &logger) const { - if (!response) { - return false; - } - + assert(response); response->clear(); if (_pipe == INVALID_HANDLE_VALUE) { @@ -120,26 +129,34 @@ bool CommunicationSocket::ReadLine(wstring* response) return true; } - std::array resp_utf8 = {}; + std::array resp_utf8; DWORD numBytesRead = 0; DWORD totalBytesAvailable = 0; - if (!PeekNamedPipe(_pipe, nullptr, 0, nullptr, &totalBytesAvailable, nullptr)) { - Close(); + if (!PeekNamedPipe(_pipe, NULL, 0, 0, &totalBytesAvailable, 0)) { return false; } if (totalBytesAvailable == 0) { - return false; + return true; } - if (!ReadFile(_pipe, resp_utf8.data(), DWORD(resp_utf8.size()), &numBytesRead, nullptr)) { - Close(); - return false; + if (!ReadFile(_pipe, resp_utf8.data(), DWORD(resp_utf8.size()), &numBytesRead, &_overlapped)) { + if (GetLastError() == ERROR_IO_PENDING) { + if (WaitForSingleObject(_overlapped.hEvent, timeoutC) != WAIT_OBJECT_0) { + logger << "ReadLine timed out" << std::endl; + } + if (!GetOverlappedResult(_pipe, &_overlapped, &numBytesRead, FALSE)) { + logger << "GetOverlappedResult failedt" << std::endl; + return false; + } + } else { + return false; + } } if (numBytesRead <= 0) { return false; } - _buffer.insert(_buffer.end(), resp_utf8.begin(), resp_utf8.begin()+numBytesRead); + _buffer.insert(_buffer.end(), resp_utf8.begin(), resp_utf8.begin() + numBytesRead); continue; } } diff --git a/shell_integration/windows/NCUtil/CommunicationSocket.h b/shell_integration/windows/NCUtil/CommunicationSocket.h index 0b631a849670f..eca3ea00f2787 100644 --- a/shell_integration/windows/NCUtil/CommunicationSocket.h +++ b/shell_integration/windows/NCUtil/CommunicationSocket.h @@ -35,15 +35,17 @@ class __declspec(dllexport) CommunicationSocket bool Connect(const std::wstring& pipename); bool Close(); - bool SendMsg(const wchar_t*, std::ofstream &logger) const; - bool ReadLine(std::wstring*); + bool SendMsg(const wchar_t *, std::ofstream &logger) const; + bool ReadLine(std::wstring *, std::ofstream &logger) const; HANDLE Event() { return _pipe; } private: HANDLE _pipe; - std::vector _buffer; + mutable std::vector _buffer; bool _connected = false; + + mutable OVERLAPPED _overlapped = {}; }; #endif diff --git a/shell_integration/windows/NCUtil/RemotePathChecker.cpp b/shell_integration/windows/NCUtil/RemotePathChecker.cpp index f6367f1efcdfd..4c8b513b87960 100644 --- a/shell_integration/windows/NCUtil/RemotePathChecker.cpp +++ b/shell_integration/windows/NCUtil/RemotePathChecker.cpp @@ -63,8 +63,9 @@ void RemotePathChecker::workerThreadLoop(ofstream &logger) if (!asked.count(filePath)) { asked.insert(filePath); if (!socket.SendMsg(wstring(L"RETRIEVE_FILE_STATUS:" + filePath + L'\n').data(), logger)) { + MessageBox(nullptr, L"stopping thread - socket.SendMsg RETRIEVE_FILE_STATUS returned false", L"Debugging", MB_OK); _stop = true; - logger << "stopping thread" << std::endl; + logger << "stopping thread - socket.SendMsg RETRIEVE_FILE_STATUS returned false" << std::endl; break; } } @@ -74,12 +75,16 @@ void RemotePathChecker::workerThreadLoop(ofstream &logger) std::wstring response; while (!_stop) { - if (!socket.ReadLine(&response)) { + if (!socket.ReadLine(&response, logger)) { socket.Close(); + logger << "closing socket, no more data to read" << std::endl; + MessageBox(nullptr, L"closing socket, no more data to read", L"Debugging", MB_OK); break; } if (response.empty()) { + logger << "closing socket, response is empty" << std::endl; + MessageBox(nullptr, L"closing socket,response is empty", L"Debugging", MB_OK); break; } From 40035024a1de05da5d7206815a2a4fb8db83869b Mon Sep 17 00:00:00 2001 From: Camila Ayres Date: Thu, 10 Oct 2024 21:34:55 +0200 Subject: [PATCH 6/6] Fix logs. Signed-off-by: Camila Ayres --- shell_integration/windows/NCOverlays/NCOverlay.cpp | 11 ++++++++--- .../windows/NCUtil/RemotePathChecker.cpp | 6 +++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/shell_integration/windows/NCOverlays/NCOverlay.cpp b/shell_integration/windows/NCOverlays/NCOverlay.cpp index 9d983b3966041..a7846e827042c 100644 --- a/shell_integration/windows/NCOverlays/NCOverlay.cpp +++ b/shell_integration/windows/NCOverlays/NCOverlay.cpp @@ -51,8 +51,9 @@ NCOverlay::NCOverlay(int state) : _referenceCount(1) , _state(state) { - m_logger.open("c:\\testOverlay.log"); - m_logger << "hello world" << std::endl; + // it is saved under %userprofile% + m_logger.open("C:\\overlay.log"); + m_logger << "debug" << std::endl; } NCOverlay::~NCOverlay(void) @@ -122,10 +123,11 @@ IFACEMETHODIMP NCOverlay::GetPriority(int *pPriority) IFACEMETHODIMP NCOverlay::IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib) { - RemotePathChecker* checker = getGlobalChecker(m_logger); + auto checker = getGlobalChecker(m_logger); std::shared_ptr> watchedDirectories = checker->WatchedDirectories(); if (watchedDirectories->empty()) { + m_logger << "list of watched directories are empty" << std::endl; return MAKE_HRESULT(S_FALSE, 0, 0); } @@ -138,13 +140,16 @@ IFACEMETHODIMP NCOverlay::IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib) } if (!watched) { + m_logger << "watched is false" << std::endl; return MAKE_HRESULT(S_FALSE, 0, 0); } int state = 0; if (!checker->IsMonitoredPath(pwszPath, &state)) { + m_logger << "not monitored path: " << pwszPath << std::endl; return MAKE_HRESULT(S_FALSE, 0, 0); } + return MAKE_HRESULT(state == _state ? S_OK : S_FALSE, 0, 0); } diff --git a/shell_integration/windows/NCUtil/RemotePathChecker.cpp b/shell_integration/windows/NCUtil/RemotePathChecker.cpp index 4c8b513b87960..2d3693990b17a 100644 --- a/shell_integration/windows/NCUtil/RemotePathChecker.cpp +++ b/shell_integration/windows/NCUtil/RemotePathChecker.cpp @@ -63,7 +63,7 @@ void RemotePathChecker::workerThreadLoop(ofstream &logger) if (!asked.count(filePath)) { asked.insert(filePath); if (!socket.SendMsg(wstring(L"RETRIEVE_FILE_STATUS:" + filePath + L'\n').data(), logger)) { - MessageBox(nullptr, L"stopping thread - socket.SendMsg RETRIEVE_FILE_STATUS returned false", L"Debugging", MB_OK); + //MessageBox(nullptr, L"stopping thread - socket.SendMsg RETRIEVE_FILE_STATUS returned false", L"Debugging", MB_OK); _stop = true; logger << "stopping thread - socket.SendMsg RETRIEVE_FILE_STATUS returned false" << std::endl; break; @@ -78,13 +78,13 @@ void RemotePathChecker::workerThreadLoop(ofstream &logger) if (!socket.ReadLine(&response, logger)) { socket.Close(); logger << "closing socket, no more data to read" << std::endl; - MessageBox(nullptr, L"closing socket, no more data to read", L"Debugging", MB_OK); + //MessageBox(nullptr, L"closing socket, no more data to read", L"Debugging", MB_OK); break; } if (response.empty()) { logger << "closing socket, response is empty" << std::endl; - MessageBox(nullptr, L"closing socket,response is empty", L"Debugging", MB_OK); + //MessageBox(nullptr, L"closing socket,response is empty", L"Debugging", MB_OK); break; }