// Copyright © 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 . #include "stdafx.h" #include "DOpus.h" #include "rapidxml.hpp" #include #define DOPUS_IPC_LP_INFO 0x00000015 #define DOPUS_IPC_LP_DATA L"listsel" #define DOPUS_CLASS L"DOpus.ParentWindow" #define DOPUS_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 = DOPUS_IPC_LP_DATA; COPYDATASTRUCT cds; cds.dwData = DOPUS_IPC_LP_INFO; cds.cbData = static_cast(wcslen(data) + 1) * sizeof WCHAR; cds.lpData = data; auto ret = SendMessage(FindWindow(DOPUS_CLASS, DOPUS_NAME), WM_COPYDATA, reinterpret_cast(hMsgWnd), reinterpret_cast(&cds)); if (!ret) return; WaitForSingleObject(hGetResultEvent, 2000); ParseXmlBuffer(buffer); delete[] pXmlBuffer; } void DOpus::ParseXmlBuffer(PWCHAR buffer) { /* * * * * * * ... */ 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); delete[] b; return; // we now cares only the first result } } void DOpus::PrepareMessageWindow() { WNDCLASSEX wx = {sizeof wx}; 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(lParam); auto buf = static_cast(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); } }