C++ Windows API - clipboard

C++ Windows API - clipboard
« kdy: 05. 09. 2020, 20:56:56 »
Ahojte,

potreboval by som naprogramovať aplikáciu ktorá na pozadí a checkuje zmeny v schránke windows.

Keď sa v hociktorej inej aplikácii niečo skopíruje do schránky (akcie cut, copy) tak moja aplikácia toto kopírovanie deteguje. Pozrie si obsah schránky a skopíruje ho na iné mesto v pamati.

Keď moja aplikácia deteguje vkladanie (paste), tak sa buď:

a) obsah vloží priamo z mojej aplikácie
b) alebo sa obsah vloží do schránky a z nej sa obsah vloží do tej aplikácie v ktorej bolo detegované vkladanie.

Ide mi proste o náhradu clipboardu z windows svojim vlastným clipboardom. Buď by sa clipboard nahradil úplne, alebo by sa windows clipboard prepojil s mojou aplikáciou (neviem čo je jednoduchšie).

Ako na to?

Mám odchytiť messages WM_PASTE a WM_COPYDATA? Určite existuje viacero možností ako to spraviť tak poprosím napíšte aspoň jednu. Vo windows api sa moc nevyznám, ale tak veľmi hrubo si to predstavujem asi tak že sa bude musieť hooknuť WndProc? A potom sa v ňom odchytiť príslušná správa? Ale ako to spraviť tak aby to fungovalo pre všetky aplikácie?


Re:C++ Windows API - clipboard
« Odpověď #1 kdy: 05. 09. 2020, 22:06:15 »
Pokud programujete pro Windows Vista a novější, pro sledování obsahu schránky můžete využít AddClipboardFormatListener.
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-addclipboardformatlistener

Pokud potřebujete podporovat i Windows XP, musíte využít funkci ChangeClipboardChain. Zde musíte být opatrný, abyste nerozbil ostatní aplikace, protože zde v zásadě dochází k vytváření spojového seznamu oken, kterým se má notifikace posílat. Ten samozřejmě nesmíte rozpojit...

Pak budete potřebovat funkce na přístup k obsahu schránky. Ten samý obsah může být uložen ve více různých formátech, takže si můžete vybrat ten nejvhodnější pro vaši aplikaci. Pozor na to, že aplikace si může přidat vlastní formát.

Co se týče vámi navrhované metody monitorování zpráv, pro kterou se obvykle používá termín subclassing, není přísliš vhodná, chcete-li monitorovat všechny aplikace na daném desktopu či window station. Pro tento účel se lépe hodí tzv. Háky Windows (mrkněte na funkci SetWindowsHookEx). I zde ale musíte být velmi opatrný, abyste nerozbil jiné aplikace. V podstatě totiž systém přimějete, aby do každé vhodné aplikace injektoval vaší DLL knihovnu, která pak bude odposlouchávat (a teoreticky i upravovat) zprávy zasílané jejím oknům. Je třeba opravdu pečlivě číst dokumentaci.

tecka

Re:C++ Windows API - clipboard
« Odpověď #2 kdy: 05. 09. 2020, 22:45:53 »
Já na Linuxu používám ClipIt a zdá se, že je dost alternativ i pro Windows.
https://alternativeto.net/software/clipit/?license=opensource&platform=windows

Re:C++ Windows API - clipboard
« Odpověď #3 kdy: 05. 09. 2020, 23:26:46 »
Pokud programujete pro Windows Vista a novější, pro sledování obsahu schránky můžete využít AddClipboardFormatListener.
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-addclipboardformatlistener

Pokud potřebujete podporovat i Windows XP, musíte využít funkci ChangeClipboardChain. Zde musíte být opatrný, abyste nerozbil ostatní aplikace, protože zde v zásadě dochází k vytváření spojového seznamu oken, kterým se má notifikace posílat. Ten samozřejmě nesmíte rozpojit...

Pak budete potřebovat funkce na přístup k obsahu schránky. Ten samý obsah může být uložen ve více různých formátech, takže si můžete vybrat ten nejvhodnější pro vaši aplikaci. Pozor na to, že aplikace si může přidat vlastní formát.

Co se týče vámi navrhované metody monitorování zpráv, pro kterou se obvykle používá termín subclassing, není přísliš vhodná, chcete-li monitorovat všechny aplikace na daném desktopu či window station. Pro tento účel se lépe hodí tzv. Háky Windows (mrkněte na funkci SetWindowsHookEx). I zde ale musíte být velmi opatrný, abyste nerozbil jiné aplikace. V podstatě totiž systém přimějete, aby do každé vhodné aplikace injektoval vaší DLL knihovnu, která pak bude odposlouchávat (a teoreticky i upravovat) zprávy zasílané jejím oknům. Je třeba opravdu pečlivě číst dokumentaci.

Ďakujem za vyčerpávajúce info. Tie hooky som skúšal  ešte na začiatku, hook na wnd proc som mal v exernom DLLku, ale asi som robil niečo zlé lebo mi to nefungovalo.

Medzitým som si, ale na githube našiel príklad pre inšpiráciu - jednu appku, ktorá pracuje so schránkou (príklad je v C# takže som to musel prepísať do C++).

Tu je kód tej inšpirácie v C#:

https://github.com/chrisnas/DebuggingExtensions/blob/b3c38e5e3d95f1f53ce26bbe1209569716e60714/src/LeakShell/ClipboardListener.cs#L124,L165

Keď si zadefinujem:

Kód: [Vybrat]
HWND nextInChain = SetClipboardViewer(hWnd);
tak potom sa mi pri cut + copy akcii v akejkoľvek windows aplikácii triggeruje WM_DRAWCLIPBOARD ktoré zachytávam vo WndProc taktiež tam riešim WM_CHANGECBCHAIN (ako ste spomínali). Po skončení aplikácie zavolám ChangeClipboardChain(hWnd, nextInChain);

Kód: [Vybrat]
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_CHANGECBCHAIN:
    {
    if ((HWND)wParam == nextInChain)
    {
    nextInChain = (HWND)lParam;
    }
    else if (nextInChain != NULL)
    {
    SendMessage(nextInChain, message, wParam, lParam);
    }
    }
    break;
    case WM_DRAWCLIPBOARD:
        {
            if (attachedToClipboard && nextInChain != NULL)
            {
                /*** TU MOŽEM ZACHYTÁVAŤ KOPÍROVANIE ***/
                SendMessage(nextInChain, message, wParam, lParam);
            }
        }
        break;

Každopádne AddClipboardFormatListener a RemoveClipboardFormatListener bude na tento účel asi adresnejšie (idem to vyskúšať). Akurát týmto mám vyriešené len CUT a COPY akcie. Ale ako mám zachytiť PASTE?

Re:C++ Windows API - clipboard
« Odpověď #4 kdy: 05. 09. 2020, 23:31:06 »
Já na Linuxu používám ClipIt a zdá se, že je dost alternativ i pro Windows.
https://alternativeto.net/software/clipit/?license=opensource&platform=windows

Dík za tip. V linuxe vyskúšam ten ClipIt. Ale vo windows potrebujem niečo presne na mieru mojim potrebám. Mám pár nápadov, ktoré som ešte nevidel v žiadnej aplikácii tohto druhu. A okrem toho je to dobrý spôsob ako sa niečo nové naučiť. Keď to budem mať hotové tak to hodím na github.


Re:C++ Windows API - clipboard
« Odpověď #5 kdy: 05. 09. 2020, 23:41:47 »
Takže vyskúšal som to AddClipboardFormatListener funguje podobne ako SetClipboardViewer, akurát sa namiesto WM_DRAWCLIPBOARD triggeruje WM_CLIPBOARDUPDATE.

Ešte musím vyriešiť PASTE

Re:C++ Windows API - clipboard
« Odpověď #6 kdy: 06. 09. 2020, 20:49:27 »
Tak som to včera v noci skúšal vyriešiť (podľa rád Martin-a Dráb-a), ale funguje mi zatiaľ len copy + cut, na paste budem musieť použiť asi tie hooky lebo iná možnosť ako odchytiť paste neexistuje:

https://pastebin.com/Z5YNnnLm POZN: Toto je samozrejme len prototyp, preto tam nepoužívam exceptiony, ale chyby vypisujem priamo na ostream vo svojej appke to potom celé wrapnem do objektov.


Re:C++ Windows API - clipboard
« Odpověď #7 kdy: 07. 09. 2020, 11:03:19 »
Na Paste není žádný univerzální postup, protože si to aplikace může řešit sama jak se jí zachce. Teoreticky se může hodit zachytit klávesovou zkratku Ctrl+V, potlačit V pokud je aktivní ta správná aplikace, zpracovat schránku a pak s pomocí SendInput poslat nové Ctrl+V. Hook na zachycování má příznak, jestli jde o opravdovou událost nebo umělou, takže tím se odliší SendInput od HW stisku a nezpracuje se. Samozřejmě, když uživatel klikne v nabídce na Vložit, tak je to marné.
Zpracování zachycené zprávy by mělo být co nejrychlejší, jinak to systém odřízne.

Re:C++ Windows API - clipboard
« Odpověď #8 kdy: 07. 09. 2020, 12:15:58 »
Na Paste není žádný univerzální postup, protože si to aplikace může řešit sama jak se jí zachce. Teoreticky se může hodit zachytit klávesovou zkratku Ctrl+V, potlačit V pokud je aktivní ta správná aplikace, zpracovat schránku a pak s pomocí SendInput poslat nové Ctrl+V. Hook na zachycování má příznak, jestli jde o opravdovou událost nebo umělou, takže tím se odliší SendInput od HW stisku a nezpracuje se. Samozřejmě, když uživatel klikne v nabídce na Vložit, tak je to marné.
Zpracování zachycené zprávy by mělo být co nejrychlejší, jinak to systém odřízne.

Ďakujem za informácie. No veď toto je práve ten problém, že užívateľ nemusí pri pastovaní používať skratku Ctrl+V a potom to neni dostatočne univerzálne riešenie.

Ale teraz ma napadol ešte jeden spôsob ako to celé obísť, bez toho aby som potreboval zachytávať paste.

Nechcem to teraz prezrádzať lebo tým by som prezradil aj iné nápady (týkajúce sa schránky), ale keď budem mať hotovú celú appku tak sem dám link na github, že ako som to vyriešil.

RDa

  • *****
  • 989
    • Zobrazit profil
    • E-mail
Re:C++ Windows API - clipboard
« Odpověď #9 kdy: 07. 09. 2020, 14:24:27 »
Delat to pres hook na CTRL+V je blby... to jeste musis taky davat pozor zda to neni ctrl+SHIFT+v nebo s alt-em.. nektere mail editory tak maj paste-without-formatting. A pak buhvi zda jina aplikace nepouziva ctrl+v pro neco co nesouvisi se schranou, takze bys mel udrzovat blacklist.

Nejde nainstalovat neco jako "Windows kernel breakpoint" ? Tam, kudy to tece v pripade Paste (neco jako GetData nebo jina funkce), a kdyz uz to budete delat.. udelejte PRE_PASTE i POST_PASTE event (hook).

Re:C++ Windows API - clipboard
« Odpověď #10 kdy: 07. 09. 2020, 22:05:50 »
Citace
Nejde nainstalovat neco jako "Windows kernel breakpoint" ? Tam, kudy to tece v pripade Paste (neco jako GetData nebo jina funkce), a kdyz uz to budete delat.. udelejte PRE_PASTE i POST_PASTE event (hook).
O tom celkem pochybuju. Paste může obecně fungovat tak, že aplikace prostě otevře schránku, načte z ní data, nějak je zpracuje a následně je někam vyplivne. Pokud takováto operace nemá žádné vedlejší efekty.

Pokud by práce se schránkou vyžadovala nějaký přechod z kernelu do usermode (KeUserModeCallback), byla by šance takovou akci zachytit. Díky tomuto mechanismu například aplikace může implementovat ochranu proti některým typům injekcí či sledování (např. se do ní nedoustanou DLLky injektované přes SetWindowsHookEx).

Re:C++ Windows API - clipboard
« Odpověď #11 kdy: 08. 09. 2020, 11:57:01 »
Ještě jsem si vzpomněl, že existuje cesta, před hodně lety jsem to dělal. Když aplikace volá GetClipboardData tak se dá volání funkce z User32.dll přesměrovat na vlastní kód, předělat data ze schránky a pak vrátit volání na původní funkci. Aplikace pro schránku musí mít práva amina aby mohla měnit kód dll za běhu. Nevýhoda byla, že se to muselo dělat pro každou aplikaci zvlášť, protože aplikace používají vlastní kopii dll.

Re:C++ Windows API - clipboard
« Odpověď #12 kdy: 08. 09. 2020, 19:54:47 »
Citace
Ještě jsem si vzpomněl, že existuje cesta, před hodně lety jsem to dělal. Když aplikace volá GetClipboardData tak se dá volání funkce z User32.dll přesměrovat na vlastní kód, předělat data ze schránky a pak vrátit volání na původní funkci. Aplikace pro schránku musí mít práva amina aby mohla měnit kód dll za běhu. Nevýhoda byla, že se to muselo dělat pro každou aplikaci zvlášť, protože aplikace používají vlastní kopii dll.

Administrátorská práva zajišťují, že aplikace se dostane prakticky do každého normálního procesu, kde pak může modifikovat user32!GetClipboardData. Pro aplikace běžící pod stejném uživatelem a na stejné úrovni integrity obvykle taková oprávnění nejsou potřeba.

Tohle samozřejmě bude fungovat. Cílová aplikace se ale může rozhodnout, že se jí ty cizí modifikace user32.dll nelíbí a něco s tím udělat. Případně může používat různé process mitigation policies, které injektování kódu do ní značně ztíží.