🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.nativeapi
9 messages
9 total messages Started by Mike Collins Sun, 11 Jun 2006 15:11
Message-Only Invisible Window
#3446
Author: Mike Collins
Date: Sun, 11 Jun 2006 15:11
52 lines
3625 bytes
Hi all,

Just looking for a bit of information on creating hidden message windows for 
a DLL.  The background is that I have a bug in a DLL that i've written that 
seems to stem from the fact that the calling process exports some functions 
that are not thread safe.

Basically a ProcessA calls my DLL and makes available some functions for my 
DLL by passing my DLL a pointer to a specific structure.  My DLL has two 
threads, it's main thread (threadM) and a secondary one that examines some 
hardware (threadH).  If a certain hardware condition occurs, I need to call 
one of the functions in the calling processA.  However, if threadH calls the 
exported function, the whole system can, on occasion stop working correctly 
or work sporadically.

For this reason my main DLL thread needs to create a message-only window so 
the secondary hardware polling thread can inform it with a custom message, 
of the hardware condition.  In response to this, the main thread, threadM, 
can then call the non-thread-safe function in ProcessA.

After reading MSDN, it seems that I can do this with CreateProcess and 
CreateProcessEx, passing HWND_MESSAGE as the hWndParent.  However, I'm not 
100% sure what calls I need to implement in this particular case.  Normally 
when using CreateWindow I would do the following;

1) define a WndProc callback procedure for the intended window.
2) define and propagate a WNDCLASS or WNDCLASSEX class structure.
3) Register the class with a call to RegisterClass or RegisterClassEx.
4) If sucessfull, call CreateWindow or CreateWindowEx with the same 
classname as used in WNDCLASS.
5) If a valid HWND is created, call ShowWindow() and UpdateWindow().
6) Enter a while(GetMessage()) loop.

However, the situation that I have is slightly different and I need to 
confirm the following:

1) Are there any specific properties, other than HWND_MESSAGE as the 
hWndParent, that I need to set in either WNDCLASS / WNDCLASSEX or 
RegisterClass / RegisterClassEx in my specific situation?
2) Do I need to call ShowWindow() or UpdateWindow in this particular context 
as I don't really have a window to show?
3) Do I specifically have code the while(GetMessage()) loop or can I rely on 
the WndProc to detect and capture my custom messages?  I only ask this 
because it would seem to me that if I have a while loop in the start-up of 
my DLL's main thread, it would then in effect pause the thread as it would 
be sitting in that loop.
4) I want to ensure that no other processes can attempt to close or 
terminate this hidden window - what is the best way to prevent this.


Any help or pointers would be great - google search is a bit limited on this 
subject 
Re: Message-Only Invisible Window
#3448
Author: Bob Gonder
Date: Sun, 11 Jun 2006 15:39
43 lines
2911 bytes
Mike Collins wrote:

>Basically a ProcessA calls my DLL and makes available some functions for my 
>DLL by passing my DLL a pointer to a specific structure.  My DLL has two 
>threads, it's main thread (threadM) and a secondary one that examines some 
>hardware (threadH).  If a certain hardware condition occurs, I need to call 
>one of the functions in the calling processA.  However, if threadH calls the 
>exported function, the whole system can, on occasion stop working correctly 
>or work sporadically.

So, really, your dll creates One thread (threadH), and your theadM is
actually ProcessA?
So, you want ProcessA to call the function.
You could tell the author of ProcessA to handle your special message.
Or you could create a global hook that gets injected into ProcessA's
message handling.

See  SetWindowsHookEx()

You might Google for code that Remy has posted several times.

>1) Are there any specific properties, other than HWND_MESSAGE as the 
>hWndParent, that I need to set in either WNDCLASS / WNDCLASSEX or 
>RegisterClass / RegisterClassEx in my specific situation?

I don't think so.

>2) Do I need to call ShowWindow() or UpdateWindow in this particular context 
>as I don't really have a window to show?

I don't think so, or maybe with SW_SHOW_HIDDEN

>3) Do I specifically have code the while(GetMessage()) loop or can I rely on 
	Yes
>the WndProc to detect and capture my custom messages?  I only ask this 
	No
>because it would seem to me that if I have a while loop in the start-up of 
>my DLL's main thread, it would then in effect pause the thread as it would 
>be sitting in that loop.
	Yes. That's why you used CreateProcess or CreateThread
>4) I want to ensure that no other processes can attempt to close or 
>terminate this hidden window - what is the best way to prevent this.
	Best way to prevent that is to not do it this way.
Re: Message-Only Invisible Window
#3449
Author: JD
Date: Sun, 11 Jun 2006 17:32
8 lines
1020 bytes
Bob Gonder <notbg@notmindspring.invalid> wrote:
>
> [...] Best way to prevent that is to not do it this way.

Sounds like a damn virus to me.

~ JD
Re: Message-Only Invisible Window
#3451
Author: Bob Gonder
Date: Sun, 11 Jun 2006 18:08
8 lines
1243 bytes
JD wrote:
>Bob Gonder  wrote:
>>
>> [...] Best way to prevent that is to not do it this way.
>
>Sounds like a damn virus to me.

Or good defensive programming for a public kiosk.
Re: Message-Only Invisible Window
#3452
Author: Mike Collins
Date: Sun, 11 Jun 2006 23:57
35 lines
2443 bytes
Ok guys, not a virus - would like to think that i've asked enough stupid 
questions here that people would know i'm not a virus writter.

I just didn't want to distract from the problem by going into a long 
explaination of the exact problem.  Basically I'm bug fixing a GinaStub 
system that we have had in place for the last 9 months.  I've just recently 
started to recieve some errors.  On careful examination and scowering MSDN, 
I have found that the winlogon exported funtions are not thread safe.  In my 
main dll / thread I had a procedure that called a specific winlogon exported 
function.  My polling thread would call this procedure.  However, this would 
seem to be in the context of the polling thread, not the main thread.

So this is the reason for the message window.  The polling thread would 
SendMessage to the hidden window which would call the procedure in the 
context of the main thread.

I've got a basic implimentation working now except it causes some strange 
problems in Windows 2k3 i.e. seems to cause certain services not to start.

If i simply wanted to hide a window i would do it with ShowWindow....

Mike


"JD" <nospam@nospam.com> wrote in message 
news:448c53ad$1@newsgroups.borland.com...
>
> Bob Gonder <notbg@notmindspring.invalid> wrote:
>>
>> [...] Best way to prevent that is to not do it this way.
>
> Sounds like a damn virus to me.
>
> ~ JD
> 
Re: Message-Only Invisible Window
#3453
Author: Dennis Jones
Date: Mon, 12 Jun 2006 03:53
110 lines
5349 bytes
"Mike Collins" <its@TheBottomOfThePost.com> wrote in message
news:448c3299@newsgroups.borland.com...

> After reading MSDN, it seems that I can do this with CreateProcess and
> CreateProcessEx, passing HWND_MESSAGE as the hWndParent.  However, I'm not
> 100% sure what calls I need to implement in this particular case.
Normally
> when using CreateWindow I would do the following;
>
> 1) define a WndProc callback procedure for the intended window.
> 2) define and propagate a WNDCLASS or WNDCLASSEX class structure.
> 3) Register the class with a call to RegisterClass or RegisterClassEx.
> 4) If sucessfull, call CreateWindow or CreateWindowEx with the same
> classname as used in WNDCLASS.
> 5) If a valid HWND is created, call ShowWindow() and UpdateWindow().
> 6) Enter a while(GetMessage()) loop.
>
> However, the situation that I have is slightly different and I need to
> confirm the following:
>
> 1) Are there any specific properties, other than HWND_MESSAGE as the
> hWndParent, that I need to set in either WNDCLASS / WNDCLASSEX or
> RegisterClass / RegisterClassEx in my specific situation?
> 2) Do I need to call ShowWindow() or UpdateWindow in this particular
context
> as I don't really have a window to show?
> 3) Do I specifically have code the while(GetMessage()) loop or can I rely
on
> the WndProc to detect and capture my custom messages?  I only ask this
> because it would seem to me that if I have a while loop in the start-up of
> my DLL's main thread, it would then in effect pause the thread as it would
> be sitting in that loop.
> 4) I want to ensure that no other processes can attempt to close or
> terminate this hidden window - what is the best way to prevent this.

I can't answer your questions directly, but I can tell you that I managed to
create an invisible window to process messages in a service (a service does
not normally receive/process Windows messages, and I needed to handle the
WM_TIMECHANGE message, along with several custom messages).  Basically, my
service follows your steps 1-4 to create a window via CreateWindow().  I do
not call ShowWindow/UpdateWindow nor do I have a GetMessage() loop, and yet,
my service receives and processes Windows messages.

Here is a code-snippet, just in case it proves to be helpful (keep in mind
that this code was implemented in a TService descendant class):

// Services cannot normally receive Windows messages because they do not
have windows associated
// with a desktop.  This function registers a hidden window that is capable
of receiving broadcast
// Windows messages or self-posted messages.
bool TMyService::CreateMessageHandlerWnd( void )
{
   WNDCLASSEX w;
   memset(&w, 0, sizeof(w));
   w.cbSize = sizeof(w);
   w.hInstance = Forms::Application->Handle;
   w.lpfnWndProc = MyServiceWindowProc;
   w.lpszClassName = "MyServiceWindowClass";
   ATOM atom = ::RegisterClassEx(&w);
   if ( atom )
   {
      // TMyService::Handle is a static HWND data member
      TMyService::Handle = ::CreateWindow( w.lpszClassName,
                                                    "",
                                                    WS_DISABLED,
                                                    0, 0, 0, 0,
                                                    NULL,
                                                    NULL,
                                                    w.hInstance,
                                                    NULL);
   }
   return (atom && TMyService::Handle);
}

And the WndProc function is quite simple:

// This is the message processing function.  When the service receives
broadcast messages, or
// or messages posted by the service, they are handled and processed here.
LRESULT CALLBACK TMyService::MyServiceWindowProc( HWND hWnd,
                                                                    UINT
uMsg,
                                                                    WPARAM
wParam,
                                                                    LPARAM
lParam )
{
   TMessage msg;
   msg.Msg = uMsg;
   msg.WParam = wParam;
   msg.LParam = lParam;

   // don't try to handle messages until the service has been instantiated
   if ( MyService )
   {
      switch( uMsg )
      {
         case WM_TIMECHANGE:
            MyService->WMTimeChangeHandler( msg );
            break;

         // etc.
      }
   }
   return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}

- Dennis
Re: Message-Only Invisible Window
#3456
Author: JD
Date: Mon, 12 Jun 2006 11:51
13 lines
1469 bytes
"Mike Collins" <its@TheBottomOfThePost.com> wrote:
>
> Ok guys, not a virus - would like to think [...]

Don't mind me. I just went a round with a particularly nasty
one that worked exactly how you described ... 2 processes that
monitored the other so if you killed one process, the other
restarted it. It also renamed itself and set the file date to
years ago and monitored the registry as well so if you removed
it from there ... you get the idea.

~ JD
Re: Message-Only Invisible Window
#3457
Author: Mike Collins
Date: Mon, 12 Jun 2006 14:32
22 lines
1992 bytes
Yeh, I know what you mean, it's a pity that some of these creative virus 
writers couldn't put there skill to something more useful than popping porn 
up on our desktops.

In reality, the methods that they adopt are usually pretty simplistic  - 
just creative use of the win api's.  The real skill is in rootkiting and dll 
inject - total system cloaking - but it's hard work and you need to stay 
abreast of the windows updates.  We have a system like this running and it's 
pretty impressive - just looks like there's nothing there :) - but our 
product is a legitimate one.....

I think i had explained myself badly in the first place...

No offence taken, regards

"JD" <nospam@nospam.com> wrote in message 
news:448d552a$1@newsgroups.borland.com...
>
> "Mike Collins" <its@TheBottomOfThePost.com> wrote:
>>
>> Ok guys, not a virus - would like to think [...]
>
Re: Message-Only Invisible Window
#3458
Author: Mike Collins
Date: Mon, 12 Jun 2006 14:37
136 lines
6487 bytes
Thanks for the post - your code works pretty much as mine does.  I've 
upgraded it to use the Ex versions of RegisterClass and CreateWindow and it 
works brilliantly.  Obviously the  while(GetMessage()) loop is used to 
translate user input message and in my case this is not necessary AND blocks 
the further flow of the dll's processing.

A point worth noting for you is that if you set the parent window handle to 
HWND_MESSAGE - the message window does not appear when you enumerate windows 
so it's a bit harder for others to find the handle and mess on with it.  The 
downside of this is that the window does not receive broadcast messages but 
in my case that is now an issue.



"Dennis Jones" <nospam@nospam.com> wrote in message 
news:448ce553$1@newsgroups.borland.com...
>
> "Mike Collins" <its@TheBottomOfThePost.com> wrote in message
> news:448c3299@newsgroups.borland.com...
>
>> After reading MSDN, it seems that I can do this with CreateProcess and
>> CreateProcessEx, passing HWND_MESSAGE as the hWndParent.  However, I'm 
>> not
>> 100% sure what calls I need to implement in this particular case.
> Normally
>> when using CreateWindow I would do the following;
>>
>> 1) define a WndProc callback procedure for the intended window.
>> 2) define and propagate a WNDCLASS or WNDCLASSEX class structure.
>> 3) Register the class with a call to RegisterClass or RegisterClassEx.
>> 4) If sucessfull, call CreateWindow or CreateWindowEx with the same
>> classname as used in WNDCLASS.
>> 5) If a valid HWND is created, call ShowWindow() and UpdateWindow().
>> 6) Enter a while(GetMessage()) loop.
>>
>> However, the situation that I have is slightly different and I need to
>> confirm the following:
>>
>> 1) Are there any specific properties, other than HWND_MESSAGE as the
>> hWndParent, that I need to set in either WNDCLASS / WNDCLASSEX or
>> RegisterClass / RegisterClassEx in my specific situation?
>> 2) Do I need to call ShowWindow() or UpdateWindow in this particular
> context
>> as I don't really have a window to show?
>> 3) Do I specifically have code the while(GetMessage()) loop or can I rely
> on
>> the WndProc to detect and capture my custom messages?  I only ask this
>> because it would seem to me that if I have a while loop in the start-up 
>> of
>> my DLL's main thread, it would then in effect pause the thread as it 
>> would
>> be sitting in that loop.
>> 4) I want to ensure that no other processes can attempt to close or
>> terminate this hidden window - what is the best way to prevent this.
>
> I can't answer your questions directly, but I can tell you that I managed 
> to
> create an invisible window to process messages in a service (a service 
> does
> not normally receive/process Windows messages, and I needed to handle the
> WM_TIMECHANGE message, along with several custom messages).  Basically, my
> service follows your steps 1-4 to create a window via CreateWindow().  I 
> do
> not call ShowWindow/UpdateWindow nor do I have a GetMessage() loop, and 
> yet,
> my service receives and processes Windows messages.
>
> Here is a code-snippet, just in case it proves to be helpful (keep in mind
> that this code was implemented in a TService descendant class):
>
> // Services cannot normally receive Windows messages because they do not
> have windows associated
> // with a desktop.  This function registers a hidden window that is 
> capable
> of receiving broadcast
> // Windows messages or self-posted messages.
> bool TMyService::CreateMessageHandlerWnd( void )
> {
>   WNDCLASSEX w;
>   memset(&w, 0, sizeof(w));
>   w.cbSize = sizeof(w);
>   w.hInstance = Forms::Application->Handle;
>   w.lpfnWndProc = MyServiceWindowProc;
>   w.lpszClassName = "MyServiceWindowClass";
>   ATOM atom = ::RegisterClassEx(&w);
>   if ( atom )
>   {
>      // TMyService::Handle is a static HWND data member
>      TMyService::Handle = ::CreateWindow( w.lpszClassName,
>                                                    "",
>                                                    WS_DISABLED,
>                                                    0, 0, 0, 0,
>                                                    NULL,
>                                                    NULL,
>                                                    w.hInstance,
>                                                    NULL);
>   }
>   return (atom && TMyService::Handle);
> }
>
> And the WndProc function is quite simple:
>
> // This is the message processing function.  When the service receives
> broadcast messages, or
> // or messages posted by the service, they are handled and processed here.
> LRESULT CALLBACK TMyService::MyServiceWindowProc( HWND hWnd,
>                                                                    UINT
> uMsg,
>                                                                    WPARAM
> wParam,
>                                                                    LPARAM
> lParam )
> {
>   TMessage msg;
>   msg.Msg = uMsg;
>   msg.WParam = wParam;
>   msg.LParam = lParam;
>
>   // don't try to handle messages until the service has been instantiated
>   if ( MyService )
>   {
>      switch( uMsg )
>      {
>         case WM_TIMECHANGE:
>            MyService->WMTimeChangeHandler( msg );
>            break;
>
>         // etc.
>      }
>   }
>   return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
> }
>
> - Dennis
>
> 
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads