Sign in to follow this  
Followers 0
Confuzzled

Getting results from Win API DLL calls

5 posts in this topic

#1 ·  Posted (edited)

I'm a noob with AutoIt, so be patient! I'm getting great results and it fits the bill for a lot of things - very versatile.

I'm extracting a few system details in a script, and need to get the GDI, System, and User Resources values for 98 and ME systems, and the GetCompressedFileSize for sparse or compressed files and folders under NTFS.

The respective VB, etc codes I have found are:

Private Declare Function GetFreeResources Lib "RSRC32" _
Alias "_MyGetFreeSystemResources32@4" (ByVal lWhat As Long) As _
Long

Const GFSR_SYSTEMRESOURCES = 0
Const GFSR_GDIRESOURCES = 1
Const GFSR_USERRESOURCES = 2

'get free system resource use :
GetFreeResources(GFSR_SYSTEMRESOURCES) 
' get free GDI resources use:
GetFreeResources(GFSR_GDIRESOURCES) 
' get free user resources use:
GetFreeResources(GFSR_USERRESOURCES) 
' the values returned are in percentage

(I know this relies on the RSRC32.DLL file that exists on 98 and ME systems.)

and the other, which has me more confused:

Declare Function GetCompressedFileSize Lib "kernel32.dll" _
                 Alias "GetCompressedFileSizeA" ( _
                 ByVal lpFileName As String, _
                 lpFileSizeHigh As Long) As Long


Declare Function GetCompressedFileSize Lib "KERNEL32" Alias "GetCompressedFileSizeA" (ByVal lpFileName As String, lpFileSizeHigh As Long) As Long

[DllImport("kernel32.dll")]
static extern uint GetCompressedFileSize(string lpFileName,
   IntPtr lpFileSizeHigh);

GetCompressedFileSize
The GetCompressedFileSize function obtains the actual number of bytes of disk storage used to store a specified file. If the file is located on a volume that supports compression, and the file is compressed, the value obtained is the compressed size of the specified file. If the file is not located on a volume that supports compression, or if the file is not compressed, the value obtained is the actual file size, the same as the value returned by a call to GetFileSize. 

VB4-32,5,6

Declare Function GetCompressedFileSize Lib "kernel32" Alias "GetCompressedFileSizeA" ( _
ByVal lpFileName As String, _
lpFileSizeHigh As Long _
) As Long
Operating Systems Supported
Requires Windows NT 3.1 or later; Requires Windows 98 or later 

Library
kernel32 

Parameter Information
¡ lpFileName

Pointer to a null-terminated string that specifies the name of the file.
¡ lpFileSizeHigh

Pointer to a DWORD variable that the function sets to the high-order doubleword of the compressed file size. The functionÂs return value is the low-order doubleword of the compressed file size.

This parameter can be NULL if the high-order doubleword of the compressed file size is not needed. Files less than 4 gigabytes in size do not need the high-order doubleword. 

Return Values
If the function succeeds, the return value is the low-order doubleword of the actual number of bytes of disk storage used to store the specified file, and if lpFileSizeHigh is non-NULL, the function puts the high-order doubleword of that actual value into the DWORD pointed to by that parameter. This is the compressed file size for compressed files, the actual file size for noncompressed files.
If the function fails, and lpFileSizeHigh is NULL, the return value is 0xFFFFFFFF. To get extended error information, call GetLastError.
If the function fails, and lpFileSizeHigh is non-NULL, the return value is 0xFFFFFFFF, and GetLastError returns a value other than NO_ERROR.

I've read the DLLCall description help, and that doesn't go into enough detail for me to confidently experiment without crashing something.

Can somebody translate these code snippets into something I can use in AutoIt?

Can somebody point me to somewhere on the net that explains how to call Windows APIs, and what all the C++, C#, etc parameter definitions mean in plain language that a noob can absorb and turn into something useful (and not bother you with what must be something obvious once the penny drops)? The Microsoft MSDN is probably the best source, but of course I don't know how to decipher the language used as my C++ skills are non-existant, so I'm looking elsewhere.

Thanks.

Edited by Confuzzled

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

$a = DLLCall("kernel32.dll","int","GetCompressedFileSize","str","c:\filehere.fil","int",0)

the result you are looking for will be in $a[2]. but you may need function that pulls out high-order and low-order information... i dunno really.

Lar.

<{POST_SNAPBACK}>

Thanks for the reply Larry.

I tried your example as follows:

dim $a[2]

dim $b

$b= "C:\CONFIG.SYS" & Chr(0)

$a = DLLCall("kernel32.dll","int","GetCompressedFileSize","str",$b,"int",0)

MsgBox (0,"GetcompressedFileSize","File: " & $b & ", Size obtained is: " & hex($a[2],4) & ". Error code returned was: " & @error)

It returned zeros for both size and error code.

What am I doing wrong? :)

Edited by Confuzzled

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Thanks for the reply Larry.

I tried your example as follows:

dim $a[2]

dim $b

$b= "C:\CONFIG.SYS" & Chr(0)

$a = DLLCall("kernel32.dll","int","GetCompressedFileSize","str",$b,"int",0)

MsgBox (0,"GetcompressedFileSize","File: " & $b & ", Size obtained is: " & hex($a[2],4) & ". Error code returned was: " & @error)

It returned zeros for both size and error code.

What am I doing wrong?  :evil:

<{POST_SNAPBACK}>

I experimented a little (the last parameter needs to be a pointer I think) and finally got the working code as follows:

#cs
MSDN: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/getcompressedfilesize.asp

GetCompressedFileSize
=====================

DWORD GetCompressedFileSize(
  LPCTSTR lpFileName,
  LPDWORD lpFileSizeHigh
);

Parameters
lpFileName 
[in] Pointer to a null-terminated string that specifies the name of the file. 

lpFileSizeHigh 
[out] Pointer to a variable that receives the high-order DWORD of the compressed file size.
The function's return value is the low-order DWORD of the compressed file size. 
This parameter can be NULL if the high-order DWORD of the compressed file size is not needed.
Files less than 4 gigabytes in size do not need the high-order DWORD.

Return Values
If the function succeeds, the return value is the low-order DWORD of the actual number of bytes
of disk storage used to store the specified file, and if lpFileSizeHigh is non-NULL,
the function puts the high-order DWORD of that actual value into the DWORD pointed to by that parameter.
This is the compressed file size for compressed files, the actual file size for noncompressed files.

If the function fails, and lpFileSizeHigh is NULL, the return value is INVALID_FILE_SIZE.
To get extended error information, call GetLastError.

If the return value is INVALID_FILE_SIZE and lpFileSizeHigh is non-NULL, an application must call
GetLastError to determine whether the function has succeeded (value is NO_ERROR) or failed (value is other than NO_ERROR).
#ce

; _GetCompressedFileSize;Gets actual space used by file on disk (can be less than actual size due to compression & sparseness)
; AutoIT3 implementation

dim $ret[2]    ;Variable for lower order DWORD of file size and DLLcall function [Note: subscript for three values 0-3]
dim $lpFileName    ;Pointer to null-terminated string that specifies the file name
dim $lpFileSizeHigh;Pointer to high order DWORD of file size
dim $highorder;Stores high order file size
dim $loworder;Stores low order file size
$lpFileName    = "Full file name"

$ret = DLLCall("Kernel32.dll","int","GetCompressedFileSize","str",$lpFileName ,"int_ptr",$lpFileSizeHigh)

$highorder=$ret[2]
$loworder=$ret[0]

if $highorder = "" and $loworder = -1 Then
    MsgBox(0,"DllCall Error","DllCall Failed")
    exit
EndIf

MsgBox (0,"GetCompressedFileSize demo","File name is " & $lpFileName    & @CRLF  & @CRLF & _
"Ret[0] is : " & hex($ret[0],8) & @CRLF & _
"Ret[1] is : " & hex($ret[1],8) & @CRLF & _
"Ret[2] is : " & hex($ret[2],8) & @CRLF & @CRLF & _
"Lower order DWORD of file size is: HEX " & hex($loworder,8) & " decimal " & $loworder& @CRLF & _
"High order DWORD of file size is: HEX " & hex($highorder,8) & " decimal " & $highorder & @CRLF & @CRLF & _
"Error is: " & hex(@error,2) & @CRLF & @CRLF & _
"Filesizehigh is: " & hex($lpFileSizeHigh,8) & @CRLF & @CRLF & _
"Value of filesize in HEX is: " & hex($highorder,8) & hex($loworder,8) & @CRLF & @CRLF & _
"Use Windows Calculator scientific HEX function to verify the results are accurate!" )

;Note: This only works for file sizes less than 0x80000000 or 2Gb, else the sign bit in the 32 bit signed integer 
;      kicks in and you have to do some awkward manipulations

Unfortunately the variable sizes have taken their toll. :D I'm not doing bitwise manipulation on each file size while enumerating a whole folder or tree to get a final result. Can anybody help with converting signed integers into numeric variables that can be added (I suppose I could divide everything by 1024 and do it in Kb - is that a bit shift left for 10?)

64bit variables anybody? :)

Edited by Confuzzled

Share this post


Link to post
Share on other sites

I'm extracting a few system details in a script, and need to get the GDI, System, and User Resources values for 98 and ME systems, and the GetCompressedFileSize for sparse or compressed files and folders under NTFS.

The respective VB, etc codes I have found are:

Private Declare Function GetFreeResources Lib "RSRC32" _
Alias "_MyGetFreeSystemResources32@4" (ByVal lWhat As Long) As _
Long

Const GFSR_SYSTEMRESOURCES = 0
Const GFSR_GDIRESOURCES = 1
Const GFSR_USERRESOURCES = 2

'get free system resource use :
GetFreeResources(GFSR_SYSTEMRESOURCES) 
' get free GDI resources use:
GetFreeResources(GFSR_GDIRESOURCES) 
' get free user resources use:
GetFreeResources(GFSR_USERRESOURCES) 
' the values returned are in percentage

(I know this relies on the RSRC32.DLL file that exists on 98 and ME systems.)

Thanks.

<{POST_SNAPBACK}>

I finally got it down to this workable code:

If @OSType = "WIN32_WINDOWS" Then
    Dim $Resinfo[2]
    $Resinfo = DLLCall("RSRC32.DLL","long","_MyGetFreeSystemResources32@4","long",0)
    $Free_System_Resources = $Resinfo[0]
    $Resinfo = DLLCall("RSRC32.DLL","long","_MyGetFreeSystemResources32@4","long",1)
    $Free_GDI_Resources = $Resinfo[0]
    $Resinfo = DLLCall("RSRC32.DLL","long","_MyGetFreeSystemResources32@4","long",2)
    $Free_User_Resources = $Resinfo[0]
    MsgBox(0, "System Resource Information" , "OS Type is: " & @TAB & @TAB & @OSType & "," & @CRLF & _
    "Free System Resources: " & @TAB & $Free_System_Resources & "%," & @CRLF & _
    "Free GDI Resources: " & @TAB & $Free_GDI_Resources & "%," & @CRLF & _
    "Free User Resources: " & @TAB & $Free_User_Resources & "%")
EndIf
It works! :)

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  
Followers 0