Click here to Skip to main content
15,881,248 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

I am using jeffrey richters's example 22 LastMsgBoxInfoLib, modified to hook User32.dll's SetClipboardData and GetClipboardData functions. But after hooking, neither the client app nor dll is able to successfully call OpenClipboard().
The dll is win32 based and client is in mfc, Visual Studiio 2005 SP1, Windows XP Sp3
//This is a GetClipboardData replacement function inside dll
HANDLE WINAPI Hook_GetClipboardData(UINT uType)
{    ......

    //Check if notepad or wordpad
    if(_tcsicmp(allowedAppName, szProcessPathname) == 0)//If user allowed app send info to change value of clipboard
    {
        
        HANDLE nResult = ((PFNGETCLIPBOARDDATA)(PROC) g_GetClipboardData)(uType); //original hooked fn called.
       //now call the openclipboard to set custom data in clipboard.
       //This call fails
       if(OpenClipboard(NULL)){       //this call fails

        ....I never reach here...
        }
         return nResult;

    }
}   
//Code inside mfc client
Before hooking this call works, so I can set data in clipboard first time. But after hooking OpenClipboard() fails.

if(OpenClipboard()){
        HGLOBAL hClipboardData;
         bool res = EmptyClipboard();
         TCHAR* arr;
         size_t bytes = (m_szCer.GetLength()+1)*sizeof(TCHAR);
         hClipboardData = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,(m_szCer.GetLength()+1)*sizeof(TCHAR));
         if (!hClipboardData) return;
         arr=(TCHAR*)GlobalLock(hClipboardData);
         _tcscpy(arr, LPCTSTR(m_szCer));         
         //This call always returns false;
          res = GlobalUnlock(hClipboardData);//Here result is always false.
        //Why the above call always fails...
        
         VERIFY(SetClipboardData(CF_UNICODETEXT, hClipboardData));
         res = CloseClipboard();
        
    }   
Also the following line in the function always returns false whether called before or after hooking.

res = GlobalUnlock(hClipboardData);//Here result is always false.     
My idea was to try to unhook the the two clipboard function before I reset the clipboard second time, but no luck.
///this call is to set the hook, dwThreadId =0;
LastClipBoardInfo_HookAllApps(TRUE,dwThreadId,"fsd","as",.....);
///and this call to unhook is
LastClipBoardInfo_HookAllApps(FALSE,dwThreadId,"","",.....);

Please help me on this.

Thanks

Bikram...
Posted
Updated 6-Jul-11 8:19am
v3
Comments
TRK3 6-Jul-11 14:21pm    
Added code blocks for you. It would help if you included a link to the example code you are referencing, as well as a link to this thread http://social.msdn.microsoft.com/Forums/en-HK/vcgeneral/thread/56776b15-ac5c-4490-9026-36efecee9329 where you got some answers to a related problem.
bikramthapa 6-Jul-11 16:12pm    
Hi TRK3,
Ya, my mistake, I should have done that. Here is the link to the project example I used:http://www.wintellect.com/Downloads/Windows%20via%20C++%20Code%20(December%201,%202007).zip The projects are 22-LastMsgBoxInfo and 22-LastMsgBoxInfoLib.
The solution to the problem posted by me earlier simply involved having correct function name and function prototype, so I thought that won't be relevant to current issue. But yes, I should have posted the link to the sample code. Sorry for that.

Regards
Bikram...
Rage 8-Jul-11 6:13am    
Is the issue then solved ?
bikramthapa 13-Jul-11 21:26pm    
Hi Rage,
I did the GetLastError() and found that for openclipboard() the handle was invalid. The reason being inside my hooked function, I cannot access the clipboard. So from inside my dll I pass commandline to my dialog box.
FORWARD_WM_COPYDATA(hdlMl1, , NULL, &cds, SendMessage);

//This is a GetClipboardData replacement function inside dll
HANDLE WINAPI Hook_GetClipboardData(UINT uType)
{
......
//Check if notepad or wordpad
if(_tcsicmp(allowedAppName, szProcessPathname) == 0)//If user allowed app send info to change value of clipboard
{
HANDLE nResult = ((PFNGETCLIPBOARDDATA)(PROC) g_GetClipboardData)(uType); //original hooked fn called.
//now call the openclipboard to set custom data in clipboard.
//This call fails
if(OpenClipboard(NULL)){ //this call fails
.....
}
//So used this technique
COPYDATASTRUCT cds = { 0, ((DWORD)_tcslen(pszDest) + 1) * sizeof(TCHAR), pszDest};
FORWARD_WM_COPYDATA(hdlMsWheel1, NULL, &cds, SendMessage);//send message to mfc client app
}
}


Then inside my dialobox I use wm_copydata in my messagemap.
The procedure to handle is
//Window Procedure to grab command line argument if program already running
LRESULT CKlipboardControllerDlg::OnCopyData(WPARAM wParam, LPARAM lParam)
{
......
COPYDATASTRUCT* pCDS = reinterpret_cast<copydatastruct*>(lParam);
TCHAR* pszCmdLine = static_cast<tchar*>(pCDS->lpData);
//SendMessage will always fail the openclipboard()
PostMessage(WM_COMMAND,IDC_BUTTON_HIDDEN,0);//simulate hidden button click
....
}

void CKlipboardControllerDlg::OnBnClickedButtonHidden()
{
// TODO: Add your control notification handler code here
if(stepCount == 2)//check how many times call from dll was made
{
if(OpenClipboard()){
....//set new data
}
}
}

The results are unreliable. If say I have two strings 346456 and 454. If I do paste operation in quick succession, the result should first print first string followed by second string and third time the clipboard should not print any thing. But sometimes first string is printed twice , other times second string is printed more than once etc. Because I do the post call to reset clipboard content, the stepCount variable has old value while the second call has been made.
How can I do a post message to call any method inside my dll instead of passing commandline to client application.
My second option would be to make stepCount variable thread safe, I tried critical section but no luck. stepCount is int member variable of my dialogbox class. Can u suggest means to make postmessage calls to this variable lock while its inside the the function CKlipboardControllerDlg::OnBnClickedButtonHidden();

Thanks
Bikram...
KarstenK 14-Jul-11 3:57am    
you got to understand PostMessage (RTFM). The messages got quequed and unordered worked. PostMessage is somehow "unsure" in results ;-)

I have done this: PostMessage with a pointer to memory where the string data is, so the other modul can access the raw data.

1 solution

"An application should call the CloseClipboard function after every successful call to OpenClipboard."

http://msdn.microsoft.com/en-us/library/ms649048(v=vs.85).aspx[^]
 
Share this answer
 
Comments
bikramthapa 13-Jul-11 21:30pm    
Hi KarstenK,
Thanks for ur input, but I had resolve that issue already. Please check my reply to "Rage" : Is the issue then solved ?
Can u please suggest some ideas.

Regards
Bikram...

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900