Jump to content

WinAPIEx UDF


Yashied
 Share

Recommended Posts

Link to comment
Share on other sites

The library has been updated, version remains unchanged.

  • Added the following functions.

    _WinAPI_ChangeWindowMessageFilterEx

    _WinAPI_EnumDllProc

  • Added examples for the functions above.
  • Updated documentation.

Thanks for these great functions. I have installed and have tips when editing, but F1 search doesn't bring up the proper help file. Is there a way for me to add the WinAPIEx.chm to the F1 search?

edit: guess it has to be linked in using htmlhelp. Just as easy to do a macro to paste it in. No big deal. Great functions btw. One you added in the latest release I was messing with trying to get it to work all day. Guess I should read the documentation before using DllCall(). :graduated:

Edited by MilesAhead
Link to comment
Share on other sites

For a small speed boost, DLLOpen() can be used on some of the Windows API functions without worrying about an extra drain on resources. For example, the following DLL's are loaded by every process since at least Windows 2000 (and can't be unloaded):

advapi32.dll
comctl32.dll
gdi32.dll
kernel32.dll
ntdll.dll
rpcrt4.dll
shell32.dll
shlwapi.dll
user32.dll

Additionally, AutoIt's interpreter code imports these modules (checked AutoIt versions 3.3.6 -> current beta):

comdlg32.dll
mpr.dll
ole32.dll
oleaut32.dll
psapi.dll
userenv.dll
version.dll
wininet.dll
winmm.dll
wsock32.dll

DLLOpen() on the above DLL's will not affect the memory or resource footprint. DLLClose() doesn't have to be done on the above DLL's either. In most of my own code I use a global DLLOpen() on these DLL's (via an include file), then replace the DLL string with those variables.

Just a tip for whoever :graduated:

Btw Yashied - nice job on the DisplayStruct function. Looks alot nicer than my _DLLStructDisplay UDF.

Edited by Ascend4nt
Link to comment
Share on other sites

@Ascend4nt

I also thought about it, but global DllOpen() does not bring tangible results if the DLL is already loaded. I took a list of loaded DLL through the _WinAPI_EnumProcessModules() function. If DLL is present in this list (under Windows XP), I use DllCall() directly, otherwise I call the __DLL() before DllCall() that increases the DLL counter. For example, see _WinAPI_GetConnectedDlg(), _WinAPI_GetPwrCapabilities(), etc.

Func __DLL($sPath)
    If Not _WinAPI_GetModuleHandle($sPath) Then
        If Not _WinAPI_LoadLibrary($sPath) Then
            Return 0
        EndIf
    EndIf
    Return 1
EndFunc   ;==>__DLL

In the next call to DllCall(), the library will be pre-loaded and DllOpen() is no need. In other words, the following two codes are equivalent in the multiple calls (in terms of speed):

Global Const $hGlobalDll = DllOpen('powrprof.dll')

...

DllCall($hGlobalDll, ...)

If __DLL('powrprof.dll') Then
    DllCall('powrprof.dll', ...)
EndIf

BTW, every call of DllCall () also increases the DLL counter. Also, you can use _WinAPI_GetModuleHandleEx() with $GET_MODULE_HANDLE_EX_FLAG_PIN flag to guarantee the presence of the DLL in memory.

Link to comment
Share on other sites

You may not think so, but using a handle obtained with DLLOpen does in fact result in faster execution. Just run a few tests with TimerInit/Diff and you'll see this clearly. DLLCall() with a DLL handle skips two steps that a typical DLLCall with a DLL name needs to perform (load libraryl, free library).

As far as using your __DLL() function, that's a waste of time - you are calling one to two extra API functions needlessly. And looking through your code now, I see that you have put this in functions where there is absolutely no need for it. DllCall does everything you need. I suggest removing that completely from your code.

I also don't know what the point of using GET_MODULE_HANDLE_EX_FLAG_PIN is. I mean, my post was about GUARANTEED loaded DLL's. This means they will be loaded for the duration of the script, unless you force an unload (which will result in a crash).

Any other DLL can be loaded dynamically with DLLCall or DLLOpen. The ones I listed are there for reference so that a DLLOpen() at the top of a script (to get AutoIt's generic handle) can speed up DLLCall, which it does.

Link to comment
Share on other sites

#Include <WinAPIEx.au3>

$tSPC = DllStructCreate('byte[76]')
$pSPC = DllStructGetPtr($tSPC)

;Test1
ConsoleWrite('powrprof.dll: ' & _WinAPI_GetModuleHandle('powrprof.dll') & @CR)
$Timer = TimerInit()
For $i = 1 To 1000
    DllCall('powrprof.dll', 'int', 'GetPwrCapabilities', 'ptr', $pSPC)
Next
ConsoleWrite(TimerDiff($Timer) & @CR & @CR)

; Test2
$hDll = DllOpen('powrprof.dll')
ConsoleWrite('powrprof.dll: ' & _WinAPI_GetModuleHandle('powrprof.dll') & @CR)
$Timer = TimerInit()
For $i = 1 To 1000
    DllCall($hDll, 'int', 'GetPwrCapabilities', 'ptr', $pSPC)
Next
ConsoleWrite(TimerDiff($Timer) & @CR & @CR)
DllClose($hDll)

; Test3
$hModule = _WinAPI_LoadLibrary('powrprof.dll')
ConsoleWrite('powrprof.dll: ' & _WinAPI_GetModuleHandle('powrprof.dll') & @CR)
$Timer = TimerInit()
For $i = 1 To 1000
    DllCall('powrprof.dll', 'int', 'GetPwrCapabilities', 'ptr', $pSPC)
Next
ConsoleWrite(TimerDiff($Timer) & @CR & @CR)
_WinAPI_FreeLibrary($hModule)

; Test4
ConsoleWrite('powrprof.dll: ' & _WinAPI_GetModuleHandle('powrprof.dll') & @CR)
$Timer = TimerInit()
For $i = 1 To 1000
    __DLL('powrprof.dll')
    DllCall('powrprof.dll', 'int', 'GetPwrCapabilities', 'ptr', $pSPC)
Next
ConsoleWrite(TimerDiff($Timer) & @CR & @CR)

A difference between the second and fourth test are small, but I avoid wasting memory allocated by the DLL that may not be necessary.

Edited by Yashied
Link to comment
Share on other sites

Okay, a few things:

1. You are not wasting any memory with calling DLLOpen() on the preloaded DLL's I listed. That was one of the points made in that post. At *most* you are wasting a few bytes in memory for AutoIt's internal representation of a handle, which is next to nothing.

2. Calling the same API function time after time isn't representative of the huge scope of API functions offered by the DLL's I listed. Plus, there may be memory caching somewhere in searching for the same function string.

3. __DLL() WILL and DOES waste memory. In your UDF, you don't free a DLL that is loaded through this method in your code. The solution is to simply get rid of that function and just use DLLCall on its own. It does the load/free library on its own. If you want to save execution time (if the particular function you need to call is repeatedly used), you should give the programmer the option to load/unload the DLL, or pass an optional parameter if you wish.

Okay, now lets explore what the intention of my post was. Lets use DLLOpen() on one of the guaranteed preloaded DLL's. This will not reload a DLL and all it does is create a generic handle. Lets also add some other functions to the mix:

Global $hUser32=DllOpen('user32.dll')

$iTimer=TimerInit()
For $i=1 To 5000
    $aRet=DllCall('user32.dll','handle','GetDC','hwnd',0)
    DllCall('user32.dll','int','ReleaseDC','hwnd',0,'handle',$aRet[0])
    DllCall('user32.dll',"handle","GetSysColorBrush","int",1)
    DllCall('user32.dll','int','GetSystemMetrics','int',78)
    DllCall('user32.dll','bool','SystemParametersInfoW','uint',0x46,'uint',0,'bool*',0,'uint',0)
Next
ConsoleWrite(TimerDiff($iTimer)&@CRLF)

$iTimer=TimerInit()
For $i=1 To 5000
    $aRet=DllCall($hUser32,'handle','GetDC','hwnd',0)
    DllCall($hUser32,'int','ReleaseDC','hwnd',0,'handle',$aRet[0])
    DllCall($hUser32,"handle","GetSysColorBrush","int",1)
    DllCall($hUser32,'int','GetSystemMetrics','int',78)
    DllCall($hUser32,'bool','SystemParametersInfoW','uint',0x46,'uint',0,'bool*',0,'uint',0)
Next
ConsoleWrite(TimerDiff($iTimer)&@CRLF)

The time gap gets wider the more functions are called (and more times they are called, of course). Obviously what it boils down to is how many API functions are called and how often. However - there is no drawback to using DLLOpen() in these cases, so why not take advantage of it?

I'm not arguing that you add this to your UDF, just suggesting what people can do with it to optimize it further.

Link to comment
Share on other sites

Hi,

Having trouble with _WinAPI_GetFileAttributes on Windows XP SP3 - X86 / Limited User Account

Description:

When "GetFileAttributesW" fails it is returning 4294967295 instead of 0xFFFFFFFF (-1); defeating the error check.

Steps to reproduce:

1) A file that is normally inaccessible (e.g. @HomeDrive &"\pagefile.sys" OR @HomeDrive&"\NOEXISTS"

Results:

Return = 4294967295

Error = 0

Expected results:

Return = 0

Error = 1

Test file:

#include <WinAPIEx.au3>
test()
Func test()
Local $ret = _WinAPI_GetFileAttributes(@HomeDrive &"\NOT_EXIST")
MsgBox(0, 'NOT EXIST', "ret: "& $ret & " err: "& @error)
 
Local $ret = _WinAPI_GetFileAttributes(@HomeDrive &"\pagefile.sys")
MsgBox(0, 'PAGEFILE', "ret: "& $ret & " err: "& @error)
; windows xp sp3 - x86 / limited user account
;~ return = 4294967295
;~ error = 0
EndFunc

- money

Edit: too many edits!! and forgot to mention my os arch

Edit #2:

I have a question, why does this API fail (error code: 32) for in-use files such as pagefile,sys... while cmd and explorer (both running under same account) do not ?

Edited by money
Link to comment
Share on other sites

When "GetFileAttributesW" fails it is returning 4294967295 instead of 0xFFFFFFFF (-1); defeating the error check.

Those numbers are the same. Try this... consolewrite(ptr(4294967295) & @LF) :graduated:

But you are right about the error... it ought to be set. (You could just go into UDF an see if you can fix it yourself... While eaiting for official fix...)

Is it a problem with x64-system?

/Manko

Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually...
Link to comment
Share on other sites

Func _WinAPI_GetFileAttributes($sFile)
Local $Ret = DllCall('kernel32.dll', 'dword', 'GetFileAttributesW', 'wstr', $sFile)
If (@error) Or ($Ret[0] = 0xFFFFFFFF) Then
  Return SetError(1, 0, 0)
EndIf
Return $Ret[0]
EndFunc   ;==>_WinAPI_GetFileAttributes

Possible change:

If (@error) Or (ptr($Ret[0]) = 0xFFFFFFFF) Then

But that will likely not be right in a x64 system, as ptr will then be twice as long and return 0x00000000FFFFFFFF ... ?

I don't do x64 so I don't know...

[EDIT: But that actually works so it is alright! :) ]

/Manko

Edited by Manko
Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually...
Link to comment
Share on other sites

For those who come across this post here is my example for _WinAPI_GetDriveBusType() using an Array.

#include <APIConstants.au3>
#include <WinAPIEx.au3>

Opt('MustDeclareVars', 1)

Global $aDrive = DriveGetDrive('ALL')

For $i = 1 To $aDrive[0]
    ConsoleWrite(StringUpper($aDrive[$i]) & ' => ' & _GetDriveBusType($aDrive[$i]) & @CR)
Next

Func _GetDriveBusType($sDrive)
    Local $aArray[14][2] = [[$DRIVE_BUS_TYPE_UNKNOWN, 'UNKNOWN'], _
            [$DRIVE_BUS_TYPE_SCSI, 'SCSI'], _
            [$DRIVE_BUS_TYPE_ATAPI, 'ATAPI'], _
            [$DRIVE_BUS_TYPE_ATA, 'ATA'], _
            [$DRIVE_BUS_TYPE_1394, '1394'], _
            [$DRIVE_BUS_TYPE_SSA, 'SSA'], _
            [$DRIVE_BUS_TYPE_FIBRE, 'FIBRE'], _
            [$DRIVE_BUS_TYPE_USB, 'USB'], _
            [$DRIVE_BUS_TYPE_RAID, 'RAID'], _
            [$DRIVE_BUS_TYPE_ISCSI, 'ISCSI'], _
            [$DRIVE_BUS_TYPE_SAS, 'SAS'], _
            [$DRIVE_BUS_TYPE_SATA, 'SATA'], _
            [$DRIVE_BUS_TYPE_SD, 'SD'], _
            [$DRIVE_BUS_TYPE_MMC, 'MMC']], $iDriveType
    $iDriveType = _WinAPI_GetDriveBusType($sDrive)
    If @error Then
        Return $aArray[0][1]
    EndIf
    Return $aArray[$iDriveType][1]
EndFunc   ;==>_GetDriveBusType

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

Have you not thought about adding _WinAPI_PrivateExtractIcon()?

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...