🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.nativeapi
Article #2389

Re: My app closes, but cancels Windows shutdown?

#2389
From: Remy Lebeau (TeamB)
Date: Fri, 09 Mar 2007 18:37
133 lines
6487 bytes
"A Nonymous" <anonymous@hotmail.com> wrote in message
news:Xns98EE722D896C6anonymoushotmailcom@207.105.83.66...

> I can't debug the app while Windows is shutting down

You could have your app install an OS-level message hook for itself
via SetWindowsHookEx(), and then check all messages that are received.
Both the WH_CALLWNDPROC and WH_CALLWNDPROCRET hooks provide you the
specific HWND that is processing each message, and WH_CALLWNDPROCRET
gives you the final result of the message as well.  So you could be
notified of all windows that receive WM_QUERYENDSESSION, check if any
of them return FALSE, and if so then log the HWND's class name.  That
will, at least, tell you whether or not AllocateHWnd() is at fault to
begin with.  The class name of the HWND that AllocateHWnd() creates is
"TPUtilWindow".

If that is the case, then you could use GetWindowLong() to get the
pointer to the HWND's window procedure, which will be a pointer to
Borland's proxy stub, and then extract the original TMethod from that
stub.  That TMethod will point directly to the class method that was
passed to AllocateHWnd().  From that, you will have the 'this' pointer
for the object, which you could cast to a TComponent pointer and
access its properties normally.  For example:

    --- MyProject.cpp ---

    HHOOK hHook = NULL;

    LRESULT CALLBACK CallWndRetProc(int nCode, WPARAM wParam, LPARAM
lParam)
    {
        if( nCode == HC_ACTION )
        {
            CWPRETSTRUCT *ret = (CWPRETSTRUCT*) lParam;

            if( (ret->message == WM_QUERYENDSESSION) && (ret->lResult
== FALSE) )
            {
                TCHAR szClassName[16] = {0};
                GetClassName(ret->hwnd, szClassName, 15);

                if( lstrcmp(szClassName, TEXT("TPUtilWindow")) == 0 )
                {
                    LPBYTE ptr = (LPBYTE) GetWindowLong(ret->hwnd,
GWL_WNDPROC);
                    TComponent *comp = (TComponent*)
(((TMethod*)(ptr+5))->Data);
                    // log information about comp, such as its Name...
                }
                else
                {
                    // log information about the HWND for later
inspection...
                }
            }
        }

        return CallNextHookEx(hHook, nCode, wParam, lParam);
    }

    WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
lpCmdLine, int nCmdShow)
    {
        hHook = SetWindowsHookEx(WH_CALLWNDPROCRET, (HOOKPROC)
&CallWndRetProc, NULL, 0);

        // normal app code here...

        UnhookWindowsHookEx(hHook);
        return 0;
    }

> Looking for a better solution, I created a fake shutdown utility
that
> would send a WM_QUERYENDSESSION message to my app
> in hopes that I could debug my app to see how it responded to the
> message.  Well it shuts down and returns true, which is what it is
> supposed to do according to everything I have read.

But you are only sending the message to the program's main window, not
to any of its secondary windows.  You need to do that if you are going
to continue down that route.

> I actually expected to see my app to return false.

The main window will only return FALSE to that message if the
OnCloseQuery event hanlder sets the CanClose parameter to false (or if
any of the VCL's termination procedures return false after the TForm
is closed, but that is a separate issue).  But any of the secondary
windows could be returning FALSE instead or TRUE to the message.  You
are not checking for that yet.

> Some of the suggestion here were that windows might be sending
> WM_QUERYENDSESSION to some window other the the main
> form.  This would certainly explain the situation where shutdown was
> canceled even though the main form returned true.  OK, I modified
> my fake shutdown utility to find the handle of TApplication and
> TFormMain, and they are the  same.

No, they are not the same.  They are very distinct windows that are
separate from each other.  AllocateHWnd() also creates a separate
window.  And let's not forget the case where user/library code may be
calling CreateWindow/Ex() directly as well.  You woud have to loop
through all running windows on the system, such as with EnumWindows(),
use GetWindowThreadProcessId() to determine which windows belong to
the target application, and then you can send your messages to all of
those windows.

> According to the docs I have Windows should only be
> sending to the main form of the app, so child forms should
> not be involved?

Not true.  There is no such thing as a "main" window from the Win32
API's perspective.  It sends the shutdown messages to all top-level
windows, regardless of how Borland has wrapped them.

> What other forms in my app could be involved?

Every TForm is involved, as are every AllocateWnd() window, and any
windows the user/library may be creating manually.

> Tracing messages sent to my app and debugging with the fake
> shutdown doesn't seem to be revealing anything.

That is because you are not doing it correctly yet.

> How can I enumerate all window handles on my system?

EnumWindows()


Gambit
Technical Details
Message-ID: <45f1a96b$1@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news4.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail
References: <Xns98ED90968E734anonymoushotmailcom@207.105.83.66> <45f07307@newsgroups.borland.com> <Xns98ED988E421A8anonymoushotmailcom@207.105.83.66> <45f08f8f$1@newsgroups.borland.com> <Xns98EDAC20DAA4Eanonymoushotmailcom@207.105.83.66> <45f095bf$1@newsgroups.borland.com> <45f0a594@newsgroups.borland.com> <45f0a77f$1@newsgroups.borland.com> <45f0d6c1@newsgroups.borland.com> <Xns98EE722D896C6anonymoushotmailcom@207.105.83.66>

Show Full Headers
Complete Article Headers
X-Google-Thread: 10cc67,346f60f70c29a156
X-Google-Attributes: gid10cc67,public
X-Google-Language: ENGLISH,ASCII-7-bit
From: "Remy Lebeau \(TeamB\)" <no.spam@no.spam.com>
Newsgroups: borland.public.cppbuilder.nativeapi
References: <Xns98ED90968E734anonymoushotmailcom@207.105.83.66> <45f07307@newsgroups.borland.com> <Xns98ED988E421A8anonymoushotmailcom@207.105.83.66> <45f08f8f$1@newsgroups.borland.com> <Xns98EDAC20DAA4Eanonymoushotmailcom@207.105.83.66> <45f095bf$1@newsgroups.borland.com> <45f0a594@newsgroups.borland.com> <45f0a77f$1@newsgroups.borland.com> <45f0d6c1@newsgroups.borland.com> <Xns98EE722D896C6anonymoushotmailcom@207.105.83.66>
Subject: Re: My app closes, but cancels Windows shutdown?
Date: Fri, 9 Mar 2007 10:37:30 -0800
Lines: 135
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2800.1409
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1409
NNTP-Posting-Host: 75.83.34.171
Message-ID: <45f1a96b$1@newsgroups.borland.com>
X-Trace: newsgroups.borland.com 1173465451 75.83.34.171 (9 Mar 2007 10:37:31 -0800)
Path: arc1-ca.pugleaf.net!g2news1.google.com!news4.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail