Announcement

Collapse
No announcement yet.

Does PowerBasic handle WM_QUERYENDSESSION

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Does PowerBasic handle WM_QUERYENDSESSION

    Windows applications are sent the WM_QUERYENDSESSION message at shutdown. Applications can return TRUE to indicate that they can be closed, or FALSE to indicate that they should not be closed (e.g., because doing so would cause the user to lose data or destroy a CD being burned). Does PowerBasic handle this message. If so, can PowerBasic perform a specific action, specifically write a registry key or run an external program when it receives WM_QUERYENDSESSION

  • #2
    Afaik PB9 is changed to do this.
    It should now handle a double 'return' value.
    hellobasic

    Comment


    • #3
      I assume you mean the PowerBasic Compiler as opposed to the Console Compiler. What is Afaik?

      Can this be done with the console? The result I need is a program that just sits there silently and then either erases a key or runs Regedit to erase a key when Windows exits. I know this can be done with Group Policy or some shareware programs but they won't do. It also has to silently do a little other housekeeping but I think I can handle that.

      Last time I used PowerBasic it was called QuickBasic.

      Comment


      • #4
        Oh I got it. As far as I know, right?

        Comment


        • #5
          You need to use CreateWindow/CreateWindowEx or a dialog resource to create a hidden window in order to capture the message, as you do not have access to the console window handler. Subclassing the console could also be done I suppose, although it's more complex and you don't really need the console.

          Search source code forum for PBCC examples of CreateWindow or dialog box creation. Also see #CONSOLE OFF (sp?) in the PB help file.

          PS> PowerBASIC has never been called QuickBasic, that was a Microsoft product. It was called TurboBASIC in the 80's.
          Last edited by Kev Peel; 30 Oct 2008, 02:14 PM.
          kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

          Comment


          • #6
            Ah yes, my bad. It was so far ahead of Quickbasic it was incredible. It started teaching me structured programming and assembly. Back then the screen write routines were so incredibly slow that you could whatch the characters arrive. I wrote a program which called an assembly language routine to poke the screen... no one could believe it when a complete screen of text would pop up.

            After using the subprogram features, when I graduated to FORTH where structured programming is the only way its possible, I had no problems.

            Since its been so long since I have used PowerBasic and am not at all familiar with the program or documentation, do you think maybe you could be a bit more specific? Exactly how does PB handle a WM_QUERYENDSESSION message? I was hoping that it would be similar to error handling where I could jump to a subroutine.

            Would it be easier to use PB9? I suppose there would be no objection as I'm sure I could hide the window at least until shutdown.
            Last edited by Guest; 30 Oct 2008, 02:42 PM.

            Comment


            • #7
              Welcome (back)

              The compiler itself does not enforce this new method, but Windows. This is the hurdle many programmers face transitioning from DOS. My advice would to get a good book (Charles Petzold's 'Programming Windows' is a good one, although the samples are in C).

              Basically, you provide Windows with a function (which would be a 'callback') and Windows calls the function periodically to send the messages ('events') through to your app. This is part of the 'event driven' model of Windows.

              I just don't have time to write an example at the moment (sorry), but here is some code from Michael Mattias that creates a Window and callback in PBCC:

              Progress Bar Dialog for PB/CC programs

              Would it be easier to use PB9?

              If you already have PB/WIN 9 then YES! It would be extremely easy with PB/WIN DDT statements and there are plenty of sample DDT projects that are supplied with the compiler.
              Last edited by Kev Peel; 30 Oct 2008, 02:46 PM.
              kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

              Comment


              • #8
                See http://msdn.microsoft.com/en-us/library/aa376890(VS.85).aspx and http://msdn.microsoft.com/en-us/library/ms700677(VS.85).aspx.

                A WM_QUERYENDSESSION message is sent to a callback function (see http://www.powerbasic.com/support/he.../callbacks.htm) in PBWin or a user defined WindowProc (see http://msdn.microsoft.com/en-us/library/ms633573(VS.85).aspx) in PBCC.
                Sincerely,

                Steve Rossell
                PowerBASIC Staff

                Comment


                • #9
                  With PB/CC maybe SetConsoleCtrlHandler() with a callback function looking for CTRL_LOGOFF_EVENT might be useful.
                  Michael Mattias
                  Tal Systems (retired)
                  Port Washington WI USA
                  [email protected]
                  http://www.talsystems.com

                  Comment


                  • #10
                    Then if its ok I am going to research what you suggest and re-ask the question in the PBC forum.

                    Comment


                    • #11
                      Originally posted by Thomas Bonge View Post
                      Then if its ok I am going to ... re-ask the question in the PBC forum.
                      If you mean the PowerBasic for Windows forum, then save yourself the effort, more or less the same 200 people will respond in either forum. Also the administrator loveth not crossposting.

                      Comment


                      • #12
                        Try this out.

                        Code:
                        #COMPILE EXE
                        #DIM ALL
                        
                        %CCWIN = 1
                        #INCLUDE "WIN32API.INC"
                        
                        FUNCTION WINMAIN (BYVAL hInstance AS LONG, BYVAL hPrevInstance AS LONG, _
                                          BYVAL lpCmdLine AS ASCIIZ PTR, BYVAL iCmdShow AS LONG) AS LONG
                        
                            DIM hWnd    AS LOCAL    DWORD
                            DIM cWnd    AS LOCAL    WndClassEX
                            DIM szName  AS LOCAL    ASCIIZ * 12
                            DIM tMSG    AS LOCAL    tagMSG
                        
                            szName              = "QSessionEnd"
                            cWnd.cbSize         = SIZEOF(cWnd)
                            cWnd.lpfnWndProc    = CODEPTR(WndProc)
                            cWnd.lpszClassName  = VARPTR(szName)
                            cWnd.hbrBackground  = GETSTOCKOBJECT(%LTGRAY_BRUSH)
                            REGISTERCLASSEX cWnd
                        
                            hWnd = CREATEWINDOW ( szName, "QSessionEnd", %WS_DISABLED, 0, 0, 0, 0, %HWND_DESKTOP, %NULL, hInstance, BYVAL %NULL )
                            SHOWWINDOW hWnd, %SW_HIDE
                        
                            WHILE GETMESSAGE(tMsg, %NULL, 0, 0)
                                TRANSLATEMESSAGE tMsg
                                DISPATCHMESSAGE tMsg
                            WEND
                        
                        END FUNCTION
                        
                        FUNCTION WndProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, _
                                          BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
                        
                            IF wMsg = %WM_QUERYENDSESSION THEN
                                'wParam = 0 = Shutdown Windows Dialog Box
                                PRINT TIME$ & ": Prevented ShutDown.  (" & FORMAT$(wParam) & ")"
                                FUNCTION = 0
                                EXIT FUNCTION
                            END IF
                        
                            FUNCTION = DEFWINDOWPROC(hWnd&, wMsg&, wParam&, lParam&)
                        
                        END FUNCTION
                        LOCAL MyEMail AS STRING
                        MyEmail = STRREVERSE$("53pmohtj") & CHR$(64) & STRREVERSE$("liamg") & CHR$(46) & STRREVERSE$("moc")

                        Comment


                        • #13
                          Thank you so much for posting this. Unfortunately I don't know what to do with it. It'sw not clear if it should be compiled with PB or PBCC but I qassumed PBCC because it references "WIN32API.INC." I tried both and although I could eventually compile both, the Debug-Run of both gave errors. I assume that it presents aq DOS screen then when you try to reboot it cancels the reboot and prints a message to the screen. Assembled with PBCC it gives the blank screen, no message, and crashes on run. Compiled with PB it gives the same blank screen, no message, no crash, but the computer reboots fine.

                          What am I doing wrong?

                          Comment


                          • #14
                            It was meant for CC. It compiled and ran (normal and debug) without issue for me. When I ran the compiled executable it prevented the shutdown. I'm not quite sure what the problem could be. Microsoft has a page that provides further detail into WM_QUERYENDSESSION @ http://msdn.microsoft.com/en-us/libr...90(VS.85).aspx . Maybe this could provide insight?

                            I use this code in a small program I made that sits in the system tray and prevents shutdown until it is closed.
                            LOCAL MyEMail AS STRING
                            MyEmail = STRREVERSE$("53pmohtj") & CHR$(64) & STRREVERSE$("liamg") & CHR$(46) & STRREVERSE$("moc")

                            Comment


                            • #15
                              Code:
                              #DIM ALL
                              #COMPILE EXE
                              #INCLUDE "win32api.inc"
                              FUNCTION PBMAIN
                                SetConsoleCtrlHandler CODEPTR(ConsoleHandler), 1
                                WAITKEY$
                                SetConsoleCtrlHandler CODEPTR(ConsoleHandler), 0
                              END FUNCTION
                              FUNCTION ConsoleHandler(BYVAL dwEvent AS DWORD) AS LONG
                                'these will all terminate the program
                                SELECT CASE dwEvent
                                  CASE %CTRL_C_EVENT
                                    PRINT "Ctrl-C pressed"
                                  CASE %CTRL_BREAK_EVENT
                                    PRINT "Ctrl-Break pressed"
                                  CASE %CTRL_CLOSE_EVENT
                                    PRINT "[x] Close pressed"
                                  CASE %CTRL_LOGOFF_EVENT
                                    PRINT "User logging off or restarting"
                                  CASE %CTRL_SHUTDOWN_EVENT
                                    PRINT "System shutting down"
                                END SELECT
                                ? "Press a key to exit console handler"
                                WAITKEY$
                              END FUNCTION
                              The world is full of apathy, but who cares?

                              Comment


                              • #16
                                John's code needs only slight modification to compile and run with PBWin804 / 9 (replace Print w/ MsgBox ).

                                Here's a version that has the option to resume the shutdown process (after writting to the registry or whatever).
                                The extra code is mostly C&P from PB's sample utility code "Restart.bas". (Plus a check to see if it was shutdown or a logoff that caused the WM_QUERYENDSESSION. - Quicker testing to resume a logoff!)
                                Code:
                                #COMPILE EXE
                                #DIM ALL
                                 
                                #INCLUDE "WIN32API.INC"
                                 
                                '  < First three functions are from PB sample "Restart.bas" -  Mods for Shut down / LogOff.
                                %SHTDN_REASON_FLAG_USER_DEFINED = &H40000000
                                 
                                FUNCTION IsNt () AS LONG
                                 LOCAL tOsVersion AS OSVERSIONINFO
                                  tOsVersion.dwOSVersionInfoSize = SIZEOF(tOsVersion)
                                  IF GetVersionEx(tOsVersion) THEN
                                      FUNCTION = (tOsVersion.dwPlatformId = %VER_PLATFORM_WIN32_NT)
                                  END IF
                                END FUNCTION
                                '------------------/IsNt
                                 
                                FUNCTION AdjustToken () AS LONG
                                 LOCAL hToken       AS DWORD
                                 LOCAL tokenProcess AS TOKEN_PRIVILEGES
                                    ' Get the privilege token for this process. - keep in hToken
                                  IF ISFALSE OpenProcessToken(GetCurrentProcess(), %TOKEN_ADJUST_PRIVILEGES OR %TOKEN_QUERY, hToken) THEN
                                    EXIT FUNCTION
                                  END IF
                                    ' Get the value of the shutdown privilege.
                                  IF LookupPrivilegeValue(BYVAL %NULL, "SeShutdownPrivilege", tokenProcess.Privileges(0).pLuid) THEN
                                    ' Enable the shutdown privilege for this process.
                                    tokenProcess.PrivilegeCount           = 1
                                    tokenProcess.Privileges(0).Attributes = %SE_PRIVILEGE_ENABLED
                                    FUNCTION = AdjustTokenPrivileges(hToken, %FALSE, tokenProcess, 0, BYVAL %NULL, BYVAL %NULL)
                                  END IF
                                 CloseHandle hToken
                                END FUNCTION
                                '------------------/AdjustTken
                                 
                                FUNCTION ResumeShutDown(BYVAL LogOff AS LONG) AS LONG
                                  IF IsNT() THEN
                                    IF ISFALSE AdjustToken() THEN
                                      MSGBOX "Could not obtain shutdown privilege."
                                      EXIT FUNCTION
                                    END IF
                                  END IF
                                    ' If you're using Windows XP or later, you may want to provide a shutdown
                                    ' reason code in the second parameter. See the Reason.inc file for codes.
                                    ' The major reason code should be ORed with the minor reason code.
                                    ' eg %SHTDN_REASON_FLAG_USER_DEFINED  = &H40000000
                                  IF LogOff = 0 THEN
                                    IF ISFALSE ExitWindowsEx(%EWX_SHUTDOWN OR %EWX_FORCEIFHUNG, %SHTDN_REASON_FLAG_USER_DEFINED) THEN
                                        MSGBOX "Shutdown failed."
                                    END IF
                                  ELSE
                                    IF ISFALSE ExitWindowsEx(%EWX_LOGOFF, 0) THEN
                                        MSGBOX "Shutdown failed."
                                    END IF
                                  END IF
                                END FUNCTION
                                '------------------/ResumeShutDown
                                 
                                ' John Thompson. [URL]http://www.powerbasic.com/support/pbforums/showthread.php?p=300964#post300964[/URL]
                                ' with some mods
                                FUNCTION WINMAIN (BYVAL hInstance AS LONG, BYVAL hPrevInstance AS LONG, _
                                                  BYVAL lpCmdLine AS ASCIIZ PTR, BYVAL iCmdShow AS LONG) AS LONG
                                 
                                    DIM hWnd    AS LOCAL    DWORD
                                    DIM cWnd    AS LOCAL    WndClassEX
                                    DIM szName  AS LOCAL    ASCIIZ * 12
                                    DIM tMSG    AS LOCAL    tagMSG
                                 
                                    szName              = "QSessionEnd"
                                    cWnd.cbSize         = SIZEOF(cWnd)
                                    cWnd.lpfnWndProc    = CODEPTR(WndProc)
                                    cWnd.lpszClassName  = VARPTR(szName)
                                    cWnd.hbrBackground  = GETSTOCKOBJECT(%LTGRAY_BRUSH)
                                    REGISTERCLASSEX cWnd
                                 
                                    hWnd = CREATEWINDOW ( szName, "QSessionEnd", %WS_DISABLED, 0, 0, 0, 0, %HWND_DESKTOP, %NULL, hInstance, BYVAL %NULL )
                                    SHOWWINDOW hWnd, %SW_HIDE
                                 
                                    WHILE GETMESSAGE(tMsg, %NULL, 0, 0)
                                        TRANSLATEMESSAGE tMsg
                                        DISPATCHMESSAGE tMsg
                                    WEND
                                 
                                END FUNCTION
                                '------------------/WinMain
                                 
                                FUNCTION WndProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, _
                                                  BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
                                  DIM Res AS LONG
                                  STATIC ThisProc, LogOff AS LONG
                                    IF wMsg = %WM_QUERYENDSESSION THEN
                                        IF ThisProc = 0 THEN
                                            ThisProc = %TRUE          ' Test for resume shutdown
                                            LogOff = IIF(lParam AND %ENDSESSION_LOGOFF = %ENDSESSION_LOGOFF, 1, 0)
                                            MSGBOX TIME$ & ": Prevented ShutDown.  (" & FORMAT$(wParam) & ")"
                                            PostMessage hWnd, %WM_USER + 1000, 0, 0
                                            FUNCTION = 0              ' Stop the shutdown process
                                            EXIT FUNCTION
                                        END IF
                                    END IF
                                 
                                    IF wMsg = %WM_USER + 1000 THEN    ' Here you could do those other things, then..
                                      Res = MSGBOX ("Resume Shutdown / LogOff?", %MB_YESNO OR %MB_SYSTEMMODAL _    ' / logoff
                                               OR %MB_ICONWARNING OR %MB_DEFBUTTON2, "Ready to quit?")
                                      IF Res = %IDYES THEN
                                        ResumeShutDown (LogOff)
                                      ELSE
                                        ThisProc = 0
                                        LogOff = 0
                                      END IF
                                    END IF
                                 
                                  FUNCTION = DEFWINDOWPROC(hWnd&, wMsg&, wParam&, lParam&)
                                 
                                END FUNCTION
                                '------------------/WndProc
                                Rgds, Dave

                                Comment


                                • #17
                                  'Here's a slightly modified vesion of the previous post..
                                  Code:
                                  #COMPILE EXE
                                  #DIM ALL
                                   
                                  #INCLUDE "WIN32API.INC"
                                   
                                  '  < First three functions are from PB sample "Restart.bas" -  Shut down / LogOff.
                                  %SHTDN_REASON_FLAG_USER_DEFINED = &H40000000
                                   
                                  FUNCTION IsNt () AS LONG
                                   LOCAL tOsVersion AS OSVERSIONINFO
                                    tOsVersion.dwOSVersionInfoSize = SIZEOF(tOsVersion)
                                    IF GetVersionEx(tOsVersion) THEN
                                        FUNCTION = (tOsVersion.dwPlatformId = %VER_PLATFORM_WIN32_NT)
                                    END IF
                                  END FUNCTION
                                  '------------------/IsNt
                                   
                                  FUNCTION AdjustToken () AS LONG
                                   LOCAL hToken       AS DWORD
                                   LOCAL tokenProcess AS TOKEN_PRIVILEGES
                                      ' Get the privilege token for this process. - keep in hToken
                                    IF ISFALSE OpenProcessToken(GetCurrentProcess(), %TOKEN_ADJUST_PRIVILEGES OR %TOKEN_QUERY, hToken) THEN
                                      EXIT FUNCTION
                                    END IF
                                      ' Get the value of the shutdown privilege.
                                    IF LookupPrivilegeValue(BYVAL %NULL, "SeShutdownPrivilege", tokenProcess.Privileges(0).pLuid) THEN
                                      ' Enable the shutdown privilege for this process.
                                      tokenProcess.PrivilegeCount           = 1
                                      tokenProcess.Privileges(0).Attributes = %SE_PRIVILEGE_ENABLED
                                      FUNCTION = AdjustTokenPrivileges(hToken, %FALSE, tokenProcess, 0, BYVAL %NULL, BYVAL %NULL)
                                    END IF
                                   CloseHandle hToken
                                  END FUNCTION
                                  '------------------/AdjustTken
                                   
                                  FUNCTION ResumeShutDown(BYVAL LogOff AS LONG) AS LONG
                                    IF IsNT() THEN
                                      IF ISFALSE AdjustToken() THEN
                                        MSGBOX "Could not obtain shutdown privilege."
                                        EXIT FUNCTION
                                      END IF
                                    END IF
                                      ' If you're using Windows XP or later, you may want to provide a shutdown
                                      ' reason code in the second parameter. See the Reason.inc file for codes.
                                      ' The major reason code should be ORed with the minor reason code.
                                      ' eg %SHTDN_REASON_FLAG_USER_DEFINED  = &H40000000
                                    IF LogOff = 0 THEN
                                      IF ISFALSE ExitWindowsEx(%EWX_SHUTDOWN OR %EWX_FORCEIFHUNG, %SHTDN_REASON_FLAG_USER_DEFINED) THEN
                                          MSGBOX "Shutdown failed."
                                      END IF
                                    ELSE
                                      IF ISFALSE ExitWindowsEx(%EWX_LOGOFF, 0) THEN
                                          MSGBOX "Shutdown failed."
                                      END IF
                                    END IF
                                  END FUNCTION
                                  '------------------/ResumeShutDown
                                   
                                  ' John Thompson. [URL]http://www.powerbasic.com/support/pbforums/showthread.php?p=300964#post300964[/URL]
                                  ' with some mods
                                  FUNCTION WINMAIN (BYVAL hInstance AS LONG, BYVAL hPrevInstance AS LONG, _
                                                    BYVAL lpCmdLine AS ASCIIZ PTR, BYVAL iCmdShow AS LONG) AS LONG
                                   
                                      DIM hWnd    AS LOCAL    DWORD
                                      DIM cWnd    AS LOCAL    WndClassEX
                                      DIM szName  AS LOCAL    ASCIIZ * 12
                                      DIM tMSG    AS LOCAL    tagMSG
                                   
                                      szName              = "QSessionEnd"
                                      cWnd.cbSize         = SIZEOF(cWnd)
                                      cWnd.lpfnWndProc    = CODEPTR(WndProc)
                                      cWnd.lpszClassName  = VARPTR(szName)
                                      cWnd.hbrBackground  = GETSTOCKOBJECT(%LTGRAY_BRUSH)
                                      REGISTERCLASSEX cWnd
                                   
                                      hWnd = CREATEWINDOW ( szName, "QSessionEnd", %WS_DISABLED, 0, 0, 0, 0, %HWND_DESKTOP, %NULL, hInstance, BYVAL %NULL )
                                      SHOWWINDOW hWnd, %SW_HIDE
                                   
                                      WHILE GETMESSAGE(tMsg, %NULL, 0, 0)
                                          TRANSLATEMESSAGE tMsg
                                          DISPATCHMESSAGE tMsg
                                      WEND
                                   
                                  END FUNCTION
                                  '------------------/WinMain
                                   
                                  FUNCTION WndProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, _
                                                    BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
                                    DIM Res AS LONG
                                    STATIC ThisProc, LogOff AS LONG
                                      IF wMsg = %WM_QUERYENDSESSION THEN
                                          IF ThisProc = 0 THEN
                                              ThisProc = %TRUE          ' Test for resume shutdown
                                              LogOff = IIF(lParam AND %ENDSESSION_LOGOFF = %ENDSESSION_LOGOFF, 1, 0)
                                   '            MSGBOX TIME$ & ": Prevented ShutDown.  (" & FORMAT$(wParam) & ")"   ' **  moved msgbox         
                                              PostMessage hWnd, %WM_USER + 1000, 0, 0
                                              FUNCTION = 0              ' Stop the shutdown process
                                              EXIT FUNCTION
                                          END IF
                                      END IF
                                   
                                      IF wMsg = %WM_USER + 1000 Then
                                        MSGBOX TIME$ & ": Prevented ShutDown."   ' **
                                   
                                        ' Here you could do those other things, then..
                                   
                                        Res = MSGBOX ("Resume Shutdown / LogOff?", %MB_YESNO OR %MB_SYSTEMMODAL _    ' / logoff
                                                 OR %MB_ICONWARNING OR %MB_DEFBUTTON2, "Ready to quit?")
                                        IF Res = %IDYES THEN
                                          ResumeShutDown (LogOff)
                                        ELSE
                                          ThisProc = 0
                                          LogOff = 0
                                        END IF
                                      END IF
                                   
                                    FUNCTION = DEFWINDOWPROC(hWnd&, wMsg&, wParam&, lParam&)
                                   
                                  END FUNCTION
                                  '------------------/WndProc
                                  With the MsgBox in it's original position, if you wait too long (ie more than about 3 seconds) before clicking OK, the msgbox will close automatically.
                                  (It receives %WM_QUERYENDSESSION itself?) and the Session End process isn't halted.
                                  With the modification the hidden window "QSessionEnd" keeps working until you elect to resume the shutdown / logoff process.
                                  Last edited by Dave Biggs; 24 Nov 2008, 08:47 AM.
                                  Rgds, Dave

                                  Comment

                                  Working...
                                  X