News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

IPC, WM_COPYDATA (IPC between desktops)

Started by Vozzie, September 25, 2012, 07:12:29 AM

Previous topic - Next topic

Vozzie

Hi,

I'm writing (for fun) a kiosk application that creates a second desktop runs some applications on it and only returns to the original desktop when the users enters a password. I got all this working and have 2 processes each running in a different desktop account.

My problem is i thought using WM_COPYDATA to communicate between the 2 applications but i can't find the window handle of the application running on the other desktop. I have the DF_ALLOWOTHERACCOUNTHOOK flag set when using CreateDesktop but that doesn't seem to work. (How can one hook without a window's handle?)

Does anybody know if it's possible to find the handle of a window in process on a created desktop?

And if not, what would be the second best way to communicate between 2 applications? I was thinking about waiting for events in a thread (CreateEvent, WaitForSingleObject etc) but being able to use the application's message window would be best (for me).

Regards,

Michaël

dedndave

there are a couple ways
you could use HWND_BROADCAST to send the first message to all windows
another way might be to use the clipboard to pass the handle

another way to go, altogether, is to use DDE - a bit complicated

still another way is to find the window with EnumWindows
if you create the process, you have the process ID

jj2007

Michaël,

The usual FindWindow etc stuff doesn't work, see below? Can the two apps communicate at all via handles?

If yes, you could pass the handle of the parent via the commandline to the child.

If no, and you don't need nanosecond speed, then polling with WM_TIMER and exchanging data via disk files works fine and is simple.

include \masm32\MasmBasic\MasmBasic.inc   ; download
   Init
   .if WinByTitle("Post reply")   ; returns handle in eax
      xchg eax, ebx
      Print "The full title is ", Win$(ebx)
      SendData ebx, "Hello Mozilla, you cannot use this string..."
      SetWin$ ebx="... but I can change your caption, hehe..."
   .else
      Print "no handle found..."
   .endif
   Inkey
   Exit
end start

dedndave

oh yah - then there is always the command line - lol
nice, Jochen   :t

a method i have used before and forgot all about   :lol:

Vozzie

Hy,

Because i want to use WM_COPYDATA because of it is convenient that you get a return value for your "command" i'll go for HWND_BROADCAST joined with a message created with RegisterWindowsMessage to pass the HWND from one to the other. If this doesn't work i'll try the commandline,... Hope that WM_COPYDATA then breaks the "desktop" barrier...

If not i'll maybe leave the communication behind(kill the process with TerminateProcess instead of WM_CLOSE) because the other options are (not bad but) too much hassle for too little need. (And it's always most fun when something that didn't work finally works...)

I thought to make it possible to load DLL's in both processes to make this program more dynamic. And make a way for those dll's to communicate. But i can leave this feature of communication behind and then the only need to communicate is to stop the other process properly.

Thx, greetings and i'll probably share some results...

qWord

You can enumerate all top level windows of a desktop using EnumDesktopWindows().
If you assign a unique property to the main window (SetProp) you can easily identify your application in that desktop.
In the attachment an working(Win7,x64) example.
MREAL macros - when you need floating point arithmetic while assembling!

Vozzie

Hi,

I was typing this while you posted...

Quote from: myselfHWND_BROADCAST wasn't very successfull either. Guess that's it impossible...

The bible states:
Quote from: MSDN LibraryWindow messages can be sent only between processes that are on the same desktop. In addition, the hook procedure of a process running on a particular desktop can only receive messages intended for windows created in the same desktop.

A bit strange, still have to find out what exactly DF_ALLOWOTHERACCOUNTHOOK is for (and maybe how to use it).

I could use the file system to signal the process it can exit and leave the communication i had in mind behind...

I've just seen the EnumDesktopWindows api and thought to give it a try , thx for pointing me out and for your sample i'm about to watch...

Vozzie

Yes! Thank you,  :t  :eusa_clap:

I've added the desk_b.exe in my kiosk's ini file, it was running on the new desktop, then i've hit desk_a.exe on the old desktop and desk_b.exe was gone...

Thank you, i'll try WM_COPYDATA now, i'm excited...  :biggrin:

Update: WM_COPYDATA works

Vozzie

Hi,

Still not the solution, but i found the bottleneck. I wanted to use a "Message Only" window, but that doesn't show up in "EnumDesktopWindows" or "FindWindow". (At least not the way i did create it...)

Invoke RtlFillMemory, Addr wc, SizeOf WNDCLASSEX, 0
Mov wc.cbSize, SizeOf WNDCLASSEX
Mov wc.lpfnWndProc, Offset WndKiosk32Proc
Push hInstance
Pop wc.hInstance
Mov wc.lpszClassName, Offset szClassName
Invoke RegisterClassEx, Addr wc
Invoke CreateWindowEx, 0, Offset szClassName, Offset szNewDesktop, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, hInstance, bNewDesktop


Now i know that messages work i'll find another way to pass the handles... Send it from parent to the child process by commandline, and the child process gets it from the parent process with SendMessage...

Update: FindWindowEx should be able to find it

jj2007

Quote from: Vozzie on September 25, 2012, 10:21:23 AM
Update: WM_COPYDATA works

What you attached doesn't do anything on my machine (XP SP3). I see two dialogs but they seem not to recognise each other. Or do I miss something?

This works, so the problem is elsewhere:

            .elseif WORD ptr wParam == 104
               if 1   ; works
         SendData "Desktop B", Win$(rv(GetDlgItem, hDlg, 100))   ; requires MasmBasic
      else   ; no reaction from Desktop B
         .if rv(GetDlgItemText,hDlg,100,&sz,LENGTHOF sz)
            .if !rvx(hDesk=OpenDesktop,&sz,0,0,0)
               invoke MessageBeep,MB_ICONEXCLAMATION
            .else
               invoke EnumDesktopWindows,hDesk,EnumWindowsProc,2
               invoke CloseDesktop,hDesk
            .endif
         .else
            invoke MessageBeep,MB_ICONEXCLAMATION
         .endif
      endif
            .endif

Vozzie

Hi

The purpose is to run the second dialog on another desktop. There you run them both on the same "Default" desktop, it should work when you enter "Default" in the Edit box...

(By default, there are three desktops in the interactive window station: Default, ScreenSaver, and Winlogon. )

I attached a EasyCode project that runs a program on another desktop named "RunSolo". (The desktop's name is also RunSolo).

CommandLine: RunSolo.exe Notepad.exe
Or: RunSolo.exe desk_b.exe

Greetings

btw: The sample was code from qWord, I did only add the WM_COPYDATA. It looks like qWord made a perfect sample and the assumption that i knew what to do with it, ... Or he was testing me...

dedndave

you could create a temporary file to pass info

qWord

Hi,
can you please recap what you want to do? Why do you want to use WM_COPYDATA?
To you message-only window: replace HWND_MESSAGE with zero -> this creates an invisible top most window, which can be enumerated.
MREAL macros - when you need floating point arithmetic while assembling!

Vozzie

Hi,

I'm @ my job now

Yes i want to use WM_COPYDATA. There was a problem with my program i could not find the window(EnumDesktopWindows, FindWIndowEx,...), BUT in your sample it works perfectly. So I was sure there was a 'bug' in my program.

I was still able to solve this problem this night but i am not sure about the reason. I ignored to call UpdateWindow after CreateWindow and it is possible that EnumDesktopWindows could not find the window due to this...
This evening i'll try with and without the call to UpdateWindow and see if this was the reason,...


What i want to do is

1) find a way to close the program on the new desktop This is OK now
2) load dll's in my program(from a config file) and pass them a "Interface" so they can make calls into my program but also make calls into the other instance of the program. ( by using WM_COPYDATA) Now i can concentrate on this

You all was of great help already.

I have no problem with showing/sharing my project, even i use a (good EasyCode) IDE. But it's a bit overhead to post the project for every single 'problem'.

Vozzie

#14
Quote from: qWord on September 25, 2012, 08:40:43 PM
To you message-only window: replace HWND_MESSAGE with zero -> this creates an invisible top most window, which can be enumerated.

Yes, the problem is indeed the HWND_MESSAGE argument for hWndParent... (And not UpdateWindow).

Double thanks.  :t

MasmBasic looks awesome, but i'll first learn how to walk before i'll run...