Fix #29: stupid DOpus requires a more stupid "dopusrt.exe"... let OllyDbg fxxk it up

This commit is contained in:
Paddy Xu
2017-06-17 01:03:58 +03:00
parent bda5a38df1
commit 27afa85086
15 changed files with 2832 additions and 28 deletions

View File

@@ -0,0 +1,141 @@
// Copyright <20> 2017 Paddy Xu
//
// This file is part of QuickLook program.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdafx.h"
#include "DOpus.h"
#include "rapidxml.hpp"
#include <iostream>
#define DOPOUS_IPC_LP_INFO 0x00000015
#define DOPOUS_IPC_LP_DATA L"listsel"
#define DOPOUS_CLASS L"DOpus.ParentWindow"
#define DOPOUS_NAME L"Directory Opus"
#define MSGWINDOW_CLASS L"QuickLook.Native.DOpus.MsgWindow"
HWND hMsgWnd;
HANDLE hGetResultEvent;
PCHAR pXmlBuffer;
void DOpus::GetSelected(PWCHAR buffer)
{
/*
* CPU Disasm
* 6A44B588 |. 68 A839526A PUSH OFFSET 6A5239A8 ; /WindowName = "Directory Opus"
* 6A44B58D |. 68 6459526A PUSH OFFSET 6A525964 ; |ClassName = "DOpus.ParentWindow"
* 6A44B592 |. 894424 40 MOV DWORD PTR SS:[ESP+40],EAX ; |
* 6A44B596 |. C74424 30 140 MOV DWORD PTR SS:[ESP+30],14 ; |
* 6A44B59E |. FFD7 CALL EDI ; \USER32.FindWindowW
* ...
* 00BC2E9B |. 50 PUSH EAX ; /lParam = 12FE80C -> 15 ;
* 00BC2E9C |. 57 PUSH EDI ; |wParam ; class = dopusrt.getinfo
* 00BC2E9D |. 6A 4A PUSH 4A ; |Msg = WM_COPYDATA
* 00BC2E9F |. FF75 FC PUSH DWORD PTR SS:[LOCAL.1] ; |hWnd => [LOCAL.1] ; class = DOpus.ParentWindow, text = Directory Opus
* 00BC2EA2 |. FF15 0802C000 CALL DWORD PTR DS:[<&USER32.SendMessageW ; \USER32.SendMessageW
*
* CPU Stack
* 012FE80C |00000015 
* 012FE810 |00000010
* 012FE814 |013A26C0 ; UNICODE "listsel"
*/
if (hMsgWnd == nullptr)
PrepareMessageWindow();
if (hMsgWnd == nullptr)
return;
PWCHAR data = DOPOUS_IPC_LP_DATA;
COPYDATASTRUCT cds;
cds.dwData = DOPOUS_IPC_LP_INFO;
cds.cbData = (wcslen(data) + 1) * sizeof WCHAR;
cds.lpData = data;
auto ret = SendMessage(FindWindow(DOPOUS_CLASS, DOPOUS_NAME), WM_COPYDATA, (WPARAM)hMsgWnd, (LPARAM)&cds);
if (!ret)
return;
WaitForSingleObject(hGetResultEvent, 2000);
ParseXmlBuffer(buffer);
delete[] pXmlBuffer;
}
void DOpus::ParseXmlBuffer(PWCHAR buffer)
{
/*
* <?xml version="1.0" encoding="UTF-8"?>
* <results command="listsel" result="1">
* <items display_path="C:\folder" lister="0x707f6" path="C:\folder" tab="0xb0844">
* <item id="11" name="1.jpg" path="C:\folder\1.jpg" type="0" />
* <item id="12" name="2.zip" path="C:\folder\2.zip" type="1" />
* ...
*/
using namespace rapidxml;
xml_document<> doc;
doc.parse<0>(pXmlBuffer);
auto results = doc.first_node("results");
auto items = results->first_node("items");
for (auto item = items->first_node("item"); item; item = item->next_sibling("item"))
{
auto path = item->first_attribute("path")->value();
auto size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, path, -1, nullptr, 0);
auto b = new WCHAR[size];
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, path, -1, b, size);
wcscpy_s(buffer, MAX_PATH, b);
return; // we now cares only the first result
}
}
void DOpus::PrepareMessageWindow()
{
WNDCLASSEX wx = {'\0'};
wx.cbSize = sizeof(WNDCLASSEX);
wx.lpfnWndProc = msgWindowProc;
wx.lpszClassName = MSGWINDOW_CLASS;
if (RegisterClassEx(&wx))
hMsgWnd = CreateWindowEx(0, MSGWINDOW_CLASS, L"", 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, nullptr);
hGetResultEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
}
LRESULT CALLBACK DOpus::msgWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_COPYDATA:
{
auto cds = reinterpret_cast<PCOPYDATASTRUCT>(lParam);
auto buf = static_cast<PCHAR>(cds->lpData);
pXmlBuffer = new CHAR[cds->cbData + 1]{'\0'};
memcpy(pXmlBuffer, buf, cds->cbData);
SetEvent(hGetResultEvent);
return 0;
}
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}

View File

@@ -0,0 +1,27 @@
// Copyright <20> 2017 Paddy Xu
//
// This file is part of QuickLook program.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
class DOpus
{
public:
static void PrepareMessageWindow();
static void GetSelected(PWCHAR buffer);
private:
static void ParseXmlBuffer(PWCHAR buffer);
static LRESULT CALLBACK msgWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};

View File

@@ -49,6 +49,8 @@ void DialogHook::GetSelected(PWCHAR buffer)
if (!IsWow64Process(hProc, &isTargetWoW64))
return;
CloseHandle(hProc);
BOOL isSelfWoW64 = false;
if (!IsWow64Process(GetCurrentProcess(), &isSelfWoW64))
return;

View File

@@ -19,12 +19,14 @@
#include "Shell32.h"
#include "WoW64HookHelper.h"
#include "DOpus.h"
#define EXPORT extern "C" __declspec(dllexport)
EXPORT void LaunchWoW64HookHelper()
EXPORT void Init()
{
WoW64HookHelper::Launch();
DOpus::PrepareMessageWindow();
}
EXPORT Shell32::FocusedWindowType GetFocusedWindowType()

View File

@@ -83,8 +83,10 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="DialogHook.h" />
<ClInclude Include="DOpus.h" />
<ClInclude Include="Everything.h" />
<ClInclude Include="HelperMethods.h" />
<ClInclude Include="rapidxml.hpp" />
<ClInclude Include="WoW64HookHelper.h" />
<ClInclude Include="Shell32.h" />
<ClInclude Include="stdafx.h" />
@@ -100,6 +102,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="DOpus.cpp" />
<ClCompile Include="Everything.cpp" />
<ClCompile Include="HelperMethods.cpp" />
<ClCompile Include="DllExport.cpp" />

View File

@@ -36,6 +36,12 @@
<ClInclude Include="Everything.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DOpus.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="rapidxml.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
@@ -62,5 +68,8 @@
<ClCompile Include="Everything.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DOpus.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -21,6 +21,7 @@
#include "HelperMethods.h"
#include "DialogHook.h"
#include "Everything.h"
#include "DOpus.h"
using namespace std;
@@ -32,29 +33,33 @@ Shell32::FocusedWindowType Shell32::GetFocusedWindowType()
return INVALID;
WCHAR classBuffer[MAX_PATH] = {'\0'};
if (SUCCEEDED(GetClassName(hwndfg, classBuffer, MAX_PATH)))
if (FAILED(GetClassName(hwndfg, classBuffer, MAX_PATH)))
return INVALID;
if (wcscmp(classBuffer, L"dopus.lister") == 0)
{
if (wcscmp(classBuffer, L"EVERYTHING") == 0)
return DOPUS;
}
if (wcscmp(classBuffer, L"EVERYTHING") == 0)
{
return EVERYTHING;
}
if (wcscmp(classBuffer, L"WorkerW") == 0 || wcscmp(classBuffer, L"Progman") == 0)
{
if (FindWindowEx(hwndfg, nullptr, L"SHELLDLL_DefView", nullptr) != nullptr)
{
return EVERYTHING;
return DESKTOP;
}
if (wcscmp(classBuffer, L"WorkerW") == 0 || wcscmp(classBuffer, L"Progman") == 0)
}
if (wcscmp(classBuffer, L"ExploreWClass") == 0 || wcscmp(classBuffer, L"CabinetWClass") == 0)
{
return EXPLORER;
}
if (wcscmp(classBuffer, L"#32770") == 0)
{
if (FindWindowEx(hwndfg, nullptr, L"DUIViewWndClassName", nullptr) != nullptr)
{
if (FindWindowEx(hwndfg, nullptr, L"SHELLDLL_DefView", nullptr) != nullptr)
{
return DESKTOP;
}
}
if (wcscmp(classBuffer, L"ExploreWClass") == 0 || wcscmp(classBuffer, L"CabinetWClass") == 0)
{
return EXPLORER;
}
if (wcscmp(classBuffer, L"#32770") == 0)
{
if (FindWindowEx(hwndfg, nullptr, L"DUIViewWndClassName", nullptr) != nullptr)
{
return DIALOG;
}
return DIALOG;
}
}
@@ -77,6 +82,9 @@ void Shell32::GetCurrentSelection(PWCHAR buffer)
case EVERYTHING:
Everything::GetSelected(buffer);
break;
case DOPUS:
DOpus::GetSelected(buffer);
break;
default:
break;
}

View File

@@ -29,6 +29,7 @@ public:
EXPLORER,
DIALOG,
EVERYTHING,
DOPUS,
};
static FocusedWindowType GetFocusedWindowType();

File diff suppressed because it is too large Load Diff

View File

@@ -31,3 +31,4 @@
#include<shlguid.h>
#include<Shlobj.h>
#include<Shellapi.h>
#include<Psapi.h>

View File

@@ -21,6 +21,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\QuickLook.Native32\DOpus.cpp" />
<ClCompile Include="..\QuickLook.Native32\Everything.cpp" />
<ClCompile Include="..\QuickLook.Native32\HelperMethods.cpp" />
<ClCompile Include="..\QuickLook.Native32\Shell32.cpp" />

View File

@@ -9,5 +9,6 @@
<ClCompile Include="..\QuickLook.Native32\stdafx.cpp" />
<ClCompile Include="..\QuickLook.Native32\WoW64HookHelper.cpp" />
<ClCompile Include="..\QuickLook.Native32\Everything.cpp" />
<ClCompile Include="..\QuickLook.Native32\DOpus.cpp" />
</ItemGroup>
</Project>

View File

@@ -88,14 +88,13 @@ namespace QuickLook
if (e.Args.Contains("/first"))
AutoStartupHelper.CreateAutorunShortcut();
if (Is64Bit)
NativeMethods.QuickLook.LaunchWoW64HookHelper();
NativeMethods.QuickLook.Init();
PluginManager.GetInstance();
BackgroundListener.GetInstance();
PipeServerManager.GetInstance().MessageReceived +=
(msg, ea) => Dispatcher.BeginInvoke(
new Action(() => ViewWindowManager.GetInstance().InvokeViewer(msg as string)),
new Action(() => ViewWindowManager.GetInstance().InvokeViewer(msg as string, closeIfSame: true)),
DispatcherPriority.ApplicationIdle);
}

View File

@@ -25,6 +25,10 @@ namespace QuickLook.NativeMethods
{
private const int MaxPath = 260;
[DllImport("QuickLook.Native32.dll", EntryPoint = "Init",
CallingConvention = CallingConvention.Cdecl)]
private static extern void Init_32();
[DllImport("QuickLook.Native32.dll", EntryPoint = "GetFocusedWindowType",
CallingConvention = CallingConvention.Cdecl)]
private static extern FocusedWindowType GetFocusedWindowTypeNative_32();
@@ -33,9 +37,9 @@ namespace QuickLook.NativeMethods
CallingConvention = CallingConvention.Cdecl)]
private static extern void GetCurrentSelectionNative_32([MarshalAs(UnmanagedType.LPWStr)] StringBuilder sb);
[DllImport("QuickLook.Native64.dll", EntryPoint = "LaunchWoW64HookHelper",
[DllImport("QuickLook.Native64.dll", EntryPoint = "Init",
CallingConvention = CallingConvention.Cdecl)]
private static extern void LaunchWoW64HookHelper_64();
private static extern void Init_64();
[DllImport("QuickLook.Native64.dll", EntryPoint = "GetFocusedWindowType",
CallingConvention = CallingConvention.Cdecl)]
@@ -45,10 +49,12 @@ namespace QuickLook.NativeMethods
CallingConvention = CallingConvention.Cdecl)]
private static extern void GetCurrentSelectionNative_64([MarshalAs(UnmanagedType.LPWStr)] StringBuilder sb);
internal static void LaunchWoW64HookHelper()
internal static void Init()
{
if (App.Is64Bit)
LaunchWoW64HookHelper_64();
Init_64();
else
Init_32();
}
internal static FocusedWindowType GetFocusedWindowType()

View File

@@ -173,8 +173,15 @@ namespace QuickLook
}
}
internal bool InvokeViewer(string path = null, bool topMost = true)
internal bool InvokeViewer(string path = null, bool topMost = true, bool closeIfSame = false)
{
if(closeIfSame)
if (_currentMainWindow.Visibility == Visibility.Visible && path == _path)
{
ClosePreview();
return false;
}
if (path != null)
_path = path;