2

I am pulling my hair out on this one. I am trying to send a message to a window in another process. I keep getting Access Denied (0x5) from GetLastError() after calling SendMessage or PostMessage or PostThreadMessage. I have tried turning off UAC. I have also accounted for UIPI by ensuring that the Integrity Levels match accross processes. (I checked with Process Explorer from SysInternals, now MS) I also turned off Windows Defender with no luck. I can send a message to the window from inside the process just fine, but from outside I get bupkus! This seems like some sort of security issue but I have no idea what it is as both processes have the same Integrity Level (medium - decimal 8192)

Code from DLL sending the message

UINT MsgCode = ::RegisterWindowMessage(_T("MESSAGE_CODING_STRING"));
::ChangeWindowMessageFilter(MsgCode,MSGFLT_ADD);
::PostMessage(hwnd1,MsgCode,(WPARAM)1,(LPARAM)1);
DWORD errorcode = ::GetLastError();

Selected Code from recieving Window

BEGIN_MESSAGE_MAP(CMessageMailBox, CDialog)
    ON_REGISTERED_MESSAGE(MsgCode, TextFromApp)
END_MESSAGE_MAP()

// Class Constructor    
CMessageMailBox::CMessageMailBox(CWnd* pParent /*=NULL*/)
        : CDialog(CMessageMailBox::IDD, pParent){
       MsgCode = ::RegisterWindowMessage(_T("MESSAGE_CODING_STRING"));
       ::ChangeWindowMessageFilter(MsgCode,MSGFLT_ADD);
    }

//Message Handler   
    afx_msg LRESULT CMessageMailBox::TextFromApp(WPARAM wParam,LPARAM lParam){
        ::MessageBox(NULL,L"message recieved",L"yea!",MB_OK);
        return 0L;
    }
JohnG
  • 75
  • 1
  • 4
  • 10
  • Are both apps running as desktop apps? Or is one of them a service or running under a different session? – jdigital May 29 '09 at 03:44
  • Is the above pseudo-code? Because it looks erroneous; how can you use MsgCode in the message map BEFORE it is initialized in the constructor? I am not expert of MFC, but maybe that's the problem? – beef2k May 29 '09 at 05:40
  • Process explorer states that both are running in Session 1. The top code section is running in a dll that has been injected into another process with a WH_CALLWNDPROC hook. I think I can use MsgCode in the message map with ON_REGISTERED_MESSAGE and not plain old ON_MESSAGE. This message map works with a sendmessage call from inside the process but not from the injected dll. – JohnG May 30 '09 at 04:11
  • How are you getting the window handle that goes into hwnd1? If you're just passing the numeric value of the handle from one process to another, it's not likely to work without a call to DuplicateHandle(). – DavidK May 31 '09 at 09:26
  • I was simply passing the numeric value. However, according to this http://msdn.microsoft.com/en-us/library/ms724251(VS.85).aspx DuplicateHandle does not duplicate a HWND. Any suggestions on how to use DupHandle to create a HWND? I get "the handle is invalid" error even after casting the source HWND to a HANDLE. – JohnG May 31 '09 at 16:35
  • 2
    After re-reading Petzold, I've realised I was wrong: window handles are system-wide, so you can just pass the number. Given that, it sounds like UIPI is still the problem for some reason. Can you try the code on XP to see if it works there? – DavidK Jun 03 '09 at 15:51
  • I was going to try that but instead gave up. I have implemented a named pipe as recommened by beef2k. I am rather disappointed I could not solve this one... The only XP machine I have is in pieces at the moment so I didnt have an easy way to test it. But I agree with you, I am pretty sure it is caused by some Vista security "feature" although I did turn off UAC completely with no change. – JohnG Jun 06 '09 at 06:40
  • 1
    The process that is receiving the message has to be the one to call ChangeWindowMessageFilter(), to allow the message to be received. Calling it from the DLL that is trying to send the message will not unblock the message in the receiving process. Also, are you sure the error from GetLastError() is actually related to the PostMessage() and not some earlier API call? Calling GetLastError() after PostMessage() is not meaninful if PostMessage() does not return FALSE. – Remy Lebeau Jun 17 '09 at 00:36
  • 2
    Also, did you check to make sure that ChangeWindowMessageFilter() is succeeding in the first place? – Remy Lebeau Jun 17 '09 at 00:39
  • I called ChangeWindowMessageFilter in both the sending and recieving processes. I did not check the success of this call however. Unfortunately, I have solved my problem with a named pipe so I cant go back and test that. Thanks for your input though. – JohnG Jul 11 '09 at 05:04

2 Answers2

2

Looks like it is a case of User Interface Privilege Isolation (UIPI) (That is if your DLL is loaded to another process)

Use ChangeWindowMessageFilterEx on the receiving process. I hope it will work

2

Does it have to be a message? There are plenty of ways to communication between different processes:

  • Pipes
  • Sockets
  • Shared Memory
  • Files
beef2k
  • 2,233
  • 2
  • 19
  • 20
  • 1
    I think I will have to go with one of those options if I cant get this to work. I didn't want to go to the trouble for such a small notification. – JohnG May 30 '09 at 03:42
  • Pipes are actually pretty simple to implement. Probably the best choice for your problem. – beef2k May 30 '09 at 06:02