Jump to content
Sign in to follow this  
Decipher

How to prep system for non standard shutdown using WinAPI and DLL calls?

Recommended Posts

Please see this post

I've started try to code this but I'm having trouble with the DLL syntax and I'd like to be sure that the system is safe to power down before I force it to do so.

I've tried:

$iReturnValue = DllCall("advapi32.dll", "int", "RegFlushKey", "long", "HKEY_CLASSES_ROOT")
if @error Then MsgBox(0, "", "Fail!")
MsgBox(0, "Flush Home Key Classes Root", $iReturnValue)


$bReturnValue = DllCall("kernel32.dll", "BOOL", "FlushFileBuffers", "HANDLE", "\\.\" & @HomeDrive)
if @error Then MsgBox(0, "", "Fail!")
MsgBox(0, "Flush System Drive Cache", $iReturnValue);Should return 1=true or 0=false.

But I can't determine if these functions are working correctly. Any help is greatly appreciated like always.

Share this post


Link to post
Share on other sites

dllcall return array so instead $iReturnValue try $iReturnValue[0]


TCP server and client - Learning about TCP servers and clients connection
Au3 oIrrlicht - Irrlicht project
Au3impact - Another 3D DLL game engine for autoit. (3impact 3Drad related)



460px-Thief-4-temp-banner.jpg
There are those that believe that the perfect heist lies in the preparation.
Some say that it’s all in the timing, seizing the right opportunity. Others even say it’s the ability to leave no trace behind, be a ghost.

 

Share this post


Link to post
Share on other sites

I'm still unsure wether the FlushRegistry function is working properly because I've never done DLL calls before and it returns the same no matter what registry key string(i.e. bla) is passed to it. The FlushSystemDriveCache function reports that I'm using an invalid handle...

#include <WinAPI.au3>

Global Const $ERROR_SUCCESS = 0
Global Const $KEY_ALL_ACCESS = 0xF003F

_FlushRegistry()
_FlushSystemDriveCache()

Func _FlushRegistry()
    Local Const $aHive[6] = [ _
        "HKEY_CLASSES_ROOT",  _
        "HKEY_CURRENT_CONFIG", _
       " HKEY_CURRENT_USER", _
       " HKEY_LOCAL_MACHINE", _
       " HKEY_PERFORMANCE_DATA", _
        "HKEY_USERS"]
    Local $aReturnValue
    For $i = 0 To 5 Step 1
        $aReturnValue = DllCall("advapi32.dll", "int", "RegFlushKey", "long", $aHive[$i])
        If @error Or $aReturnValue[0] <> 0 Then
            ConsoleWrite("ERROR! Could not flush " & $aHive[$i] & "! " & _WinAPI_GetLastErrorMessage() & @CRLF)
        EndIf
    Next
EndFunc

Func _FlushSystemDriveCache()
    Local $aReturnValue = DllCall("kernel32.dll", "BOOL", "FlushFileBuffers", "HANDLE", "\\.\" & @HomeDrive)
    If @error Or $aReturnValue[0] == 0 Then
        ConsoleWrite("ERROR! Could not flush the system drive. " & _WinAPI_GetLastErrorMessage() & @CRLF)
    EndIf
EndFunc

*Edit - to fix code indentations.

I just realized that I have to get a handle to the specified hive and pass that instead. This probably the case with the drive param as well.

Okay this is where I'm getting confused:

LONG WINAPI RegOpenKeyEx(
_In_     HKEY hKey,
_In_opt_ LPCTSTR lpSubKey,
_Reserved_ DWORD ulOptions,
_In_     REGSAM samDesired,
_Out_    PHKEY phkResult
);

What is _In_? Does it just mean that the value is passed to the function and _Out_ should set the value of a variable pointed to by a pointer variable, nothing more? Horrible semantics whats with all the __bla__ing in this diagram? How do I pass a pointer for phkResult? Should I just pass a predeclared variable? Are all the parameters following _In_opt_ also optional or are they mandatory? Does HKEY mean I should pass a handle because I'm using this to try and get a handle....How to pass NULL for an optional parameter is it a string "0" or what?

Anonymous

Edited by Decipher

Share this post


Link to post
Share on other sites

I think RegFlushKey & FlushFileBuffers only works for the files / keys you opened in your program (to ensure everything is flushed before you exit your app / before you begin the next processing step) and not globally for all keys and files.

But this might be interesting for you:

#cs
    System Shutdown
    http://msdn.microsoft.com/en-us/library/windows/desktop/aa376882%28v=vs.85%29.aspx

    WM_QUERYENDSESSION message
    http://msdn.microsoft.com/en-us/library/windows/desktop/aa376890%28v=vs.85%29.aspx

    WM_ENDSESSION message
    http://msdn.microsoft.com/en-us/library/windows/desktop/aa376889%28v=vs.85%29.aspx

    Application Shutdown Changes in Windows Vista
    http://msdn.microsoft.com/en-us/library/ms700677%28VS.85%29.aspx
#ce

Global Const $HWND_BROADCAST = 0xFFFF
Global Const $SMTO_ABORTIFHUNG = 0x0002

Global Const $WM_QUERYENDSESSION = 0x0011
Global Const $WM_ENDSESSION = 0x0016

Global Const $iENDSESSION_CRITICAL = 0x40000000

_WinAPI_SendMessageTimeout($HWND_BROADCAST, $WM_QUERYENDSESSION, 0, $iENDSESSION_CRITICAL, 1000, $SMTO_ABORTIFHUNG)

_WinAPI_SendMessageTimeout($HWND_BROADCAST, $WM_ENDSESSION, 1, $iENDSESSION_CRITICAL, 1000, $SMTO_ABORTIFHUNG)

; #FUNCTION# ====================================================================================================================
; Name...........: _WinAPI_SendMessageTimeout
; Description....: Sends the specified message to one of more windows.
; Syntax.........: _WinAPI_SendMessageTimeout ( $hWnd, $iMsg [, $wParam [, $lParam [, $iTimeout [, $iFlags]]]] )
; Parameters.....: $hWnd     - Handle to the window whose window procedure will receive the message.
;                $iMsg  - The message to be sent.
;                $wParam   - The message-specific information.
;                $lParam   - The message-specific information.
;                $iTimeout - The duration, in milliseconds, of the time-out period. If the message is a broadcast message, each
;                            window can use the full time-out period. Default is 1000.
;                $iFlags   - The flags that specifies how to send the message. This parameter can be one or more of the
;                            following values.
;
;                            $SMTO_BLOCK
;                            $SMTO_NORMAL
;                            $SMTO_ABORTIFHUNG
;                            $SMTO_NOTIMEOUTIFNOTHUNG
;                            $SMTO_ERRORONEXIT
;
; Return values..: Success   - The result of the message processing, depends on the message sent.
;                Failure   - (-1) and sets the @error flag to non-zero.
; Author.........: Yashied
; Modified.......:
; Remarks........: This function does not provide information about individual windows timing out if $HWND_BROADCAST is used.
;
;                If times out, function fails. To get extended error information, call _WinAPI_GetLastError(). If _WinAPI_GetLastError()
;                returns ERROR_TIMEOUT (1460), then the function timed out. This function considers a thread is not responding if it has
;                not responds within five seconds.
;
;                The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages
;                (those >= WM_USER) to another process, you must do custom marshalling.
; Related........:
; Link...........: @@MsdnLink@@ SendMessageTimeout
; Example........: Yes
; ===============================================================================================================================

Func _WinAPI_SendMessageTimeout($hWnd, $iMsg, $wParam = 0, $lParam = 0, $iTimeout = 1000, $iFlags = 0)

    Local $Ret = DllCall('user32.dll', 'lresult', 'SendMessageTimeoutW', 'hwnd', $hWnd, 'uint', $iMsg, 'wparam', $wParam, 'lparam', $lParam, 'uint', $iFlags, 'uint', $iTimeout, 'dword_ptr*', 0)

    If (@error) Or (Not $Ret[0]) Then
        Return SetError(1, 0, -1)
    EndIf
    Return $Ret[7]
EndFunc   ;==>_WinAPI_SendMessageTimeout
Edited by KaFu

Share this post


Link to post
Share on other sites

Yes, it is interesting. This is the same message that is broadcasted to services, CLI, and GUI based applications during a shutdown? However there are some undefined variables. Could you elaborate on what I'm doing wrong with the UDF?

*Edit - RegFlushKey documentation states that windows has a lazy flush mechanism to enhance system operations as this process is expensive and that those changes that an application makes are visible to other applications. I may be presuming to much about Microsoft's intelligence but if the unflushed changes are visible to other processes and vice versa then wouldn't it be safe to say that these changes are in sync with other processes i.e. just one queue so that when one application forces the flush the only visible current change between them is written to disk. If this is true then I would assume that this means that when a key is flushed to disk that the process that called the function is irrelevant and that when specifying an entire hive unless a process is actively making changes to that hive, all is well and in sync.

Concerning FileFlushBuffers MSDN states: To flush all open files on a volume, call FlushFileBuffers with a handle to the volume. The caller must have administrative privileges. For more information, see Running with Special Privileges. I think this tells the device's cache to be written to disk which is also process irrelevant unless a process is using an unbuffer I/O stream which in that case the process needs to be told to finish what its doing using the function you provided above.

Here is the code to flush the system drive's transmit buffer:

Func _FlushSystemDriveCache()
    Local Const $hSystemVolume = _WinAPI_CreateFile("\\.\" & @HomeDrive, 2, 4, 4, 8)
    If $hSystemVolume Then
        Return _WinAPI_FlushFileBuffers($hSystemVolume)
    Else
        ConsoleWrite("ERROR! Could not retrieve a handle to the system volume." & @CRLF)
    EndIf
EndFunc

MsgBox(0, "Should Return True or 1 for success", _FlushSystemDriveCache())

Exit

Anonymous

Edited by Decipher

Share this post


Link to post
Share on other sites

You might be right about the FlushFileBuffers, without documentation the assumption on RegFlushKey stays exactly that. Updated example two posts above with missing consts.

#RequireAdmin

$iSuccess = _Drive_FlushFileBuffers("c")
MsgBox(0, "", $iSuccess & @CRLF & @error)

Func _Drive_FlushFileBuffers($DriveLetter)

    Local $ret = DllCall("kernel32.dll", 'ptr', 'CreateFileW', _
            'wStr', '\\.\' & $DriveLetter & ':', _
            'dword', BitOR(0x40000000, 0x80000000), _
            'dword', 7, _
            'ptr', 0, _
            'dword', 3, _
            'dword', 0, _
            'ptr', 0 _
            )

    If @error Then Return SetError(1)
    If $ret[0] = 0xFFFFFFFF Then Return SetError(2)
    Local $ret2 = DllCall("kernel32.dll", "int", "FlushFileBuffers", "ptr", $ret[0])
    If $ret2[0] = 0 Then
        DllCall("kernel32.dll", 'int', 'CloseHandle', 'hwnd', $ret[0])
        Return SetError(3)
    EndIf
    DllCall("kernel32.dll", 'int', 'CloseHandle', 'hwnd', $ret[0])
    Return 1
EndFunc   ;==>_Drive_FlushFileBuffers

Share this post


Link to post
Share on other sites

KaFu,

I just ran the code to broadcast the WMQueryEndSession message and it worked like a charm!

Now you show me how to pass a null value(ptr = 0) and also how to combine multiple dword flags using BitOr.....

Question: In your HO, If we broadcat EndSession, set a timeout then kill other nonessential processes, flush the registry, and flush system drive cache then would it be okay to terminate the system processes to force a power down when an emergency shutdown doesn't do the job?

Thanks,

Anonymous

Edited by Decipher

Share this post


Link to post
Share on other sites

Well, I would guess that pretty much is done then. Everything essential? I don't know, only Microsoft could tell. Everything the proper way? No, that's what the Shutdown() function is for.

Share this post


Link to post
Share on other sites

I can't seem to find anything that says explicitly that RegFlushKey is used during the shutdown procedure. I did however find some information for clearing that paging file or maybe just deleting it and its registration which isn't what we want. It can be deleted using WMI but I keep getting a sharing violation.

; Generated by AutoIt Scriptomatic

$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$colItems = ""
$strComputer = "localhost"

$Output=""
$Output = $Output & "Computer: " & $strComputer & @CRLF
$Output = $Output & "==========================================" & @CRLF
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_PageFile", "WQL", _
                                         $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

If IsObj($colItems) then
For $objItem In $colItems
MsgBox(0, "Change", $objItem.ChangeSecurityPermissions(0x10000, 1)) ; Comment this line to get past the intial object error.
MsgBox(0, "Check", $objItem.GetEffectivePermission(0x10000))
     MsgBox(0, "Delete", $objItem.Delete())
     if Msgbox(1,"WMI Output",$Output) = 2 then ExitLoop
     $Output=""
Next
Else
Msgbox(0,"WMI Output","No WMI Objects Found for class: " & "Win32_PageFile" )
Endif

*Edit - Added Link ---> Delete Method of the Win32_PageFile Class and see the links @ SECURITY DESCRIPTOR STRUCTURE directly below --> (See Also)

*Edit #2 - Here is the alleged code to flush the registry similar to whats done when the system is being shutdown but there is not any documentation to support the theory.

#include <WinAPI.au3>

Global Const $ERROR_SUCCESS = 0
Global Const $KEY_ALL_ACCESS = 983103

; ----Verified Handles -------------------------------------------------------------------------------------------------------------------------------------------
Global Enum $HKEY_CLASSES_ROOT, $HKEY_CURRENT_USER, $HKEY_LOCAL_MACHINE, $HKEY_USERS, _
    $HKEY_PERFORMANCE_DATA, $HKEY_CURRENT_CONFIG
Global Const $HKEY_HANDLES[6] = [0x80000000, 0x80000001, 0x80000002, 0x80000003, 0x80000004, 0x80000005]
; _______________________________________________________________________________________________

_FlushRegistry()

Func _FlushRegistry()
    Local $aReturnValue
    For $i = 0 To 5 Step 1
        $aReturnValue = DllCall("advapi32.dll", "int", "RegFlushKey", "dword", $HKEY_HANDLES[$i])
        If @error Or $aReturnValue[0] <> $ERROR_SUCCESS Then
            MsgBox(0, "", "ERROR! Could not flush hive at " & $HKEY_HANDLES[$i]  & _WinAPI_GetLastErrorMessage() & @CRLF)
        EndIf
        ConsoleWrite("Hive #" & $i & " Returned: " & $aReturnValue[0] & @TAB & "handle = " & $aReturnValue[1] & @CRLF)
    Next
EndFunc

Exit
Edited by Decipher

Share this post


Link to post
Share on other sites

From here:

Alternatively, the registry has a 'lazy flush' mechanism that flushes registry modifications to disk at regular intervals of time. In addition to this regular flush operation, registry changes are also flushed to disk at system shutdown. Allowing the 'lazy flush' to flush registry changes is the most efficient way to manage registry writes to the registry store on disk.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

BrewManNH,

There is a small controversy about the RegFlushKey API. Do you know of any documentation to support the theory that it is the specific function that is used during the shutdown procedure? This leads some to think that it is only process specific and is a fair conclusion.

*Edit -

KaFu,

This may be to low level bro but do you think that we could broadcast IRP_MJ_SHUTDOWN.

Anonymous

Edited by Decipher

Share this post


Link to post
Share on other sites

This may be to low level bro but do you think that we could broadcast IRP_MJ_SHUTDOWN.

From the docs itself I can see that it's really low level, but not what it exactly does. But my assumption is that you can really do some sever damage using this one incorrectly, so I would advise to not investigate this one further.

Share this post


Link to post
Share on other sites

I'm not understanding what possible difference it could make whether it uses this function or another to flush the registry to disk. I'm also not understanding why you think forcing a shutdown is a good practice. If you just use the facilities that are available to shut the computer down safely you can eliminate doing something stupid to the OS.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Similar Content

    • By matwachich
      Hi guys!
      A pretty simple UDF to convert HTML to PDF using wkHTMLtoPDF.
      It uses the C API of the tool (DLL), so no external process, no ActiveX or COM sh*t.
      See the example, and the documentation of wkHTMLtoPDF.
      Cheers
      https://github.com/matwachich/wkhtmltopdf-au3
    • By Skysnake
      This is relevant
      From here https://stackoverflow.com/questions/3454315/is-it-possible-to-pin-a-dll-in-memory-to-prevent-unloading
      I use several UDFs on the Forum to do various things.  Those UDFs work very well.
      Effectively the UDFs are DLL wrappers, that make it possible to access DLL functions easily without the long hard slog of DLLCall() every time.
      However, I have now run into the issue that multiple UDF DLLCalls are slow. Not mind numbingly slow, but slow enough to become noticeable with a large of repeated function calls.
      So I was wondering, is it possible to "load a DLL into memory" and leave it there for the duration of my script's lifetime, avoid repeated DLL on-disk reads with a persistent in memory DLL?
      From Microsoft
      https://docs.microsoft.com/en-us/windows/desktop/dlls/about-dynamic-link-libraries
      Looks like what I want to do is: load-time dynamic linking,
      So next question, (a) how do I do this with AutoIt (b) How would this impact on standard AutoIt type DLL calls?
       
      The point is speed.  Is there a different approach?
      Or am I barking up the wrong tree?
      Skysnake
    • By bladem2003
      Hello,
      i need help to translate the c code to autoit .
      I don't understand the callback function.
       
      #include <windows.h> #include <stdio.h> // native IR Data by PAnsiChar typedef void CALLBACK CallBackPAnsiChar(char*, char*, char*, char*); typedef int (__stdcall *impInitPAnsiChar)(CallBackPAnsiChar); CALLBACK MyCallBackPAnsiChar(char* Protocol, char* Address, char* Command, char* Flags) { printf("\nIR Data received: Protocol: %s, Address: 0x%s, Command: 0x%s, Flags: 0x%s", Protocol, Address, Command, Flags); fflush(stdout); } int main(int argc, char **argv) { impInitPAnsiChar InitPAnsiChar = NULL; // Load DLL file HINSTANCE hinstLib = LoadLibrary(TEXT("USB_IR_Remote_Receiver.dll")); if (hinstLib == NULL) { printf("\nERROR: unable to load DLL\n"); return 1; } // Get function pointer InitPAnsiChar InitPAnsiChar = (impInitPAnsiChar)GetProcAddress(hinstLib, "InitPAnsiChar"); if (InitPAnsiChar == NULL) { printf("\nERROR: unable to find DLL function\n"); FreeLibrary(hinstLib); return 1; } if (InitPAnsiChar(*MyCallBackPAnsiChar)) { printf("\nInit DLL with InitPAnsiChar successfull"); } else { // Unload DLL file FreeLibrary(hinstLib); return 0; } while(1) { } //return 0; }  
    • By Stacker
      Hi all,
      i want to start a new application that capture a screen or image from webcam an read all barcode inside the picture.
      I have test this code https://www.autoitscript.com/forum/topic/27925-webcam-example/
      Works fine for my webcam.
      Now i need to read all barcodes (code 128 code39, no 2d) inside the picture. I have found this https://www.codeproject.com/Articles/42852/Reading-Barcodes-from-an-Image-III
      It's possible to make a dll from VB source i linked  with this  parameters :  filename, Array of barcode founded, error code and launch from Autoit with function ?
      Anyone can help me to make dll and autoit function, i don't know VB.
      Thanks
    • By Davegbuf
      I found a PowerShell module in the TechNet script center that will be useful to me for detecting reboots; however, my knowledge of PowerShell is limited and I don't know how to load the a module for use with my AutoIt scripts. (in case you need it): https://gallery.technet.microsoft.com/scriptcenter/Get-PendingReboot-Query-bdb79542)
      I loaded the PowerShell module successfully manually via the PowerShell ISE on my test machine, and ran a batch command successfully on it too. NOTE: I sometimes use a batch file commands for troubleshooting a few lines of code and then I convert the "known good" command into my final AutoIt scripts).
      As I mentioned, I ran the following batch command-line successfully after I had manually loaded the Powershell module via the ISE (the command  displays a "True" or "False" in the Windows CMD console - see the attachment) :
      PowerShell -Command (Test-PendingReboot -SkipConfigurationManagerClientCheck).IsRebootPending I need to know how I can include the PowerShell module in a subfolder and load it, in addition to running the command-line mentioned above. I have used *.PS1 scripts before in my AutoIt projects, but my general knowledge of Powershell is limited and I don't know how to work with modules. Can anyone with some Powershell knowledge help me with these few lines of code needed to accomplish the goal?
      I would appreciate any help you can offer.

×
×
  • Create New...