Solved

Filemapping code (C#)

Posted on 2004-04-16
42
2,928 Views
Last Modified: 2008-06-07
Anyone with working filemap code in c#?
0
Comment
Question by:rossryan
  • 22
  • 17
  • 2
  • +1
42 Comments
 

Author Comment

by:rossryan
ID: 10840228
Specifically, for loading and unloading into the object (shared memory).
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10840285
rossryan, is this OK for you to get the previous sample of unmanaged Dll passing bitmap bits to managed client, but instead of using memory buffer as function parameter, both use memory mapped file? I need some time to change this sample, I will post the code when it will be ready.
0
 

Author Comment

by:rossryan
ID: 10840326
Hmm. I really out of my depth. I'll post what I have, perhaps you can spot the errors. I've tried just passing memory through C# with a server/client setup, but it's being a pain.

// 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, 130869857);

                  MessageBox(NULL, "Hooked.", "HookTest", MB_OK);

                  SendMessage(hWnd, WM_USER, 0, 130869858);

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

                  SendMessage(hWnd, WM_USER, 0, 130869859);

            return 0;
        }
    }

    printf("Usage HookTest <hwnd_id_in_hex>");

    return -1;
}

// 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);
    }
      
      else if ((pInfo != NULL) && (pInfo->message == WM_USER) && (pInfo->lParam == 130869857)) {
            HookWindow2(pInfo->hwnd);
      }
      
      else if ((pInfo != NULL) && (pInfo->message == WM_USER) && (pInfo->lParam == 130869858)) {
            UpdateWindow2();
      }
      else if ((pInfo != NULL) && (pInfo->message == WM_USER) && (pInfo->lParam == 130869859)) {
            DestroyWindow2();
      }
      
   
    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);
}
// 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;
}


CPaintHook::CPaintHook(int stop)
{

}

void CPaintHook::Start()
{

      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 hWnd2 = NULL;
HBITMAP hBmp2 = NULL;
HGDIOBJ hOld2 = NULL;
HDC hDCMem2 = NULL;
HANDLE hMap2 = NULL;


HANDLE hSapphireData = NULL;
void* SapphireDataMap = NULL;
CPaintHook hook2(0);
SapphireDat* SapphireData;
RECT rect2;







void HookWindow2(HWND hWnd)
{
      hWnd2 = hWnd;
      hook2.Start();

      
      hMap2 = CreateFileMappingA(INVALID_HANDLE_VALUE,    // current file handle
    NULL,                              // default security
    PAGE_READWRITE,                    // read/write permission
    0,                                 // max. object size
    100000,                                 // size of hFile
    "SapphireFSwap");            // name of mapping object


      if (hMap2 != NULL && GetLastError() == ERROR_ALREADY_EXISTS)
      {
    CloseHandle(hMap2);
    hMap2 = NULL;
      }

      
      if (hMap2 != NULL)
      {
    CloseHandle(hMap2);
    hMap2 = NULL;
      }
      SapphireDataMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, "SapphireFSwap");

      if (SapphireDataMap != NULL)
      {
      hSapphireData = MapViewOfFile(hMap2, FILE_MAP_ALL_ACCESS, 0, 0, 0);


            if (hSapphireData != NULL)
            {
            SapphireData = (SapphireDat*)hSapphireData;
            }
      }

    hook2.SubClass(hWnd2);


    hDCMem2 = CreateCompatibleDC(NULL);

   

    GetWindowRect(hWnd2, & rect2);

   

    {
        HDC hDC = GetDC(hWnd2);
        LPBITMAPINFO lpbi;

            lpbi = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD))];
            lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
            lpbi->bmiHeader.biWidth = rect2.right - rect2.left;
            lpbi->bmiHeader.biHeight =  rect2.bottom - rect2.top;
            lpbi->bmiHeader.biPlanes = 1;
            lpbi->bmiHeader.biBitCount = 32; //24;
            lpbi->bmiHeader.biCompression = BI_RGB;
            lpbi->bmiHeader.biSizeImage = (rect2.right - rect2.left) * (rect2.bottom - rect2.top); //    WIDTHBYTES((DWORD)nWidth * 8) * nHeight;
            lpbi->bmiHeader.biXPelsPerMeter = 0;
            lpbi->bmiHeader.biYPelsPerMeter = 0;
            lpbi->bmiHeader.biClrUsed = 0;
            lpbi->bmiHeader.biClrImportant = 0;

            BYTE* pTmp;

            hBmp2 = CreateDIBSection(
                  hDC,
                  lpbi,
                  DIB_RGB_COLORS,
                  (void **)&pTmp,
                  NULL,
                  0 );

            delete[] lpbi;

        ReleaseDC(hWnd2, hDC);
    }
      hOld2 = SelectObject(hDCMem2, hBmp2);

}

void UpdateWindow2()
{
      
      
      SendMessage(hWnd2, WM_PRINT, (WPARAM) hDCMem2, PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT | PRF_OWNED);      

      //SapphireData->pBits = new BYTE[4 * (rect2.right - rect2.left) * (rect2.bottom - rect2.top)];
      GetBitmapBits(hBmp2, (4 * (rect2.right - rect2.left) * (rect2.bottom - rect2.top)), SapphireData->pBits);
      
   
   

}

void DestroyWindow2()
{

      
 

      SelectObject(hDCMem2, hOld2);
    DeleteObject(hDCMem2);

      /*
    OpenClipboard(hWnd2);
 
    EmptyClipboard();
    SetClipboardData(CF_BITMAP, hBmp);
    CloseClipboard();
      */
      
      if (hSapphireData)
      {
    UnmapViewOfFile(hSapphireData);
      hSapphireData = NULL;
      }
      CloseHandle(SapphireDataMap);

}
// 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(int stop);
    ~CPaintHook();

    void SubClass(HWND hWnd);
      void Start();
};


struct SapphireDat {
BYTE pBits[4096];
};



void CaptureWindow(HWND hWnd);
void HookWindow2(HWND hWnd);
void UpdateWindow2();
void DestroyWindow2();
0
 

Author Comment

by:rossryan
ID: 10840334
Test client I wrote:

using System;
using System.Runtime.InteropServices;

namespace FileMapTest
{
      /// <summary>
      /// Summary description for FileMap.
      /// </summary>
      public class FileMap
      {

            public struct SapphireDat
            {
                  public byte[] pBits;
            };
            public IntPtr hMap2 =IntPtr.Zero;
            public IntPtr SapphireDataMap =IntPtr.Zero;
            public IntPtr hSapphireData =IntPtr.Zero;
            public SapphireDat SapphireData;
            public SapphireDat SapphireData2;


            [STAThread]
            public static void Main()
            {
                  FileMap test = new FileMap();
            }

            public FileMap()
            {
                  /*
                  hMap2 = Kernel32.CreateFileMappingA(new IntPtr(Kernel32.INVALID_HANDLE_VALUE),    // current file handle
                        0,                              // default security
                        Kernel32.PAGE_READWRITE,                    // read/write permission
                        0,                                 // max. object size
                        100000,                                 // size of hFile
                        "SapphireFSwap");            // name of mapping object

                  int nError = Marshal.GetLastWin32Error();
                  System.Diagnostics.Debug.WriteLine("Last Error " + nError);      
                  System.Diagnostics.Debug.WriteLine("hMap2 " + hMap2);

                  if (hMap2 != IntPtr.Zero && Marshal.GetLastWin32Error() == Kernel32.ERROR_ALREADY_EXISTS)
                  {
                        //CloseHandle(hMap);
                        hMap2 = IntPtr.Zero;
                  }

                  */

                  SapphireDataMap = Kernel32.OpenFileMapping(Kernel32.FILE_MAP_ALL_ACCESS, false, "SapphireFSwap");

                  if (SapphireDataMap != IntPtr.Zero)
                  {
                        hSapphireData = Kernel32.MapViewOfFile(hMap2, Kernel32.FILE_MAP_ALL_ACCESS, 0, 0, 0);
                        System.Diagnostics.Debug.WriteLine(hSapphireData);
                        
                        if (hSapphireData != IntPtr.Zero)
                        {
                              /*
                              SapphireData.pBits = new Byte[4096];
                              SapphireData.pBits[0] = 0;
                              Marshal.StructureToPtr(SapphireData, hSapphireData, false);
                              */
                              /*
                              SapphireData2.pBits = new Byte[4096];
                              SapphireData2 = (SapphireDat)Marshal.PtrToStructure(hSapphireData, typeof(SapphireDat));
                              
                              */
                              //string test = "";
                              string test;
                              test = Marshal.PtrToStringBSTR(hSapphireData);
                              System.Diagnostics.Debug.WriteLine(test.Length);

                        }
                        
                  }
            }

      }

      public class Kernel32
      {

            public const long DONT_RESOLVE_DLL_REFERENCES     = 0x00000001;
            public const long LOAD_LIBRARY_AS_DATAFILE          = 0x00000002;
            public const long LOAD_WITH_ALTERED_SEARCH_PATH     = 0x00000008;
            public const long LOAD_IGNORE_CODE_AUTHZ_LEVEL     = 0x00000010;

            //Enum types
            public const long RT_CURSOR  = 1;          
            public const long RT_BITMAP = 2;              
            public const long RT_ICON = 3;              
            public const long RT_MENU = 4;
            public const long RT_DIALOG = 5;
            public const long RT_STRING = 6;
            public const long RT_FONTDIR = 7;
            public const long RT_FONT = 8;
            public const long RT_ACCELERATOR = 9;
            public const long RT_RCDATA = 10;
            public const long RT_MESSAGETABLE = 11;
            public const long RT_VERSION = 16;
            public const long RT_DLGINCLUDE = 17;
            public const long RT_PLUGPLAY = 19;
            public const long RT_VXD = 20;
            public const long RT_ANICURSOR = 21;
            public const long RT_ANIICON = 22;
            public const long RT_HTML = 23;
            public const long RT_MANIFEST = 24;
            //uType
            public const uint IMAGE_BITMAP = 0;
            public const uint IMAGE_ICON = 1;
            public const uint IMAGE_CURSOR = 2;
            //fuLoad
            public const uint LR_DEFAULTCOLOR     =0x0000;
            public const uint LR_MONOCHROME       =0x0001;
            public const uint LR_COLOR            =0x0002;
            public const uint LR_COPYRETURNORG    =0x0004;
            public const uint LR_COPYDELETEORG    =0x0008;
            public const uint LR_LOADFROMFILE     =0x0010;
            public const uint LR_LOADTRANSPARENT  =0x0020;
            public const uint LR_DEFAULTSIZE      =0x0040;
            public const uint LR_VGACOLOR         =0x0080;
            public const uint LR_LOADMAP3DCOLORS  =0x1000;
            public const uint LR_CREATEDIBSECTION =0x2000;
            public const uint LR_COPYFROMRESOURCE =0x4000;
            public const uint LR_SHARED           =0x8000;

            //Languages
            public const long LANG_NEUTRAL = 0x00;

            public const int WM_PAINT = 0x000F;
            public const int WM_PRINT = 0x0317;
            public const int WM_PRINTCLIENT = 0x0318;
            public const int WM_ERASEBKGND = 0x0014;

            public const int PRF_CHECKVISIBLE = 0x00000001;
            public const int PRF_NONCLIENT    = 0x00000002;
            public const int PRF_CLIENT       = 0x00000004;
            public const int PRF_ERASEBKGND   = 0x00000008;
            public const int PRF_CHILDREN     = 0x00000010;
            public const int PRF_OWNED        = 0x00000020;

            public const int ERROR_ALREADY_EXISTS =      183;





            [DllImport("kernel32.dll", SetLastError=true)]
            public static extern IntPtr LoadLibraryEx(string lpfFileName,
                  long hFile, long dwFlags);

            [DllImport("kernel32.dll", SetLastError=true)]
            public static extern Int32 EnumResourceTypes(IntPtr hModule, EnumResTypeProc callback, long lParam);

            public delegate Int32 EnumResTypeProc(IntPtr hModule, IntPtr lpszType, long lParam);
            [DllImport("kernel32.dll", SetLastError=true)]
            public static extern bool FreeLibrary(IntPtr hModule);

            [DllImport("kernel32.dll", SetLastError=true)]
            public static extern Int32 EnumResourceNames(IntPtr hModule, IntPtr lpszType, EnumResNameProc callback, long lParam);
            
            public delegate Int32 EnumResNameProc(IntPtr hModule, IntPtr lpszType, [MarshalAs(UnmanagedType.LPStr)] string lpszName, long lParam);
            
            [DllImport("user32.dll", SetLastError=true)]
            public static extern IntPtr LoadImageA(IntPtr hinst, [MarshalAs(UnmanagedType.LPStr)] string lpszName, uint uType, int cxDesired, int cyDesired, uint fuLoad);
      
            [DllImport("kernel32.dll", SetLastError=true)]
            public static extern IntPtr FindResourceEx(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string lpType, [MarshalAs(UnmanagedType.LPStr)] string lpName, long wLanguage);

            [DllImport("kernel32.dll", SetLastError=true)]
            public static extern IntPtr FindResourceEx(IntPtr hModule, long lpType, [MarshalAs(UnmanagedType.LPStr)] string lpName, long wLanguage);
            
            [DllImport("kernel32.dll", SetLastError=true)]
            public static extern IntPtr LockResource(IntPtr hResData);

            [DllImport("kernel32.dll", SetLastError=true)]
            public static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);


            [DllImport("kernel32.dll", SetLastError=true)]
            public static extern long SizeofResource(IntPtr hModule, IntPtr hResInfo);

            //[DllImport("kernel32.dll", SetLastError=true)]
            //public static extern void CopyMemory(BITMAPINFOHEADER Destination, IntPtr Source, long Length);

            [DllImport("kernel32.dll", SetLastError=true)]
            public static extern bool FreeResource(IntPtr hglbResource);

            [DllImport("shell32.dll", SetLastError=true)]
            public static extern uint ExtractIconEx(string lpszFile, int nIconIndex, IntPtr[] phiconLarge, IntPtr[] phiconSmall, int nIcons);

            [DllImport("user32.dll", SetLastError=true)]
            public static extern bool DestroyIcon(IntPtr hIcon);

            [DllImport("user32.dll", SetLastError=true)]
            public static extern IntPtr GetWindowDC(IntPtr hWnd);

            [DllImport("Gdi32.dll", SetLastError=true)]
            public static extern long CreateCompatibleDC(long hdc);

            [DllImport("Gdi32.dll", SetLastError=true)]
            public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);

            [DllImport("user32.dll", SetLastError=true)]
            public static extern long ReleaseDC(IntPtr hWnd, IntPtr hDC);

            [DllImport("Gdi32.dll", SetLastError=true)]
            public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

            [DllImport("Gdi32.dll", SetLastError=true)]
            public static extern bool DeleteObject(IntPtr hObject);

            [DllImport("user32.dll", SetLastError=true)]
            public static extern long SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

            [DllImport("kernel32.dll", SetLastError=true)]
            public static extern IntPtr CreateFileMappingA(
                  IntPtr hFile,
                  int security,
                  int flProtect,
                  int dwMaximumSizeHigh,
                  int dwMaximumSizeLow,
                  [MarshalAs(UnmanagedType.LPStr)] string lpName
                  );
            public const int PAGE_READWRITE = 0x04;
            public const int INVALID_HANDLE_VALUE = -1;


            [DllImport("kernel32.dll", SetLastError=true)]
            public static extern IntPtr OpenFileMapping(int dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, [MarshalAs(UnmanagedType.LPStr)] string lpName);

            public const int FILE_MAP_ALL_ACCESS = 0x000f001f;


            [DllImport("kernel32.dll", SetLastError=true)]
            public static extern IntPtr MapViewOfFile(
                  IntPtr hFileMappingObject,
                  int dwDesiredAccess,
                  int dwFileOffsetHigh,
                  int dwFileOffsetLow,
                  int dwNumberOfBytesToMap
                  );


            [DllImport("kernel32.dll", SetLastError=true)]
            public static extern void RtlMoveMemory(IntPtr Destination, byte[] Source,      long Length);

            [DllImport("kernel32.dll", SetLastError=true)]
            public static extern void RtlMoveMemory(ref byte[] Destination, IntPtr Source,      long Length);






      

            
            [DllImport("Gdi32.dll", SetLastError=true)]                                                                                                                                                                                                                                                                                                                                                  
            public static extern long BitBlt(
                  IntPtr hdcDest, // handle to destination DC
                  long nXDest,  // x-coord of destination upper-left corner
                  long nYDest,  // y-coord of destination upper-left corner
                  long nWidth,  // width of destination rectangle
                  long nHeight, // height of destination rectangle
                  IntPtr hdcSrc,  // handle to source DC
                  long nXSrc,   // x-coordinate of source upper-left corner
                  long nYSrc,   // y-coordinate of source upper-left corner
                  long dwRop  // raster operation code
                  );












            

      }

      public class PaintHook
      {
            [DllImport ("PaintHook.dll", EntryPoint="#1")]
            public static extern IntPtr InstallHook();

      }


      

      public class GDI32
      {
            [DllImport("GDI32.dll")]
            public static extern bool BitBlt(int hdcDest,int nXDest,int nYDest,
                  int nWidth,int nHeight,int hdcSrc,
                  int nXSrc,int nYSrc,int dwRop);
            [DllImport("GDI32.dll")]
            public static extern bool BitBlt(IntPtr hdcDest,int nXDest,int nYDest,
                  int nWidth,int nHeight,IntPtr hdcSrc,
                  int nXSrc,int nYSrc,int dwRop);
            [DllImport("GDI32.dll")]
            public static extern int CreateCompatibleBitmap(int hdc,int nWidth,
                  int nHeight);
            [DllImport("GDI32.dll")]
            public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc,int nWidth,
                  int nHeight);
            [DllImport("GDI32.dll")]
            public static extern int CreateCompatibleDC(int hdc);
            [DllImport("GDI32.dll")]
            public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
            [DllImport("GDI32.dll")]
            public static extern bool DeleteDC(int hdc);
            [DllImport("GDI32.dll")]
            public static extern bool DeleteObject(int hObject);
            [DllImport("GDI32.dll")]
            public static extern bool DeleteDC(IntPtr hdc);
            [DllImport("GDI32.dll")]
            public static extern bool DeleteObject(IntPtr hObject);
            [DllImport("GDI32.dll")]
            public static extern int GetDeviceCaps(int hdc,int nIndex);
            [DllImport("GDI32.dll")]
            public static extern int GetDeviceCaps(IntPtr hdc,int nIndex);
            [DllImport("GDI32.dll")]
            public static extern int SelectObject(int hdc,int hgdiobj);
            [DllImport("GDI32.dll")]
            public static extern IntPtr SelectObject(IntPtr hdc,IntPtr hgdiobj);            


            [DllImport("GDI32.dll")]
            public static extern long SetBitmapBits(
                  IntPtr hbmp,        // handle to bitmap
                  long cBytes,        // number of bytes in bitmap array
                  IntPtr lpBits   // array with bitmap bits
                  );

      }
 

      public class User32
      {
            public const int WM_PAINT = 0x000F;
            public const int WM_PRINT = 0x0317;
            public const int WM_PRINTCLIENT = 0x0318;
            public const int WM_ERASEBKGND = 0x0014;
            public const int WM_USER = 0x400;

            public const int PRF_CHECKVISIBLE = 0x00000001;
            public const int PRF_NONCLIENT    = 0x00000002;
            public const int PRF_CLIENT       = 0x00000004;
            public const int PRF_ERASEBKGND   = 0x00000008;
            public const int PRF_CHILDREN     = 0x00000010;
            public const int PRF_OWNED        = 0x00000020;
            public const int Visible = 1;
            public const int Invisible = 0;

            public const int CF_BITMAP = 2;

            public const int WH_CALLWNDPROC = 4;

            [DllImport("User32.dll")]
            public static extern int GetDesktopWindow();
            [DllImport("User32.dll")]
            public static extern int GetWindowDC(int hWnd);
            [DllImport("User32.dll")]
            public static extern IntPtr GetWindowDC(IntPtr hWnd);
            [DllImport("User32.dll")]
            public static extern int ReleaseDC(int hWnd,int hDC);
            [DllImport("User32.dll")]
            public static extern IntPtr ReleaseDC(IntPtr hWnd,IntPtr hDC);
            [DllImport("user32.dll", SetLastError=true)]
            public static extern int GetWindowRect(IntPtr hWnd, ref RECT rect);
            [DllImport("user32.dll", SetLastError=true)]
            public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wparam, IntPtr lparam);
            [DllImport("user32.dll", SetLastError=true)]
            public static extern IntPtr GetDC(IntPtr hWnd);
            [DllImport("user32.dll", SetLastError=true)]
            public static extern IntPtr GetDCEx(IntPtr hWnd, IntPtr hrgnClip,IntPtr flags);
            [DllImport("user32.dll", SetLastError=true)]
            public static extern IntPtr ShowWindow(IntPtr hwnd, int nCmdShow);

            [DllImport("user32.dll", SetLastError=true)]
            public static extern int OpenClipboard(IntPtr hWndNewOwner);

            [DllImport("user32.dll", SetLastError=true)]
            public static extern int EmptyClipboard();

            [DllImport("user32.dll", SetLastError=true)]
            public static extern IntPtr SetClipboardData(int uFormat, IntPtr hMem);

            [DllImport("user32.dll", SetLastError=true)]
            public static extern int CloseClipboard();

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

            public delegate int HookProc(int nCode, IntPtr wParam, long lParam);








      }
      public struct RECT
      {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
      }
}
0
 

Author Comment

by:rossryan
ID: 10840344
The funny thing of it all is this: with the C# client/server setup, I get a Win32 error 183: File open, as I should. But when I use the CPaint dll setup/C# client setup, I do not get an error. Which means the dll is not creating a filemapping object. Why, I do not know.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10840536
This is my previous sample, with appropriate changes. It is working, I hope it can help you.

BMPServer Dll, BMPServer.h:

#ifdef BMPSERVER_EXPORTS
#define BMPSERVER_API __declspec(dllexport)
#else
#define BMPSERVER_API __declspec(dllimport)
#endif

extern "C" BMPSERVER_API BOOL FillMMF(int nWidth, int nHeight);


BMPServer Dll, BMPServer.cpp:

#include "stdafx.h"
#include "BMPServer.h"
BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}


BMPSERVER_API BOOL FillMMF(int nWidth, int nHeight)
{
    HANDLE hFileMapping = CreateFileMapping(
        INVALID_HANDLE_VALUE,           // system paging file
        NULL,                           // security attributes
        PAGE_READWRITE,                 // protection
        0,                              // high-order DWORD of size
        nWidth*nHeight*4,               // low-order DWORD of size
        "BMPFileMapping");              // name

    DWORD dwError = GetLastError();

    if ( ! hFileMapping )
        return FALSE;

    if ( dwError != ERROR_ALREADY_EXISTS )
    {
        // MMF must exist
        CloseHandle(hFileMapping);
        return FALSE;
    }

    void*  pViewOfFile = MapViewOfFile(
            hFileMapping,             // handle to file-mapping object
            FILE_MAP_ALL_ACCESS,        // desired access
            0,
            0,
            0);      

    if ( ! pViewOfFile )
    {
        CloseHandle(hFileMapping);
        return FALSE;
    }

    LPBITMAPINFO lpbi;

    lpbi = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD))];
    lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    lpbi->bmiHeader.biWidth = nWidth;
    lpbi->bmiHeader.biHeight = nHeight;
    lpbi->bmiHeader.biPlanes = 1;
    lpbi->bmiHeader.biBitCount = 32;
    lpbi->bmiHeader.biCompression = BI_RGB;
    lpbi->bmiHeader.biSizeImage = nWidth * nHeight;
    lpbi->bmiHeader.biXPelsPerMeter = 0;
    lpbi->bmiHeader.biYPelsPerMeter = 0;
    lpbi->bmiHeader.biClrUsed = 0;
    lpbi->bmiHeader.biClrImportant = 0;

    BYTE* pTmp;

    HBITMAP hBitmap = CreateDIBSection(
        NULL,
        lpbi,
        DIB_RGB_COLORS,
        (void **)&pTmp,
        NULL,
        0 );

    delete[] lpbi;

    HDC hDC = CreateCompatibleDC(NULL);
    SelectObject(hDC, hBitmap);

    HPEN pen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
    HBRUSH brush = CreateSolidBrush(RGB(255, 255, 255));

    SelectObject(hDC, pen);
    SelectObject(hDC, brush);

    Rectangle(hDC, 0, 0, nWidth, nHeight);
    TextOut(hDC, 20, 20, "Hello", (int)strlen("Hello"));


    DWORD ImageSize = 4 * nWidth * nHeight;

    GetBitmapBits(hBitmap, ImageSize, pViewOfFile);

    UnmapViewOfFile(pViewOfFile);
    CloseHandle(hFileMapping);

    DeleteObject(pen);
    DeleteObject(brush);

    DeleteObject(hBitmap);
    DeleteDC(hDC);

    return TRUE;
}

C# client, Form1.cs:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
using System.IO;
using System.Drawing.Imaging;


namespace BMPClient
{
    /// <summary>
    /// Summary description for Form1.
    /// </summary>
    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.PictureBox pictureBox1;
        private System.Windows.Forms.Button button1;
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;

        public Form1()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            //
            // TODO: Add any constructor code after InitializeComponent call
            //
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.pictureBox1 = new System.Windows.Forms.PictureBox();
            this.button1 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            //
            // pictureBox1
            //
            this.pictureBox1.Location = new System.Drawing.Point(16, 24);
            this.pictureBox1.Name = "pictureBox1";
            this.pictureBox1.Size = new System.Drawing.Size(232, 136);
            this.pictureBox1.TabIndex = 0;
            this.pictureBox1.TabStop = false;
            //
            // button1
            //
            this.button1.Location = new System.Drawing.Point(72, 200);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(136, 32);
            this.button1.TabIndex = 1;
            this.button1.Text = "Run";
            this.button1.Click += new System.EventHandler(this.button1_Click);
            //
            // Form1
            //
            this.AutoScaleBaseSize = new System.Drawing.Size(6, 15);
            this.ClientSize = new System.Drawing.Size(264, 245);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.pictureBox1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.Closing += new System.ComponentModel.CancelEventHandler(this.Form1_Closing);
            this.Load += new System.EventHandler(this.Form1_Load);
            this.ResumeLayout(false);

        }
        #endregion

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.Run(new Form1());
        }


        [DllImport ("BMPServer.dll")]
        public static extern int FillMMF(int nWidth, int nHeight);

        [DllImport ("Gdi32.dll")]
        public static extern Int32 SetBitmapBits(IntPtr hBmp, Int32 cbBytes, IntPtr lpBits);

        [DllImport("gdi32.dll")]
        public static extern bool DeleteObject(IntPtr hObject);

        [DllImport ("Kernel32.dll", SetLastError=true)]
        public static extern IntPtr CreateFileMappingW(
            Int32 hFile,
            IntPtr lpAttributes,
            Int32 flProtect,
            Int32 dwMaximumSizeHigh,
            Int32 dwMaximumSizeLow,
            [MarshalAs (UnmanagedType.LPWStr)]
            string lpName);

        [DllImport ("Kernel32.dll")]
        public static extern int CloseHandle(IntPtr hObject);

        [DllImport ("Kernel32.dll", SetLastError=true)]
        public static extern IntPtr MapViewOfFile(
            IntPtr hFileMappingObject ,
            Int32 dwDesiredAccess,
            Int32 dwFileOffsetHigh,
            Int32 dwFileOffsetLow,
            Int32 dwNumberOfBytesToMap);

        [DllImport ("Kernel32.dll")]
        public static extern int UnmapViewOfFile(IntPtr lpBaseAddress);


        int nWidth = 200;
        int nHeight = 100;
        IntPtr hFileMapping;
        IntPtr pViewOfFile;

        const int PAGE_READWRITE = 4;
        const int FILE_MAP_ALL_ACCESS = 983071;
        const int INVALID_HANDLE_VALUE = -1;
        const int ERROR_ALREADY_EXISTS = 183;

        private void Form1_Load(object sender, System.EventArgs e)
        {
            button1.Enabled = false;

            hFileMapping = CreateFileMappingW(
                INVALID_HANDLE_VALUE,
                IntPtr.Zero,
                PAGE_READWRITE,
                0,
                nWidth*nHeight*4,
                "BMPFileMapping");

            int nError = Marshal.GetLastWin32Error();

            if ( hFileMapping == IntPtr.Zero )
                return;

            if ( nError == ERROR_ALREADY_EXISTS )
            {
                return;
            }

            pViewOfFile = MapViewOfFile(
                hFileMapping,
                FILE_MAP_ALL_ACCESS,
                0,
                0,
                0);

            nError = Marshal.GetLastWin32Error();

            if ( pViewOfFile == IntPtr.Zero )
            {
                return;
            }

            button1.Enabled = true;
     
        }

        private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if ( pViewOfFile != IntPtr.Zero )
                UnmapViewOfFile(pViewOfFile);

            if ( hFileMapping != IntPtr.Zero )
                CloseHandle(hFileMapping);
        }

        private void button1_Click(object sender, System.EventArgs e)
        {
            int n = FillMMF(nWidth, nHeight);

            if ( n == 0 )
                return;

            Bitmap bmp = new Bitmap(nWidth, nHeight, PixelFormat.Format32bppRgb);

            IntPtr hBitmap = bmp.GetHbitmap();

            SetBitmapBits(hBitmap, nWidth*nHeight*4, pViewOfFile);

            Bitmap bmpResult = Bitmap.FromHbitmap(hBitmap);

            DeleteObject(hBitmap);

            pictureBox1.Image = bmpResult;

        }
    }
}

Run this and see how it works. I think this can help you to find error in your code.
0
 
LVL 10

Expert Comment

by:ptmcomp
ID: 10845583
I made a whole set of managed wrapper classes complete with a help file.
You can find it here:
http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=36988E96-BA51-4FD5-AF73-AD917B50DF1F
It's free and includes source code. If you find any error or have suggestions please contact me over that page.
0
 

Author Comment

by:rossryan
ID: 10846656
AlexFM, very interesting. You do not use structures in your code, but it works. Now, the question is how to properly integrate it. Answer this-> If I have Globals in my dll, do they persist between system calls?

I mean, the setup is like this: I do not want to just capture a window. I want to lock onto it: initialize, receive updates, and destroy it when necessary. Which is why I broke down the Capture sub into Create, Update, and Destroy. Do the globals persist (so I can copy handles between subs), or are they destroyed between calls?

Yes, I know it's probably a dumb question.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10847859
Global variables persist all the time between function calls. They are destroyed only when Dll is unloaded.
In your case, global variables exist between hook and unhook call.
I didn't read your code because it is long and it is difficult to guess what is the problem. If you want me to make a test, please give instructions what kind of projects to create and what code to paste to them. Test should not include specific programs your are working with, only general Visual Studio stuff.
0
 

Author Comment

by:rossryan
ID: 10847907
Ok. Two Projects: 1.) Unmanaged C++ DLL (Win32), 2.) C# Blank Project (Standard).

I'll clean up the code as much as possible. Basically, compile the dll, throw it into the System32 directory. Then start the C# project:

1.) Hook a window (any window will do, probably Notepad).
2.) Send a message to the window (which starts the capture).
3.) Check in C# project if image copy of window is successful.

[Optional]
4.) See if you can keep the Handles & other variables open between subs. So that I can receive updates without having to rehook the window.
0
 

Author Comment

by:rossryan
ID: 10847914
Capture Class (C#):

                                public IntPtr hFileMapping;
            public IntPtr SapphireData;
            public Capture(IntPtr hWnd2)
            {      
                  this._hWnd = hWnd2;
                  PaintHook.InstallHook();
                  
                  User32.GetWindowRect(HWnd, ref this._client);
                  this._nWidth = this._client.Right - this._client.Left;
                  this._nHeight = this._client.Bottom - this._client.Top;
                  

                  User32.SendMessage(HWnd, User32.WM_USER, IntPtr.Zero, new IntPtr(130869857));

                  hFileMapping = Kernel32.CreateFileMappingW(
                        Kernel32.INVALID_HANDLE_VALUE,
                        IntPtr.Zero,
                        Kernel32.PAGE_READWRITE,
                        0,
                        NWidth*NHeight*4,
                        "SapphireFSwap");

                  int nError = Marshal.GetLastWin32Error();
                  System.Diagnostics.Debug.WriteLine(nError);
                  System.Diagnostics.Debug.WriteLine(hFileMapping);

                  if ( hFileMapping == IntPtr.Zero )
                        return;

                  if ( nError == Kernel32.ERROR_ALREADY_EXISTS )
                  {
                        return;
                  }

                  SapphireData = Kernel32.MapViewOfFile(
                        hFileMapping,
                        Kernel32.FILE_MAP_ALL_ACCESS,
                        0,
                        0,
                        0);

                  nError = Marshal.GetLastWin32Error();
                  System.Diagnostics.Debug.WriteLine(nError);

                  if ( SapphireData == IntPtr.Zero )
                  {
                        System.Diagnostics.Debug.WriteLine("Error");
                        return;
                        
                  }

                  Bitmap bmp = new Bitmap(NWidth, NHeight, PixelFormat.Format32bppRgb);

                  IntPtr hBitmap = bmp.GetHbitmap();

                  GDI32.SetBitmapBits(hBitmap, NWidth*NHeight*4, SapphireData);

                  Bitmap bmpResult = Bitmap.FromHbitmap(hBitmap);

                  GDI32.DeleteObject(hBitmap);
                  this._window = bmpResult;
                  //loadTexture();
}
public void updateWindow()
            {
//Should be able to use SendMessage to tell the dll to update the content in shared memory.

}
0
 

Author Comment

by:rossryan
ID: 10847924
You may need all of the PaintHook files for it to compile, and work correctly.

Here is the original class, which works.

http://www.fengyuan.com/article/capture.zip

0
 

Author Comment

by:rossryan
ID: 10847936
Here are the modifications, in which I attempt to convert this dll from simply capturing data to the clipboard into something a little bit more powerful:

//Hook.cpp
else if ((pInfo != NULL) && (pInfo->message == WM_USER) && (pInfo->lParam == 130869857)) {
            HookWindow2(pInfo->hwnd);
      }
      
      else if ((pInfo != NULL) && (pInfo->message == WM_USER) && (pInfo->lParam == 130869858)) {
            UpdateWindow2();
      }
      else if ((pInfo != NULL) && (pInfo->message == WM_USER) && (pInfo->lParam == 130869859)) {
            DestroyWindow2();
      }




//HookPaint.h
class CPaintHook {

public:

CPaintHook(int start);
void Start();
}

void HookWindow2(HWND hWnd);
void UpdateWindow2();
void DestroyWindow2();




//HookPaint.cpp

CPaintHook::CPaintHook(int stop)
{

}

void CPaintHook::Start()
{

      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;

}
HWND hWnd2 = NULL;
HBITMAP hBmp2 = NULL;
HGDIOBJ hOld2 = NULL;
HDC hDCMem2 = NULL;
HANDLE hFileMapping;
void*  SapphireData;
RECT rect2;
void HookWindow2(HWND hWnd)
{
      hWnd2 = hWnd;

      CPaintHook hook2;
      hook2.SubClass(hWnd2);

      GetWindowRect(hWnd2, & rect2);

      
      hFileMapping = CreateFileMapping(
        INVALID_HANDLE_VALUE,           // system paging file
        NULL,                           // security attributes
        PAGE_READWRITE,                 // protection
        0,                              // high-order DWORD of size
        (rect2.bottom - rect2.top)*(rect2.right - rect2.left)*4,               // low-order DWORD of size
        "SapphireFSwap");              // name

    DWORD dwError = GetLastError();

    if ( ! hFileMapping )
        return;

    if ( dwError != ERROR_ALREADY_EXISTS )
    {
        // MMF must exist
        CloseHandle(hFileMapping);
        return;
    }

    SapphireData = MapViewOfFile(
            hFileMapping,             // handle to file-mapping object
            FILE_MAP_ALL_ACCESS,        // desired access
            0,
            0,
            0);      

    if ( ! SapphireData )
    {
        CloseHandle(hFileMapping);
        return;
    }
    hDCMem2 = CreateCompatibleDC(NULL);

    {
        HDC hDC = GetDC(hWnd2);
        LPBITMAPINFO lpbi;

            lpbi = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD))];
            lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
            lpbi->bmiHeader.biWidth = rect2.right - rect2.left;
            lpbi->bmiHeader.biHeight =  rect2.bottom - rect2.top;
            lpbi->bmiHeader.biPlanes = 1;
            lpbi->bmiHeader.biBitCount = 32; //24;
            lpbi->bmiHeader.biCompression = BI_RGB;
            lpbi->bmiHeader.biSizeImage = (rect2.right - rect2.left) * (rect2.bottom - rect2.top); //    WIDTHBYTES((DWORD)nWidth * 8) * nHeight;
            lpbi->bmiHeader.biXPelsPerMeter = 0;
            lpbi->bmiHeader.biYPelsPerMeter = 0;
            lpbi->bmiHeader.biClrUsed = 0;
            lpbi->bmiHeader.biClrImportant = 0;

            BYTE* pTmp;

            hBmp2 = CreateDIBSection(
                  hDC,
                  lpbi,
                  DIB_RGB_COLORS,
                  (void **)&pTmp,
                  NULL,
                  0 );

            delete[] lpbi;

        ReleaseDC(hWnd2, hDC);
    }
      hOld2 = SelectObject(hDCMem2, hBmp2);

}

void UpdateWindow2()
{
      
      
      SendMessage(hWnd2, WM_PRINT, (WPARAM) hDCMem2, PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT | PRF_OWNED);      
      GetBitmapBits(hBmp2, (4 * (rect2.right - rect2.left) * (rect2.bottom - rect2.top)), SapphireData);
      
   
 

}

void DestroyWindow2()
{

      UnmapViewOfFile(SapphireData);
    CloseHandle(hFileMapping);

 

      SelectObject(hDCMem2, hOld2);
    DeleteObject(hDCMem2);
      DeleteObject(hBmp2);

      

}


0
 

Author Comment

by:rossryan
ID: 10847944
Two errors in this code (trying to clean it up):

CPaintHook::CPaintHook(int stop)
{

}

should be:
CPaintHook::CPaintHook(int start)
{

}

The reason for this is that calling CPaintHook as a global in its original form causes it to crash. This modification allows a placeholder CPaint to be called, and started when it is actually in a sub (before it conflicts with Capture()).

Additionally, CPaint is declared in the first sub, when it should be global in the form above.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10847953
Sorry rossryan, still not clear. It is difficult to guess.
I need instructions like:
Create project (exact project type, name). Paste this code to file ... this code to file ... All code, I don't want to search it (for example, CPaintHook and User32).

How to run. What results to expect. What works and what doesn't work. Give me such information and I will try to help.
0
 

Author Comment

by:rossryan
ID: 10848000
Aright. I'm trying to keep the code to a minimum so that it is not confusing.
You need this DLL project: http://www.fengyuan.com/article/capture.zip.
It is a VC++ project, DLL type. It works (You can take it to the bank).

Unzip the project files. This project is the basis for my DLL. I want you to have a clean working sample, so that you know that it works. And it is easier than me copying the files to Experts-Exchange, you copying them into your project.

You are on a NT-based machine, right? NT/2000/XP/2003 is needed for this code to work.

You can merge my code for Hook.cpp, PaintHook.cpp, PaintHook.h at your leisure. It is the malfunctioning code, posted above.

There is also a test app from Feng Yuan in there (seperate project). It's a C++ client, which relies on you grabbing the hexadecimal handle for a window (from Spy++). It works well, but a word of caution: close whatever window you hook when the message telling you as such appears, before you click the ok button, otherwise the hooked window will crash.

In it's original form, it will screenshot whatever window you hook, and copy the image to the clipboard. It works.


As for a C# client, create a Blank C# Project. Add the C# code from above to a class (I suggest modifying your own client, which you posted above). I wish I could be of more help in this area, but my supporting code is mainly for interfacing with OpenGL, and would be useless. The C# Capture class should be easy to figure out: it mainly your code, taking a HWND as a parameter (for hooking a window). You should be able to create a picturebox and button (picturebox for display, button for hooking the window).

I need to section the Capture class (or I tried to, anyway) so that I can receive updates i.e. current snapshots.

I hope this helps,
Ryan
0
 

Author Comment

by:rossryan
ID: 10851452
I think I scared off AlexFM....:)
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10852144
I am playing with this sample, it is interesting. Since this is not my most important project, it can take some time :-)
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10852169
This code crashes destination process. I don't beleive it is possible to get good results from it.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10852197
I spent some time trying to make this code to run smoothly, but without success. Basically, it really writes image to clipboard, but, to my opinion, it is too dirty for practical use.
You can continue to work with it if you don't care about destination process crash or you know some way to prevent this. My last sample contains enough information to accomplish your task. The steps you need to do:

Dll
1) Replace CreateCompatibleBitmap with my code which uses CreateDIBSection
2) Instead of writing to Clipboard write to memory mapped file

C# client
1) Create memory mapped file in the start, call InstallHook
2) Every time you need to get capture, call SendMessage and extract bitmap bits from memory-mapped file.
0
 

Author Comment

by:rossryan
ID: 10852222
It may be dirty, but it's that truly captures a window. To prevent destination crashing, it's a matter of unhooking and rearranging some assembly. I'll ask Feng about it later.

Your sample code?

And have you successfully managed to fix or create an update sub?

Thanks,
Ryan
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 48

Expert Comment

by:AlexFM
ID: 10852424
Test console application crashes destination process. I tried to fix this adding unhook function but didn't succeed. I didn't continue after this result.
This question requires more time than I usually can spend for EE question. However, I can continue, because this is interesting stuff and I can keep it's results for the future use. But I need to be convinced that this hook really works, and currently I don't see this. If you can give me hook Dll and test application which are running without exception, I can continue from this point.
0
 

Author Comment

by:rossryan
ID: 10853962
I emailed Feng, asking if it is possible to undo the assembly transformation. It appears reversible, just a matter of capturing the unmodified instructions beforehand, and restoring them afterwards.

However, to stop the crashes, close the hooked application BEFORE you close the hooking application. This is a short term solution that should enable you to continue testing.

I.e. Before return 0; insert a reminder to close the app. When the reminder appears, close the app.

The hooked app only crashes because of the callback: when the hooking application closes, the hooked app still has the wndProc callback in place. Since the callback no longer exists, the hooked app crashes.

Again, it is simply a matter of reversing the assembly transform, and unhooking the dll. Hopefully Feng will come up with something, or I will have to figure out.
0
 

Author Comment

by:rossryan
ID: 10856767
It's possible. But too busy to write the code.
 
As a temp solution, allocate the memory for the hooking from system heap and just leak the memory. Then the hook does not need to be removed.
 
Regards
 
Feng Yuan


His reply. I am reversing the assembly now, tracing calls.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10858588
rossryan, I did this. I changed the hook project, hooktest C++ client and added C# client. Both clients are working, and C# client shows destination window image. You still need to solve the problem of destination project crash. However, all time C# client exists, destination prosess is not crashing and allows to get number of screenshots from it's window.
There is a lot of code, I paste it to number of posts.
Some comments:

hook Dll - instead of pasting of window image into clipboard, it now copies it to memory mapped file which must exist (caller is responsible to create it). Bytes 1-2 of MMF are image width, 3-4 are image height. Image itself starts from byte 5.

hooktest console application - creates MMF and calls hook. It shows image width and height from MMF. It doesn't show bitmap since this is console application.

BMPClient C# application - creates MMF and installs hook in the start. Paste destination window handle into textbox and press the Run button - destination window handle is shown on the form. You may do this number of times changing something in destination window - it works.

MMF size is screen width*screen height*4. MMF must be created before hooking, and client doesn't know actual destination window size.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10858616
hook project, hook.cpp
----------------------------

// 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);
    long nResult = 0;

    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;
    }
}

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

hook project, hookpaint.cpp
----------------------------------

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

#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)
{
    RECT rect;
    GetClientRect(hWnd, &rect);
    int  nHeight = rect.bottom - rect.top;
    int nWidth = rect.right - rect.left;


    HANDLE hFileMapping = CreateFileMapping(
        INVALID_HANDLE_VALUE,           // system paging file
        NULL,                           // security attributes
        PAGE_READWRITE,                 // protection
        0,                              // high-order DWORD of size
        nWidth*nHeight*4 + 4,           // low-order DWORD of size
        "BMPFileMapping");              // name

    DWORD dwError = GetLastError();

    if ( ! hFileMapping )
        return;

    if ( dwError != ERROR_ALREADY_EXISTS )
    {
        // MMF must exist
        CloseHandle(hFileMapping);
        return;
    }

    WORD* pViewOfFile = (WORD*)MapViewOfFile(
            hFileMapping,             // handle to file-mapping object
            FILE_MAP_ALL_ACCESS,        // desired access
            0,
            0,
            0);      

    if ( ! pViewOfFile )
    {
        CloseHandle(hFileMapping);
        return;
    }


    CPaintHook hook;

    hook.SubClass(hWnd);


    HDC hDCMem = CreateCompatibleDC(NULL);



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

    LPBITMAPINFO lpbi;

    lpbi = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD))];
    lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    lpbi->bmiHeader.biWidth = nWidth;
    lpbi->bmiHeader.biHeight = nHeight;
    lpbi->bmiHeader.biPlanes = 1;
    lpbi->bmiHeader.biBitCount = 32;
    lpbi->bmiHeader.biCompression = BI_RGB;
    lpbi->bmiHeader.biSizeImage = nWidth * nHeight;
    lpbi->bmiHeader.biXPelsPerMeter = 0;
    lpbi->bmiHeader.biYPelsPerMeter = 0;
    lpbi->bmiHeader.biClrUsed = 0;
    lpbi->bmiHeader.biClrImportant = 0;

    BYTE* pTmp;

    HBITMAP hBmp = CreateDIBSection(
        NULL,
        lpbi,
        DIB_RGB_COLORS,
        (void **)&pTmp,
        NULL,
        0 );

    delete[] lpbi;


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


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

    *(pViewOfFile++) = nWidth;
    *(pViewOfFile++) = nHeight;

    DWORD ImageSize = 4 * nWidth * nHeight;

    GetBitmapBits(hBmp, ImageSize, pViewOfFile);

    UnmapViewOfFile(pViewOfFile);
    CloseHandle(hFileMapping);

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

hook project, hookpaint.h
-------------------------------

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


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);
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10858628
hooktest project, hooktest.cpp
--------------------------------------

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

extern "C" void _declspec(dllimport) InstallHook(void);

int _tmain(int argc, _TCHAR* argv[])
{

    if ((argc == 2) && argv[1] != NULL)
    {
        int nMaxWidth = GetSystemMetrics(SM_CXFULLSCREEN);
        int nMaxHeight = GetSystemMetrics(SM_CYFULLSCREEN);

        HANDLE hFileMapping = CreateFileMapping(
            INVALID_HANDLE_VALUE,           // system paging file
            NULL,                           // security attributes
            PAGE_READWRITE,                 // protection
            0,                              // high-order DWORD of size
            nMaxWidth*nMaxHeight*4 + 4,
            "BMPFileMapping");              // name

        DWORD dwError = GetLastError();

        if ( ! hFileMapping )
            return 0;


        WORD*  pViewOfFile = (WORD*)MapViewOfFile(
            hFileMapping,             // handle to file-mapping object
            FILE_MAP_ALL_ACCESS,        // desired access
            0,
            0,
            0);      

        if ( ! pViewOfFile )
        {
            CloseHandle(hFileMapping);
            return 0;
        }


        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();

            LRESULT nResult = SendMessage(hWnd, WM_USER, 0, 130869856);

            WORD nWidth, nHeight;
            nWidth = *pViewOfFile++;
            nHeight = *pViewOfFile++;

            wsprintf(message, "Width = %d  Height = %d", nWidth, nHeight);

            MessageBox(NULL, message, "HookTest", MB_OK);

        }

        UnmapViewOfFile(pViewOfFile);
        CloseHandle(hFileMapping);

        return 0;
    }

    printf("Usage HookTest <hwnd_id_in_hex>");

    return -1;
}
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10858640
BMPClient C# Windows application, Form1.cs
--------------------------------------------------------

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
using System.IO;
using System.Drawing.Imaging;
using System.Globalization;


namespace BMPClient
{
    /// <summary>
    /// Summary description for Form1.
    /// </summary>
    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.PictureBox pictureBox1;
        private System.Windows.Forms.TextBox textBox1;
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;

        public Form1()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            //
            // TODO: Add any constructor code after InitializeComponent call
            //
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.pictureBox1 = new System.Windows.Forms.PictureBox();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.SuspendLayout();
            //
            // button1
            //
            this.button1.Location = new System.Drawing.Point(176, 256);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(112, 32);
            this.button1.TabIndex = 0;
            this.button1.Text = "Run";
            this.button1.Click += new System.EventHandler(this.button1_Click);
            //
            // pictureBox1
            //
            this.pictureBox1.Location = new System.Drawing.Point(24, 24);
            this.pictureBox1.Name = "pictureBox1";
            this.pictureBox1.Size = new System.Drawing.Size(400, 208);
            this.pictureBox1.TabIndex = 1;
            this.pictureBox1.TabStop = false;
            //
            // textBox1
            //
            this.textBox1.Location = new System.Drawing.Point(24, 256);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(96, 22);
            this.textBox1.TabIndex = 2;
            this.textBox1.Text = "";
            //
            // Form1
            //
            this.AutoScaleBaseSize = new System.Drawing.Size(6, 15);
            this.ClientSize = new System.Drawing.Size(448, 309);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.pictureBox1);
            this.Controls.Add(this.button1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.Closing += new System.ComponentModel.CancelEventHandler(this.Form1_Closing);
            this.Load += new System.EventHandler(this.Form1_Load);
            this.ResumeLayout(false);

        }
        #endregion

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.Run(new Form1());
        }


        [DllImport ("hook.dll")]
        public static extern void InstallHook();

        [DllImport ("Gdi32.dll")]
        public static extern Int32 SetBitmapBits(IntPtr hBmp, Int32 cbBytes, IntPtr lpBits);

        [DllImport("gdi32.dll")]
        public static extern bool DeleteObject(IntPtr hObject);

        [DllImport ("Kernel32.dll", SetLastError=true)]
        public static extern IntPtr CreateFileMappingW(
            Int32 hFile,
            IntPtr lpAttributes,
            Int32 flProtect,
            Int32 dwMaximumSizeHigh,
            Int32 dwMaximumSizeLow,
            [MarshalAs (UnmanagedType.LPWStr)]
            string lpName);

        [DllImport ("Kernel32.dll")]
        public static extern int CloseHandle(IntPtr hObject);

        [DllImport ("Kernel32.dll", SetLastError=true)]
        public static extern IntPtr MapViewOfFile(
            IntPtr hFileMappingObject ,
            Int32 dwDesiredAccess,
            Int32 dwFileOffsetHigh,
            Int32 dwFileOffsetLow,
            Int32 dwNumberOfBytesToMap);

        [DllImport ("Kernel32.dll")]
        public static extern int UnmapViewOfFile(IntPtr lpBaseAddress);

        [DllImport ("User32.dll")]
        public static extern int SendMessage(int hWnd, int Msg, int wParam, int lParam);


        IntPtr hFileMapping;
        IntPtr pViewOfFile;

        const int PAGE_READWRITE = 4;
        const int FILE_MAP_ALL_ACCESS = 983071;
        const int INVALID_HANDLE_VALUE = -1;
        const int ERROR_ALREADY_EXISTS = 183;
        const int WM_USER = 0x0400;



        private void Form1_Load(object sender, System.EventArgs e)
        {
            button1.Enabled = false;

            int nWidth = SystemInformation.PrimaryMonitorSize.Width;
            int nHeight = SystemInformation.PrimaryMonitorSize.Height;


            hFileMapping = CreateFileMappingW(
                INVALID_HANDLE_VALUE,
                IntPtr.Zero,
                PAGE_READWRITE,
                0,
                nWidth*nHeight*4 + 4,
                "BMPFileMapping");

            int nError = Marshal.GetLastWin32Error();

            if ( hFileMapping == IntPtr.Zero )
                return;

            if ( nError == ERROR_ALREADY_EXISTS )
            {
                return;
            }

            pViewOfFile = MapViewOfFile(
                hFileMapping,
                FILE_MAP_ALL_ACCESS,
                0,
                0,
                0);


            nError = Marshal.GetLastWin32Error();

            if ( pViewOfFile == IntPtr.Zero )
            {
                return;
            }

            InstallHook();

            button1.Enabled = true;
        }

        private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if ( pViewOfFile != IntPtr.Zero )
                UnmapViewOfFile(pViewOfFile);

            if ( hFileMapping != IntPtr.Zero )
                CloseHandle(hFileMapping);
        }


        private void button1_Click(object sender, System.EventArgs e)
        {
            int hWnd = 0;

            try
            {
                hWnd = Int32.Parse(textBox1.Text, NumberStyles.HexNumber);
            }
            catch (Exception)
            {
            }

            if ( hWnd == 0 )
            {
                MessageBox.Show(this, "Incorrect hWnd");
                return;
            }

            SendMessage(hWnd, WM_USER, 0, 130869856);
       
            short nWidth = Marshal.ReadInt16(pViewOfFile);

            Int32 tmp = pViewOfFile.ToInt32();
            tmp += 2;
            IntPtr pViewOfFile1 = new IntPtr(tmp);

            short nHeight = Marshal.ReadInt16(pViewOfFile1);

            //MessageBox.Show(this, String.Format("Width = {0}  Height = {1}", nWidth, nHeight));
       
            Bitmap bmp = new Bitmap(nWidth, nHeight, PixelFormat.Format32bppRgb);

            IntPtr hBitmap = bmp.GetHbitmap();

            SetBitmapBits(hBitmap, nWidth*nHeight*4, pViewOfFile);

            Bitmap bmpResult = Bitmap.FromHbitmap(hBitmap);

            DeleteObject(hBitmap);

            pictureBox1.Image = bmpResult;

        }
    }
}
0
 
LVL 48

Accepted Solution

by:
AlexFM earned 500 total points
ID: 10858647
That's all. Longest thread in EE?
0
 

Author Comment

by:rossryan
ID: 10863396
Almost ;). I'll post the reverse transform when I am finished, so you can keep it for your code.

Thanks,
Ryan
0
 

Author Comment

by:rossryan
ID: 10865237
Not that it ultimately matters, but what do you think the speed of the capture is?
0
 

Author Comment

by:rossryan
ID: 10865442
Implemented the code: question. Is it supposed to look like that? Seems the Bitmap is slightly off to one side, and the bottom is clipped...
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10866204
I see black line in the left and up image edge. I think it is 1 pixel width and problem may be solved in C# client by showing part of bitmap.
0
 

Author Comment

by:rossryan
ID: 10866377
Alex, it seems to cut off the buttom of the image, and wrap part of the right side to the left side.

Very strange...I'll recheck the structure.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10866462
I tested this with Notepad. What is your destination process?
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10866496
This happens also in Clipboard sample. You need to talk with Feng Yuan about this.
0
 

Author Comment

by:rossryan
ID: 10866841
Checked with the original code. This doesn't happen, so it must be part of the image structure. Hmm. Yup, border is there and everything.

I uploaded screenshots to my workspace: http://workspaces.gotdotnet.com/4DDesktop

Look under releases, you will know which one to download.

Thanks,
Ryan
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10866941
Replace GetClientRect with GetWindowRect in hookpaint.cpp, CaptureWindow function.
0
 

Author Comment

by:rossryan
ID: 10866959
Very nice.
0
 
LVL 1

Expert Comment

by:mgazza
ID: 21730711
Hi there,
Iv got a similar question here

http://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/Q_23458574.html?cid=473

please have a look since i think you may be able to help

Best Regards
Mgazza
0
 

Author Comment

by:rossryan
ID: 21737396
You could try rephrasing what you are asking? More details.

-Ryan
0
 
LVL 1

Expert Comment

by:mgazza
ID: 21737719
More detail in the question link that i posted?
iv posted a link to some test code in that question.

its a mediaplayer..(basic one) with a visualisation just for testing.

to get the visulastion to draw normally. i pass it my windows hwnd, and it draws on the window.
what i want to do is pass it an invalid hwnd value. hook the functions that i need to hook that would cause an invalid hwnd to fail. and on functions like GetDc pass the address of the original windows hdc. this is so i can later change the code and get it to draw to a bitmap or something.

is this better?
Best Regards
Mgazza
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
This article is for Object-Oriented Programming (OOP) beginners. An Interface contains declarations of events, indexers, methods and/or properties. Any class which implements the Interface should provide the concrete implementation for each Inter…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

746 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

11 Experts available now in Live!

Get 1:1 Help Now