Solved

Injecting DLL into a running thread

Posted on 2004-04-12
23
1,083 Views
Last Modified: 2007-12-19
(C# code calling C++ dll that uses Assembly instructions, which hooks directly into the Win32 API...Yup, I'm going to hell). Ok, Dr. Ryan wants to work on a live patient. I know that SetWindowsHookEx will let me throw a dll into a live thread.

1.) Is this correct:

[DllImport("user32.dll", SetLastError=true)]
public static extern IntPtr SetWindowsHookEx(int idHook, HOOKPROC callback,      IntPtr hMod, IntPtr dwThreadId);

2.) How do I get info I need to attach to a process, say Notepad.exe. (ThreadID, hMod).

3.) How do I call functions for the dll that is attached to the process? (call it normally....or).

Code that needs for the hook to work properly (called once per thread):
IntPtr hook = PaintHook.CreatePaintHook();      
PaintHook.SubClass(hook, hWnd);

Code that should be called at my leisure (repeatedly):
Nevermind.

I cannot call this dll with hWnd of the process externally. It needs to be called internally. Something about GDI not liking process boundries.

Thanks,
Ryan
Mad Scientist
0
Comment
Question by:rossryan
  • 10
  • 9
  • 4
23 Comments
 
LVL 22

Expert Comment

by:_TAD_
ID: 10805862

hmm.... interesting!   Sorry I can't help though... I'm not real familiar with this aspect of C#.


I will say this though....  You may need to work with "unsafe" code in order to get/use the pointers properly.  

IntPtr myPointer = new IntPtr(void* function);


also...

Here's a site on WinAPI
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winprog/winprog/functions_by_category.asp




Also, I'm sure you've seen this, but just in case... (from Micrososft)

lpfn <HOOKPROC callback>
[in] Pointer to the hook procedure. If the dwThreadId parameter is zero or specifies the identifier of a thread created by a different process, the lpfn parameter must point to a hook procedure in a dynamic-link library (DLL). Otherwise, lpfn can point to a hook procedure in the code associated with the current process.

hMod
[in] Handle to the DLL containing the hook procedure pointed to by the lpfn parameter. The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process.

dwThreadId
[in] Specifies the identifier of the thread with which the hook procedure is to be associated. If this parameter is zero, the hook procedure is associated with all existing threads running in the same desktop as the calling thread.
0
 
LVL 22

Expert Comment

by:_TAD_
ID: 10805874


If you find a solution, please post some of it here, I'd be interested in seeing the end result.

Good Luck!
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10806442
1) Move from C# to managed C++. This allows to use unmanaged code writing mixed applications.
2) Read this article:
http://www.codeproject.com/threads/winspy.asp

You are trying to do things which are out of C# score.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10806451
Obviously, I mean "out of scope".
0
 
LVL 22

Expert Comment

by:_TAD_
ID: 10809408


C# does allow for unmanaged code writing, you just need to use the "unsafe" keyword.

In essence, it is like codeing C++ in a C# app... but not quite.
0
 

Author Comment

by:rossryan
ID: 10809987
I don't think it's quite out of scope, just a matter of translating some calls.

HOOKPROC callback;
static IntPtr hinstDLL;
static IntPtr hhookSysMsg;
 
hinstDLL = LoadLibrary("c:\\windows\\sysmsg.dll");
hkprcSysMsg = (HOOKPROC)GetProcAddress(hinstDLL, "SysMessageProc");
hhookSysMsg = SetWindowsHookEx(WH_SYSMSGFILTER,hkprcSysMsg,hinstDLL,0);

Still working, but it looks like you load the library into memory, provide a pointer to it, and create a delegate/callback for the messages.

Since I'm impatient, I'm going to generate the message myself (WM_PAINT). When the message is sent, the hook will activate, capturing the painted window...hmmm.

WH_CALLWNDPROC <= the code I am stealing the hook from specifies the windows proc, so this flag must be it.

Then the question is, how do I grab the Thread ID of a process, say Notepad?


0
 
LVL 22

Expert Comment

by:_TAD_
ID: 10810474


They call it a thread id, but isn't it really the pid (process ID)?  You can get the process handle which returns an IntPtr object.

The process handle is a unique identifier.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10810526
There is no problem to translate single API calls to C#. The problem is to make the whole thing working. Global hook requires hook function been placed in Dll, which is loaded to another process address space. This Dll must be unmanaged Dll. Unfortunately, I have no experience of writing global hooks, except simple WH_KEYBOARD_LL and WH_MOUSE_LL.

>> How do I grab the Thread ID of a process, say Notepad?
Use  GetWindowThreadProcessId API.

I suggest you also describe your current program state and what are you trying to do (what kind of hook do you have, what is working now etc.) and post question in Windows Programming area. C++ Programmers who have experience of writing global hook possibly can help you.
0
 

Author Comment

by:rossryan
ID: 10810590
Aright, Alex, you know more about this stuff than I do. Here's the email from Fen Yuan:

Yes. The problem is GDI handle does not work across process boundary.
 
To solve the problem, put the code into a DLL, inject it into the target process using SetWindowsHookEx and then control it to capture a window.

Regards
 
Feng Yuan
----- Original Message -----
From: Ryan Ross
To: fyuan@fengyuan.com
Sent: Sunday, April 11, 2004 11:05 PM
Subject: Window Contents Capturing


Pardon the intrusion, but is it possible for your PaintHook class to work other windows?

 

“Handling WM_PrintClient Messages without a Source Code change” -> Perhaps I should rephrase: is it possible to feed this class the handle to another (already loaded window, Notepad.exe for instance), and expect it to work properly (i.e. capture the whole window)?

 

Many thanks,

Ryan  




Given that it takes two calls to get the Hook installed, and I do not know how to install a hook from a dll that is loaded into a running program, much less how to control it, who should I contact && how should I phrase the question?

I'm seriously out of my league with this stuff (I think you know that). The dll is built, unless I need to add the capture class (for bitmaps from window handles) to the mix...

I mean, do I install the hook, then proceed as normal? I.e. use SetWindowHookEx to install the PaintHook (to Notepad), then use the capture class to grab the window from my program (which uses the window handle to capture, but then his email says GDI doesn't like to cross boundries, or it just the PaintHook that doesn't like that?). Or do I need to add that class to the dll, and pull only the bitmap of the window into my program?


Feng Yuan's credentials are impressive (Phd, works at HP). He wrote a book on GDI programming, which I think I'll pick up later...

Basically, I know this class is the last chance to provide the kind of functionality I need in my program, but I do not know enough about Win32, Assembly, and the x86 architecture to do more than I have. So, whatever information you can grep from his email or about this whole thing (aside from the fact that I will be spending more time in C++ land) would be immensely helpful.

Thanks,
Ryan

0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10810845
If I understand this, you get your paint hook working inside of your process, but you need to do the same for another process. To do this you need to inject your code into another process. CodeProject article http://www.codeproject.com/threads/winspy.asp describes how to to this. Jeffrey Richter's article "Load Your 32-bit DLL into Another Process's Address Space Using INJLIB" may be useful also. MSJ aricive in MSDN contains obly code from this article, possibly article text may be found in old MSDN Library versions.
Jeffrey Richter's book "Programming Applications for Microsoft Windows" has the whole chapter "DLL Injection and API Hooking" about this issue.

As I mentioned in my previous post, I didn't do such things before, so I cannot help you in this case. I can only help you to ask right question and hope somebody else can help.

I read your question in C++ area and I don't think it is clear. Try to ask by the following way (I hope I understand what happens in your program now, correct me if I am wrong):

"I need to implement paint hook <Why? What are you trying to do? ...> I have working class which does this in my process <CPaintHook class code or some fragments from it, or link to it>. Now I need to make this hook in window from another process. How can I do this?"

Describe also what can you do from C# (call API from any Dll, exactly as in Visual Basic) and ask in Windows programming area.

Please describe here your initial problem, maybe there are another ways to solve it?
0
 

Author Comment

by:rossryan
ID: 10810965
The app I am working on is called Sapphire, which is a 4D Desktop (go ahead, laugh ;). Think Project Looking Glass or MS Task Gallery, but actually useful (and fast). There are a lot of competing implementations, but while most are interesting, they do not satisfy the three axioms of GUI programming: fast, user-friendly, and productive. They spend more time turning the desktop into eye-candy city or Quake V, than a viable alternative. Why C#? I'm sick of C++ and I can't stand VB. Redeclaring things half a dozen times has got to stop (prototypes, then functions, grrrrrrrrrr).  

Anyway, it is implemented in OpenGL and C#. A lot of the programming is already completed, with the exception of the window class. In order for Sapphire to use a window (as there really isn't a window class in OpenGL), I have to build it's own class. The window itself is a texture spread over a QUAD object. When the texture is active, functions for mouse and keyboard are rerouted accordingly. Well, that's the plan, anyway...

The biggest problem is that Windows was never created with these functions in mind. GDI does not paint overlapping windows. So if you have Sapphire running fullscreen, and your app windows are hidden by Sapphire, the windows do not update (or work correctly for that matter). So the texture wraps around and kills itself.

If you have to keep the app window maximized in order for Sapphire to capture it, what's the point?

This code grabs the window by injecting itself directly into the paint process, and capturing it, no matter if it is invisible, hidden, or minimized. With a proper message filter, telling Sapphire when to update the texture, Sapphire can properly take control of all windows.

I've checked all solutions, and this one seems to be the best. Either that, or I steal a copy of the Windows source. Which isn't an option, as the men in black suits will come knocking on my door when I release the 'patched' dll. :)

Your thoughts?
-Ryan

If you want a link to the Alpha of Sapphire, ask. If your setup is close to mine (Windows XP, decent video card, more than the minimum of RAM...), it will run beautifully. If not, the code will probably physically damage your machine...
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:rossryan
ID: 10811280
Feng Yuan created a dll (oh yeah) and a test app. Here's the test app source. Looks like he sends a custom message with the hWnd, which installs the hook and captures a screenshot to the clipboard. Now, to modify it. The question is, does 130869856 correspond to the procedure or an if->procedure statement? Stand by, heavy modifications, underway.

#include "stdafx.h"
#include <windows.h>

void _declspec(dllimport) InstallHook(void);

int _tmain(int argc, _TCHAR* argv[])
{
    if ((argc == 2) && argv[1] != NULL)
    {
        HWND hWnd = NULL;

        sscanf(argv[1], "%x", & hWnd);

        TCHAR message[MAX_PATH];

        wsprintf(message, "Hook window %x ?", hWnd);

        if (MessageBox(NULL, message, "HookTest", MB_OK) == IDOK)
        {
            InstallHook();

            SendMessage(hWnd, WM_USER, 0, 130869856);

            MessageBox(NULL, "Check your clipboard\r\nClose your hooked application first.", "HookTest", MB_OK);

            return 0;
        }
    }

    printf("Usage HookTest <hwnd_id_in_hex>");

    return -1;
}

0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10811300
What happens in the window when it gets WM_USER message?
0
 

Author Comment

by:rossryan
ID: 10811369
if ((pInfo != NULL) && (pInfo->message == WM_USER) && (pInfo->lParam == 130869856))
    {
        CaptureWindow(pInfo->hwnd);
    }

Apparently, it trips the statement. Captures the window. Unfortunately, it's a one shot deal, which is why I am breaking it down. I'll define my own lParam for each sub.


Here's the sub he created:
void CaptureWindow(HWND hWnd)
{
    CPaintHook hook;

    hook.SubClass(hWnd);


    HDC hDCMem = CreateCompatibleDC(NULL);

    RECT rect;

    GetWindowRect(hWnd, & rect);

    HBITMAP hBmp = NULL;

    {
        HDC hDC = GetDC(hWnd);
        hBmp = CreateCompatibleBitmap(hDC, rect.right - rect.left, rect.bottom - rect.top);
        ReleaseDC(hWnd, hDC);
    }

    HGDIOBJ hOld = SelectObject(hDCMem, hBmp);
    SendMessage(hWnd, WM_PRINT, (WPARAM) hDCMem, PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT | PRF_OWNED);

    SelectObject(hDCMem, hOld);
    DeleteObject(hDCMem);

    OpenClipboard(hWnd);
 
    EmptyClipboard();
    SetClipboardData(CF_BITMAP, hBmp);
    CloseClipboard();
}

It hooks the application, creates a DC, sends a message to paint the window, captures it, then copies itself to the clipboard. The test program itself exits, and as the callback procedure no longer exists, the hooked window dies. Which is why you need to close the hooked window before you close the test program. But as Sapphire should be the last program to close, I do not care. I just want updates, instead of a single capture.

My subs:

void HookWindow(HWND hWnd)
{

      
    CPaintHook hook;

    hook.SubClass(hWnd);


    HDC hDCMem = CreateCompatibleDC(NULL);

    RECT rect;

    GetWindowRect(hWnd, & rect);

    HBITMAP hBmp = NULL;

    {
        HDC hDC = GetDC(hWnd);
        hBmp = CreateCompatibleBitmap(hDC, rect.right - rect.left, rect.bottom - rect.top);
        ReleaseDC(hWnd, hDC);
    }
      HGDIOBJ hOld = SelectObject(hDCMem, hBmp);

}

void UpdateWindow()
{
 SendMessage(hWnd, WM_PRINT, (WPARAM) hDCMem, PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT | PRF_OWNED);
 SelectObject(hDCMem, hOld);
}

void DestroyWindow()
{
      
    DeleteObject(hDCMem);

    OpenClipboard(hWnd);
 
    EmptyClipboard();
    SetClipboardData(CF_BITMAP, hBmp);
    CloseClipboard();

}

I need to modify them so that I can return bitmaps from UpdateWindow() (and pointers to global). Will do, probably tomorrow, I need sleep.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10811478
130869856 is just some crazy number which allows to differentiate messages in the case WM_USER is used by another application. The best way is using RegisterWindowMessage, but this is not a point here.
This code is injected to another process (how? I don't see from the posted fragment), hooks WM_PAINT and pastes result bitmap into clipboard. Clipboard is available from all processes.
Can you use Clipboard in your application? In this case this sample may be useful to you.
0
 

Author Comment

by:rossryan
ID: 10811506
Sorry, here's the full code.

// Copyright (C) 2000-2004 by Feng Yuan (www.fengyuan.com)

//hookpaint.h
class CPaintHook
{
    BYTE      m_thunk[9];
    WNDPROC   m_OldWndProc;
    HDC       m_hDC;
    HWND      m_hWnd;

    static HDC  WINAPI MyBeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint);
    static BOOL WINAPI MyEndPaint(HWND hWnd, LPPAINTSTRUCT lpPaint);

    virtual LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
      
public:
   
    bool Within_WM_PRINT(void) const
    {  
        if ( IsBadWritePtr((void *) this, sizeof(CPaintHook)) )
            return false;

        if ( (m_thunk[0]==0xB9) && ((* (unsigned *) (m_thunk+5))==0x20FF018B) )
            return m_hDC !=0;
        else
            return false;
    }    
   
    CPaintHook(void);
    ~CPaintHook();

    void SubClass(HWND hWnd);
};


void CaptureWindow(HWND hWnd);
void HookWindow(HWND hWnd);
Bitmap UpdateWindow();
void DestroyWindow();



// Copyright (C) 2000-2004 by Feng Yuan (www.fengyuan.com)
// HookPaint.cpp
#include "stdafx.h"
#include <assert.h>

#include "hookpaint.h"

#pragma warning(disable : 4311 4312)

bool Hook(const TCHAR * module, const TCHAR * proc, unsigned & syscall_id, BYTE * & pProc, const void * pNewProc)
{
    HINSTANCE hMod = GetModuleHandle(module);

    pProc = (BYTE *) GetProcAddress(hMod, proc);

    if (pProc[0] == 0xB8)
    {
        syscall_id = * (unsigned *) (pProc + 1);

        DWORD flOldProtect;

        VirtualProtect(pProc, 5, PAGE_EXECUTE_READWRITE, & flOldProtect);

        pProc[0] = 0xE9;
        * (unsigned *) (pProc+1) = (unsigned)pNewProc - (unsigned) (pProc+5);

        pProc += 5;

        return true;
    }
    else
    {
        return false;
    }
}


static unsigned syscall_BeginPaint = 0;
static BYTE *   pBeginPaint        = NULL;

static unsigned syscall_EndPaint   = 0;
static BYTE *   pEndPaint          = NULL;


LRESULT CPaintHook::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    assert(m_OldWndProc);

    if (uMsg == WM_PRINTCLIENT)
    {
        m_hDC = (HDC) wParam;
        uMsg  = WM_PAINT;
    }
       
    LRESULT hRslt = CallWindowProc(m_OldWndProc, hWnd, uMsg, wParam, lParam);

    m_hDC = NULL;

    return hRslt;
}
      

HDC WINAPI CPaintHook::MyBeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint)
{
    const CPaintHook * pThis = (CPaintHook *) GetWindowLong(hWnd, GWL_WNDPROC);
   
    pThis = (const CPaintHook *) ( (unsigned) pThis - (unsigned) & pThis->m_thunk[0] + (unsigned) pThis );
   
    if (pThis->Within_WM_PRINT())
    {
        memset(lpPaint, 0, sizeof(PAINTSTRUCT));

        lpPaint->hdc = pThis->m_hDC;
       
        GetClientRect(hWnd, & lpPaint->rcPaint);
       
        return pThis->m_hDC;
    }
    else
    {
        __asm   mov     eax, syscall_BeginPaint
        __asm   push    lpPaint
        __asm   push    hWnd
        __asm   call    pBeginPaint
    }
}


BOOL WINAPI CPaintHook::MyEndPaint(HWND hWnd, LPPAINTSTRUCT lpPaint)
{
    const CPaintHook * pThis = (CPaintHook *) GetWindowLong(hWnd, GWL_WNDPROC);
   
    pThis = (const CPaintHook *) ( (unsigned) pThis - (unsigned) & pThis->m_thunk[0] + (unsigned) pThis );
   
    if (pThis->Within_WM_PRINT())
    {
        return TRUE;
    }
    else
    {
        __asm   mov     eax, syscall_EndPaint
        __asm   push    lpPaint
        __asm   push    hWnd
        __asm   call    pEndPaint
    }
}

CPaintHook::CPaintHook()
{
    static bool s_hooked = false;

    if ( ! s_hooked )
    {
        Hook("USER32.DLL", "BeginPaint", syscall_BeginPaint, pBeginPaint, MyBeginPaint);
        Hook("USER32.DLL", "EndPaint",   syscall_EndPaint,   pEndPaint,   MyEndPaint);

        s_hooked = true;
    }

    m_thunk[0]              = 0xB9;               // mov ecx,
    *((DWORD *)(m_thunk+1)) = (DWORD) this;  //          this
      *((DWORD *)(m_thunk+5)) = 0x20FF018B;    // mov eax, [ecx]

    m_OldWndProc = NULL;
    m_hDC        = NULL;
    m_hWnd       = NULL;
}


void CPaintHook::SubClass(HWND hWnd)
{            
    m_hWnd       = hWnd;
    m_OldWndProc = (WNDPROC) GetWindowLong(hWnd, GWL_WNDPROC);
   
    SetWindowLong(hWnd, GWL_WNDPROC, (LONG) ((void *) m_thunk));
}

CPaintHook::~CPaintHook()
{
    if (m_OldWndProc)
    {
        SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG) m_OldWndProc);
    }
}


////////////////////////////////////////////////////////




void CaptureWindow(HWND hWnd)
{
    CPaintHook hook;

    hook.SubClass(hWnd);


    HDC hDCMem = CreateCompatibleDC(NULL);

    RECT rect;

    GetWindowRect(hWnd, & rect);

    HBITMAP hBmp = NULL;

    {
        HDC hDC = GetDC(hWnd);
        hBmp = CreateCompatibleBitmap(hDC, rect.right - rect.left, rect.bottom - rect.top);
        ReleaseDC(hWnd, hDC);
    }

    HGDIOBJ hOld = SelectObject(hDCMem, hBmp);
    SendMessage(hWnd, WM_PRINT, (WPARAM) hDCMem, PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT | PRF_OWNED);

    SelectObject(hDCMem, hOld);
    DeleteObject(hDCMem);

    OpenClipboard(hWnd);
 
    EmptyClipboard();
    SetClipboardData(CF_BITMAP, hBmp);
    CloseClipboard();
}


HWND hWnd = NULL;
HBITMAP hBmp = NULL;
HGDIOBJ hOld = NULL;
HDC hDCMem = NULL;

void HookWindow(HWND hWnd)
{

      
    CPaintHook hook;

    hook.SubClass(hWnd);


    HDC hDCMem = CreateCompatibleDC(NULL);

    RECT rect;

    GetWindowRect(hWnd, & rect);

    HBITMAP hBmp = NULL;

    {
        HDC hDC = GetDC(hWnd);
        hBmp = CreateCompatibleBitmap(hDC, rect.right - rect.left, rect.bottom - rect.top);
        ReleaseDC(hWnd, hDC);
    }
      HGDIOBJ hOld = SelectObject(hDCMem, hBmp);

}

Bitmap UpdateWindow()
{
 SendMessage(hWnd, WM_PRINT, (WPARAM) hDCMem, PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT | PRF_OWNED);
 SelectObject(hDCMem, hOld);
}

void DestroyWindow()
{
      
    DeleteObject(hDCMem);

    OpenClipboard(hWnd);
 
    EmptyClipboard();
    SetClipboardData(CF_BITMAP, hBmp);
    CloseClipboard();

}


// hook.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "hookpaint.h"


// Shared Data

#pragma data_seg("Shared")

HHOOK   h_WndProcHook  = NULL;

#pragma data_seg()

HINSTANCE hInstance;

BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                               )
{
    hInstance = (HINSTANCE) hModule;

    return TRUE;
}


LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    CWPRETSTRUCT * pInfo = (CWPRETSTRUCT *) (lParam - 4);

    if ((pInfo != NULL) && (pInfo->message == WM_USER) && (pInfo->lParam == 130869856))
    {
        CaptureWindow(pInfo->hwnd);
    }
   
    if (h_WndProcHook)
    {
        return CallNextHookEx(h_WndProcHook, nCode, wParam, lParam);
    }
    else
    {
        return 0;
    }
}


void _declspec(dllexport) InstallHook(void)
{
         h_WndProcHook  = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC) CallWndProc, hInstance, 0);
}


// hooktest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>

void _declspec(dllimport) InstallHook(void);

int _tmain(int argc, _TCHAR* argv[])
{
    if ((argc == 2) && argv[1] != NULL)
    {
        HWND hWnd = NULL;

        sscanf(argv[1], "%x", & hWnd);

        TCHAR message[MAX_PATH];

        wsprintf(message, "Hook window %x ?", hWnd);

        if (MessageBox(NULL, message, "HookTest", MB_OK) == IDOK)
        {
            InstallHook();

            SendMessage(hWnd, WM_USER, 0, 130869856);

            MessageBox(NULL, "Check your clipboard\r\nClose your hooked application first.", "HookTest", MB_OK);

            return 0;
        }
    }

    printf("Usage HookTest <hwnd_id_in_hex>");

    return -1;
}

Anyways, I rechecked, and apparently he now works for MS (as of 2001, I need to pay more attention). Which makes for fun.

I have to strip out the clipboard code, and replace it with Bitmap transforms...So everytime I call UpdateWindow(), I get a Bitmap as a return.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10811696
So, you have the hook which intercepts paint message to the window from another process and pastes it to clipboard. Now you want to replace clipboard with bitmap (HBITMAP)? It's impossible to move bitmap to another process. Options you have:
1) Clipboard  :-(
2) Save bitmap to file
3) Write bitmap to memory mapped file.

I suggest you first to save bitmap to file and read it from file in the client application. After this try to do the same with C# client. If this works - replace file with memory mapped file. This replacement will be straightforward (not so simple, but possible).
0
 

Author Comment

by:rossryan
ID: 10811854
OMG. Nothing simple is ever easy. Aright, tell me how to create and access a memory file, and I'll give you your points.

0
 
LVL 48

Accepted Solution

by:
AlexFM earned 500 total points
ID: 10812111
Actually, memory mapping part is relatively easy.

CreateFileMapping API creates memory-mapped file with some name. If two processes use this function with the same name, they get the same memory block which can be used for inter-process communication. Suppose client (C#) creates memory-mapped file with some unique name. Hook Dll calls CreateFileMapping with the same name, and function returns handle to the same file mapping.
MapViewOfFile API returns pointer from file mapping. This is memory pointer which can be used to read and write information to memory-mapped file.

Other problem is how to write bitmap to memory-mapped file. In your code bitmap is created using CreateCompatibleBitmap function. It should be replaced by CreateDIBSection call, which creates device-independent bitmap (DIB). DIB advantage is that it's pixels may be accessed directly and have known structure. GetBitmapBits function may be used to extract these bits from DIB. Bitmap bits may be placed to memory-mapped file.

C# client may use unsafe pointer to read bitmap bits from the memory-mapped file and write them to managed Bitmap instance.

OMG - I can say this also. I think it is better for you to solve your task using Clipboard, and having this part working, think about other inter-process communication ways.
0
 

Author Comment

by:rossryan
ID: 10818525
The problem is, during normal operations, the user needs the Clipboard (think copy and past text). If Sapphire is using the clipboard during those times for images, the text will be...gone. So, a memory mapped file it is.
By the by, you wouldn't happen to know the speed for these operations would you?
0
 

Author Comment

by:rossryan
ID: 10818721
Wait, do I need to copy the whole bitmap to the memory mapped file, or can I just pass the Hbitmap pointer, and grab directly from c#?
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10820370
1) Of course, Clipboard is not final solution. I suggest you to use it only as temporary solution, to be sure that all other things are working, and after this think about other IPC way.

2) HBITMAP cannot be passed to other process. You need to copy the whole bitmap in format of bmp file or only bitmap bits (array of pixels).
0
 

Author Comment

by:rossryan
ID: 10820417
There goes my fun...I built a structure to pass HBITMAP, now I'll create the bitmap before I pass it.

struct SapphireData
{
HBITMAP SapphireSwap;
};


SapphireData->SapphireSwap = hBmp;
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Suggested Solutions

Article by: Najam
Having new technologies does not mean they will completely replace old components.  Recently I had to create WCF that will be called by VB6 component.  Here I will describe what steps one should follow while doing so, please feel free to post any qu…
Summary: Persistence is the capability of an application to store the state of objects and recover it when necessary. This article compares the two common types of serialization in aspects of data access, readability, and runtime cost. A ready-to…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now