Skip to content

Commit

Permalink
Mooore aggressive GC; rewrite native dll
Browse files Browse the repository at this point in the history
  • Loading branch information
xupefei committed May 28, 2017
1 parent 13dfa7a commit 5ad20b8
Show file tree
Hide file tree
Showing 15 changed files with 211 additions and 311 deletions.
16 changes: 3 additions & 13 deletions QuickLook.Native.Shell32/QuickLook.Native.Shell32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,12 @@

#define EXPORT extern "C" __declspec(dllexport)

EXPORT int GetFocusedWindowType()
EXPORT Shell32::FocusedWindowType GetFocusedWindowType()
{
return Shell32::GetFocusedWindowType();
}

EXPORT void SaveCurrentSelection()
EXPORT void GetCurrentSelection(PWCHAR buffer)
{
Shell32::SaveCurrentSelection();
}

EXPORT int GetCurrentSelectionCount()
{
return Shell32::GetCurrentSelectionCount();
}

EXPORT void GetCurrentSelectionBuffer(PWCHAR buffer)
{
Shell32::GetCurrentSelectionBuffer(buffer);
Shell32::GetCurrentSelection(buffer);
}
237 changes: 92 additions & 145 deletions QuickLook.Native.Shell32/Shell32.cpp
Original file line number Diff line number Diff line change
@@ -1,166 +1,136 @@
#include "stdafx.h"

#include "Shell32.h"
#include <atlcomcli.h>

using namespace std;

vector<wstring> Shell32::vector_items;

void Shell32::SaveCurrentSelection()
Shell32::FocusedWindowType Shell32::GetFocusedWindowType()
{
vector_items.clear();
auto type = INVALID;

auto hwndfg = GetForegroundWindow();

if (isCursorActivated(hwndfg))
return INVALID;

auto classBuffer = new WCHAR[MAX_PATH];
if (SUCCEEDED(GetClassName(hwndfg, classBuffer, MAX_PATH)))
{
if (wcscmp(classBuffer, L"WorkerW") == 0 || wcscmp(classBuffer, L"Progman") == 0)
{
if (FindWindowEx(hwndfg, nullptr, L"SHELLDLL_DefView", nullptr) != nullptr)
{
type = DESKTOP;
}
}
else if (wcscmp(classBuffer, L"ExploreWClass") == 0 || wcscmp(classBuffer, L"CabinetWClass") == 0)
{
type = EXPLORER;
}
}
delete[] classBuffer;

return type;
}

void Shell32::GetCurrentSelection(PWCHAR buffer)
{
switch (GetFocusedWindowType())
{
case EXPLORER:
SaveSelectedFromExplorer();
getSelectedFromExplorer(buffer);
break;
case DESKTOP:
SaveSelectedFromDesktop();
getSelectedFromDesktop(buffer);
break;
default:
break;
}
}

UINT Shell32::GetCurrentSelectionCount()
{
return vector_items.size();
}

void Shell32::GetCurrentSelectionBuffer(PWCHAR buffer)
{
PWCHAR pos = buffer;

for (vector<wstring>::iterator it = vector_items.begin(); it < vector_items.end(); ++it)
{
int l = it->length();
wcscpy_s(pos, l + 1, it->c_str());

pos += l;

// overwrite NULL
wcscpy_s(pos++, 2, L"|");
}

// remove last "|"
wcscpy_s(pos - 1, 1, L"");
}

void Shell32::SaveSelectedFromExplorer()
void Shell32::getSelectedFromExplorer(PWCHAR buffer)
{
CoInitialize(nullptr);

CComPtr<IShellWindows> psw;
HRESULT ret = psw.CoCreateInstance(CLSID_ShellWindows);
if (FAILED(psw.CoCreateInstance(CLSID_ShellWindows)))
return;

auto hwndFGW = GetForegroundWindow();

auto fFound = FALSE;
auto count = 0L;
psw->get_Count(&count);

for (int i = 0; !fFound; i++)
for (auto i = 0; i < count; i++)
{
VARIANT vi;
V_VT(&vi) = VT_I4;
V_I4(&vi) = i;

CComPtr<IDispatch> pdisp;
// ReSharper disable once CppSomeObjectMembersMightNotBeInitialized
if (SUCCEEDED(psw->Item(vi, &pdisp)))
{
CComPtr<IWebBrowserApp> pwba;
if (SUCCEEDED(pdisp->QueryInterface(IID_IWebBrowserApp, reinterpret_cast<void**>(&pwba))))
{
HWND hwndWBA;
if (SUCCEEDED(pwba->get_HWND(reinterpret_cast<LONG_PTR*>(&hwndWBA))) && hwndWBA == hwndFGW)
{
fFound = TRUE;

CComPtr<IDispatch> ppdisp;
if (SUCCEEDED(pwba->get_Document(&ppdisp)))
{
CComPtr<IShellFolderViewDual2> pshvd;
if (SUCCEEDED(ppdisp->QueryInterface(IID_IShellFolderViewDual2, reinterpret_cast<void**>(&pshvd))))
{
CComPtr<FolderItems> pfis;
if (SUCCEEDED(pshvd->SelectedItems(&pfis)))
{
LONG pCount = 0L;
pfis->get_Count(&pCount);

for (int ii = 0; ii < pCount; ii++)
{
VARIANT vii;
V_VT(&vii) = VT_I4;
V_I4(&vii) = ii;

CComPtr<FolderItem> pfi;
// ReSharper disable once CppSomeObjectMembersMightNotBeInitialized
if (SUCCEEDED(pfis->Item(vii, &pfi)))
{
CComBSTR pbs = SysAllocStringLen(L"", MAX_PATH);
pfi->get_Path(&pbs);

wstring ws = wstring(pbs);
ws.shrink_to_fit();

vector_items.push_back(ws);
}
}
}
}
}
}
}
}
if (FAILED(psw->Item(vi, &pdisp)))
continue;

CComQIPtr<IWebBrowserApp> pwba;
if (FAILED(pdisp->QueryInterface(IID_IWebBrowserApp, reinterpret_cast<void**>(&pwba))))
continue;

HWND hwndWBA;
if (FAILED(pwba->get_HWND(reinterpret_cast<LONG_PTR*>(&hwndWBA))))
continue;

if (hwndWBA != hwndFGW || isCursorActivated(hwndWBA))
continue;

getSelectedInternal(pwba, buffer);
}
}

CComQIPtr<IWebBrowser2> Shell32::AttachDesktopShellWindow()
void Shell32::getSelectedFromDesktop(PWCHAR buffer)
{
CoInitialize(nullptr);

CComPtr<IShellWindows> psw;
CComQIPtr<IWebBrowser2> pdispOut;
CComQIPtr<IWebBrowserApp> pwba;

if (SUCCEEDED(psw.CoCreateInstance(CLSID_ShellWindows)))
{
VARIANT pvarLoc = {VT_EMPTY};
long phwnd;
psw->FindWindowSW(&pvarLoc, &pvarLoc, SWC_DESKTOP, &phwnd, SWFO_NEEDDISPATCH, reinterpret_cast<IDispatch**>(&pdispOut));
}
return pdispOut;
if (FAILED(psw.CoCreateInstance(CLSID_ShellWindows)))
return;

VARIANT pvarLoc = {VT_EMPTY};
long phwnd;
if (FAILED(psw->FindWindowSW(&pvarLoc, &pvarLoc, SWC_DESKTOP, &phwnd, SWFO_NEEDDISPATCH, reinterpret_cast<IDispatch**>(&pwba))))
return;

if (isCursorActivated(reinterpret_cast<HWND>(phwnd)))
return;

getSelectedInternal(pwba, buffer);
}

void Shell32::SaveSelectedFromDesktop()
void Shell32::getSelectedInternal(CComQIPtr<IWebBrowserApp> pwba, PWCHAR buffer)
{
auto pWebBrowser2 = AttachDesktopShellWindow();
CComQIPtr<IServiceProvider> psp;
if (FAILED(pwba->QueryInterface(IID_IServiceProvider, reinterpret_cast<void**>(&psp))))
return;

if (!pWebBrowser2)
CComPtr<IShellBrowser> psb;
if (FAILED(psp->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, reinterpret_cast<LPVOID*>(&psb))))
return;

CComQIPtr<IServiceProvider> psp(pWebBrowser2);
CComPtr<IShellView> psv;
if (FAILED(psb->QueryActiveShellView(&psv)))
return;

if (!psp) return;
CComPtr<IDataObject> dao;
if (FAILED(psv->GetItemObject(SVGIO_SELECTION, IID_IDataObject, reinterpret_cast<void**>(&dao))))
return;

CComPtr<IShellBrowser> psb;
if (SUCCEEDED(psp->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, reinterpret_cast<LPVOID*>(&psb))))
{
CComPtr<IShellView> psv;
if (SUCCEEDED(psb->QueryActiveShellView(&psv)))
{
CComPtr<IFolderView> pfv;
if (SUCCEEDED(psv->QueryInterface(IID_IFolderView, reinterpret_cast<void**>(&pfv))))
{
CComPtr<IDataObject> dao;
if (SUCCEEDED(psv->GetItemObject(SVGIO_SELECTION, IID_IDataObject, reinterpret_cast<void**>(&dao))))
vectorFromDataObject(dao);
}
}
}
return obtainFirstItem(dao, buffer);
}

void Shell32::vectorFromDataObject(CComPtr<IDataObject> dao)
void Shell32::obtainFirstItem(CComPtr<IDataObject> dao, PWCHAR buffer)
{
FORMATETC formatetc;
STGMEDIUM medium;
Expand All @@ -173,45 +143,22 @@ void Shell32::vectorFromDataObject(CComPtr<IDataObject> dao)

medium.tymed = TYMED_HGLOBAL;

if (SUCCEEDED(dao->GetData(&formatetc, &medium)))
{
int n = DragQueryFile(HDROP(medium.hGlobal), 0xFFFFFFFF, nullptr, 0);
if (FAILED(dao->GetData(&formatetc, &medium)))
return;

for (int i = 0; i < n; i++)
{
WCHAR buffer[MAX_PATH];
DragQueryFile(HDROP(medium.hGlobal), i, buffer, MAX_PATH - 1);
int n = DragQueryFile(HDROP(medium.hGlobal), 0xFFFFFFFF, nullptr, 0);

wstring ws = wstring(buffer);
ws.shrink_to_fit();
if (n < 1)
return;

vector_items.push_back(ws);
}
}
DragQueryFile(HDROP(medium.hGlobal), 0, buffer, MAX_PATH - 1);
}

Shell32::FocusedWindowType Shell32::GetFocusedWindowType()
bool Shell32::isCursorActivated(HWND hwnd)
{
auto type = INVALID;
auto tId = GetWindowThreadProcessId(hwnd, nullptr);

auto hwndfg = GetForegroundWindow();

auto classBuffer = new WCHAR[MAX_PATH];
if (SUCCEEDED(GetClassName(hwndfg, classBuffer, MAX_PATH)))
{
if (wcscmp(classBuffer, L"WorkerW") == 0 || wcscmp(classBuffer, L"Progman") == 0)
{
if (FindWindowEx(hwndfg, nullptr, L"SHELLDLL_DefView", nullptr) != nullptr)
{
type = DESKTOP;
}
}
else if (wcscmp(classBuffer, L"ExploreWClass") == 0 || wcscmp(classBuffer, L"CabinetWClass") == 0)
{
type = EXPLORER;
}
}
delete[] classBuffer;

return type;
GUITHREADINFO gui = {sizeof gui};
GetGUIThreadInfo(tId, &gui);
return gui.flags || gui.hwndCaret;
}
15 changes: 6 additions & 9 deletions QuickLook.Native.Shell32/Shell32.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,13 @@ class Shell32
};

static FocusedWindowType GetFocusedWindowType();
static void SaveCurrentSelection();
static UINT GetCurrentSelectionCount();
static void GetCurrentSelectionBuffer(PWCHAR buffer);
static void GetCurrentSelection(PWCHAR buffer);

private:
static std::vector<std::wstring> vector_items;
static void getSelectedFromDesktop(PWCHAR buffer);
static void getSelectedFromExplorer(PWCHAR buffer);

static void SaveSelectedFromDesktop();
static void SaveSelectedFromExplorer();

static CComQIPtr<IWebBrowser2> AttachDesktopShellWindow();
static void vectorFromDataObject(CComPtr<IDataObject> dao);
static void getSelectedInternal(CComQIPtr<IWebBrowserApp> pWebBrowserApp, PWCHAR buffer);
static void obtainFirstItem(CComPtr<IDataObject> dao, PWCHAR buffer);
static bool isCursorActivated(HWND hwndfg);
};
1 change: 1 addition & 0 deletions QuickLook/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq;
using System.Reflection;
using System.Windows;
using QuickLook.Helpers;

namespace QuickLook
{
Expand Down
1 change: 1 addition & 0 deletions QuickLook/BackgroundListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ protected BackgroundListener()
public void Dispose()
{
_hook?.Dispose();
_hook = null;
}

private void HotkeyEventHandler(object sender, KeyEventArgs e)
Expand Down
Loading

0 comments on commit 5ad20b8

Please sign in to comment.