Jump to content
Sign in to follow this  
targeter

DLLCall for battery info

Recommended Posts

targeter

I am trying to retrieve the Battery_Infomation structure. It turns out this is a structure within the Battery_Query_Information structure.

I know that I need to use the IOCTL_Battery_Query_Tag on the DeviceIoControl function but I am having trouble finishing the code. Mainly, I am not sure how to pass the array within the array back.... I don't need the larger Battery_Query_Information structure....

http://msdn.microsoft.com/en-us/library/aa372700(v=VS.85).aspx ---> IOCTL_Battery_Query_Tag

http://msdn.microsoft.com/en-us/library/aa372667(v=VS.85).aspx ---> Battery_Query_Information struct

http://msdn.microsoft.com/en-us/library/aa372661(v=VS.85).aspx ----> Battery_Infomation struct

Func _BatteryInfo()
    Local $BattInfo, $hbatt, $ret2, $array2[10], $bytesReturned, $overlap

    $hbatt = _WINAPI_CreateFile("\\.\batt",3,2)
    $BattInfo = DllStructCreate("ulong;uchar;uchar[3];uchar[4];ulong;ulong;ulong;ulong;ulong;ulong")
    If @error Then
        SetError(-1)
        Return $array2
    EndIf

    
; make the DllCall for battery information
    $ret2 = DllCall( _
"kernel32.dll", "int", _
"DeviceIoControl", _
"hwnd", $hbatt, _
"int", $IOCTL_BATTERY_QUERY_TAG, _
"ptr", DllStructGetPtr($BattInfo),  _
"dword", DllStructGetSize($BattInfo), _
"ptr", DllStructGetPtr($BattInfo),  _
"int", DllStructGetSize($BattInfo), _
"int", DllStructGetPtr($bytesReturned), _
"ptr", $overlap _
)
    If @error Then;DllCall Failed
        SetError(-2)
        $BattInfo = 0
        Return $array2
    EndIf

    If Not $ret2[0] Then; Query Failed
        SetError(-3)
        $BattInfo = 0
        Return $array2
    EndIf

; Fill the array
????
Edited by targeter

Share this post


Link to post
Share on other sites
jaberwacky

I'm new to DLLs, DLLStructs, and Windows functions but I think you may need to create the 'Overlapped' structure? I see that it has a union in it. I'm not sure if that can be made in autoit. Oh well, I wish I could help.

edit: From Wikipedia: "In computer science, a union is a value that may have any of several representations or formats; or a data structure that consists of a variable which may hold such a value." That sounds like a variant type to me.

Edited by jaberwocky6669

Share this post


Link to post
Share on other sites
Ascend4nt

Just messing with your code a bit, it seems that you have to do the following:

1. add: #include <WinAPI.au3>

2. Check if the file handle you receive from _WinAPI_CreateFile() is non-zero

3. Change all the 'uchar' values in the DLLStructCreate() function to 'char'

4. Define $IOCTL_BATTERY_QUERY_TAG. From looking at BatClass.h and WinIoCtl.h, it looks like this calculation *might* be right:

Global Const $IOCTL_BATTERY_QUERY_TAG=29*65536+0x11*16384+1

5. Close the handle you open using _WinAPI_CloseHandle() before returning (only if you were successful in getting a handle)

6. Change the last parameter in the DLLCall to 0, not $overlap - this is dependent on how you opened the file and I don't think you set the flags required to use this.

The CreateFile fails for me.. I don't know much about those oddball device paths, so you might have to look into whether you have it right or not.

Share this post


Link to post
Share on other sites
targeter

Just messing with your code a bit, it seems that you have to do the following:

1. add: #include <WinAPI.au3>

2. Check if the file handle you receive from _WinAPI_CreateFile() is non-zero

3. Change all the 'uchar' values in the DLLStructCreate() function to 'char'

4. Define $IOCTL_BATTERY_QUERY_TAG. From looking at BatClass.h and WinIoCtl.h, it looks like this calculation *might* be right:

Global Const $IOCTL_BATTERY_QUERY_TAG=29*65536+0x11*16384+1

5. Close the handle you open using _WinAPI_CloseHandle() before returning (only if you were successful in getting a handle)

6. Change the last parameter in the DLLCall to 0, not $overlap - this is dependent on how you opened the file and I don't think you set the flags required to use this.

The CreateFile fails for me.. I don't know much about those oddball device paths, so you might have to look into whether you have it right or not.

#include <WinAPI.au3>
Global Const $IOCTL_BATTERY_QUERY_TAG=29*65536+0x11*16384+1
Func _BatteryInfo()
    Local $BattInfo, $ret2, $array2[10], $bytesReturned, $overlap
Local $dFile = @ScriptDir & "\temp.au3"

Local $hbatt= _WinAPI_CreateFile($dFile, 2, 6, 6)

    $BattInfo = DllStructCreate("ulong;char;char[3];char[4];ulong;ulong;ulong;ulong;ulong;ca")
    If @error Then
        SetError(-1)
        Return $array2
    EndIf


; make the DllCall for battery information
    $ret2 = DllCall( _
"kernel32.dll", "int", _
"DeviceIoControl", _
"hwnd", $hbatt, _
"int", $IOCTL_BATTERY_QUERY_INFORMATION, _
"ptr", DllStructGetPtr($BattInfo),  _
"dword", DllStructGetSize($BattInfo), _
"ptr", DllStructGetPtr($BattInfo),  _
"int", DllStructGetSize($BattInfo), _
"int", DllStructGetPtr($bytesReturned), _
"ptr", 0 _
)
    If @error Then;DllCall Failed
        SetError(-2)
        $BattInfo = 0
        Return $array2
    EndIf


    If Not $ret2[0] Then; Query Failed
        SetError(-3)
        $BattInfo = 0
        Return $array2
    EndIf


    $Battinfo = 0
 Return $array2
; Fill the array




EndFunc

which device paths were you talking about... maybe I'm not quite understanding what you mean. Thanks on the constant, that skipped my mind. I had the include winapi.au3, must have cut off in the original c/p

However, it should actually be the IOCTL_BATTERY_QUERY_INFORMATION not the_TAG. Do you have the constant for that?

' From Batclass.h

Const IOCTL_BATTERY_QUERY_TAG = &H294040

Const IOCTL_BATTERY_QUERY_INFORMATION = &H294044

Const IOCTL_BATTERY_SET_INFORMATION = &H298048

Const IOCTL_BATTERY_QUERY_STATUS = &H29404C

This is what I managed to dig up.... It differs from yours though...

Edited by targeter

Share this post


Link to post
Share on other sites
jaberwacky

Ok, I got it to return a populated array! I don't know what it means but it is what it is. Dig?

I don't have my laptop at the moment or I'd test it on that.

#region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=n
#AutoIt3Wrapper_AU3Check_Stop_OnWarning=y
#AutoIt3Wrapper_AU3Check_Parameters=-w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -d
#AutoIt3Wrapper_Run_Tidy=y
#endregion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <WinAPI.au3>
#include <Array.au3>

Global Const $IOCTL_BATTERY_QUERY_TAG = 29 * 65536 + 0x11 * 16384 + 1

_BatteryInfo()

ConsoleWrite("@error: " & @error & @LF)

Func _BatteryInfo()

    Local $array2[10]

    Local Const $dFile = @ScriptDir & "\temp.au3"
    Local Const $hDevice = _WinAPI_CreateFile($dFile, 2, 6, 6)

    Local Const $controlCode = $IOCTL_BATTERY_QUERY_TAG

    Local Const $BattInfo = DllStructCreate("dword TimeOut")
    Local Const $timeOut = 10000
    DllStructSetData($BattInfo, "TimeOut", $timeOut)
    Local Const $inBuffer = DllStructGetPtr($BattInfo)
    Local Const $inBufferSize = DllStructGetSize($BattInfo)

    Local Const $oBuffStruct = DllStructCreate("dword oBuff")
    DllStructSetData($oBuffStruct, "oBuff", 256)
    Local Const $outBuffer = DllStructGetPtr($oBuffStruct)
    Local Const $outBufferSize = DllStructGetSize($BattInfo)

    Local Const $bytesReturned = DllStructCreate("dword bytesReturned")
    DllStructSetData($bytesReturned, "bytesReturned", 256)
    Local Const $pBytesReturned = DllStructGetPtr($bytesReturned)

    #cs BOOL WINAPI DeviceIoControl(
        __in    HANDLE hDevice,
        __in    DWORD dwIoControlCode,
        __in_opt    LPVOID lpInBuffer,
        __in    DWORD nInBufferSize,
        __out_opt LPVOID lpOutBuffer,
        __in    DWORD nOutBufferSize,
        __out_opt LPDWORD lpBytesReturned,
        __inout_opt LPOVERLAPPED lpOverlapped );
    #ce

    ; make the DllCall for battery information
    Local Const $ret2 = DllCall("kernel32.dll", "bool", "DeviceIoControl", _
            "hwnd", $hDevice, _
            "dword", $controlCode, _
            "ptr", $inBuffer, _
            "dword", $inBufferSize, _
            "ptr", $outBuffer, _
            "dword", $outBufferSize, _
            "ptr", $pBytesReturned, _
            "int", 0)

    ; DllCall Failed
    If @error Then SetError(-1, 0, 1)

    ; Query Failed
    If Not $ret2[0] Then SetError(-2, 0, 1)

    _ArrayDisplay($ret2)

    _WinAPI_CloseHandle($hDevice)

    Return $array2
    ; Fill the array
EndFunc ;==>_BatteryInfo
Edited by jaberwocky6669

Share this post


Link to post
Share on other sites
targeter

Wow that is awesome.. I actually came very close to resolving the code similar to what you did... The only thing I realized is that I need to pull the global constant for IOCTL_BATTERY_QUERY_INFORMATION. It turns out the _tag one is for like specific battery id info...

Where are you pulling the calc info for the global constant. I looked up batclass.h and didn't see what I needed in the header....

IOCTL_BATTERY_QUERY_INFORMATION

BOOL DeviceIoControl(

(HANDLE) hDevice, // handle to battery

IOCTL_BATTERY_QUERY_INFORMATION, // dwIoControlCode

(LPVOID) lpInBuffer, // input buffer

(DWORD) nInBufferSize, // size of input buffer

(LPVOID) lpOutBuffer, // output buffer

(DWORD) nOutBufferSize, // size of output buffer

(LPDWORD) lpBytesReturned, // number of bytes returned

(LPOVERLAPPED) lpOverlapped // OVERLAPPED structure

when you declare the size of the lpOutBuffer then it knows to pull a specific data structure!!! Go figure. this seems to be the only place where the API behaves like this.

IpOutBuffer

A pointer to the return buffer. The data type (and, therefore, size) of the return buffer depends on the information requested in the BATTERY_QUERY_INFORMATION_LEVEL member of the input BATTERY_QUERY_INFORMATION structure.

The following table shows the data returned by a given information level. http://msdn.microsoft.com/en-us/library/aa372667(v=VS.85).aspx

Edited by targeter

Share this post


Link to post
Share on other sites
jaberwacky

Well, Ascend4nt provided that information actually. However, I'm beginning to think that it isn't a defined constant so much as something that's generated based on specific information found on your computer. OR, it may be generated by the DeviceIoControl function and then passed to $IOCTL_BATTERY_QUERY_TAG. At this point the script isn't complete. I'm sure of that. $IOCTRL_BATTERY_QUERY_TAG is a mystery to my simple brain. Anyways, I'll keep looking into this but I bid you good luck and welcome to the forum. I'm always open to questions, conversation, whatever.

Edited by jaberwocky6669

Share this post


Link to post
Share on other sites
targeter

Found this...

http://us.generation-nt.com/answer/deviceiocontrol-parameters-help-8865722.html

dddd dddd dddd dddd aaff ffff ffff ffmm

Legend:

d: DeviceType

a: Access

f: Function

m: Method

You can construct the constant in this simpler way:

CTL_CODE = DeviceType * 65536 + Function * 4 + Method + Access * 16384

So I need to track down 2 numbers it seems

http://www.java2s.com/Open-Source/Python/Windows/pyExcelerator/pywin32-214/win32/lib/winioctlcon.py.htm

DeviceType = 41?

http://www.java2s.com/Open-Source/Python/Windows/pyExcelerator/pywin32-214/win32/lib/winioctlcon.py.htm

0x00000029 to 41 decimal?

Function = 0x11 ?

http://www.koders.com/c/fidA0B3DDA5A706B2E90AE44188C57175D17F1CC371.aspx

Edited by targeter

Share this post


Link to post
Share on other sites
Yashied
targeter

I am going to try and build off your code

Global Const $IOCTL_BATTERY_QUERY_INFORMATION = 41 * 65536 + 0x11 * 16384 + 1

However I am still having trouble. It looks like where lpOutBuffer you use "local $outbuffer"

This is different than how I had done with $BattInfo = DllStructCreate("ulong;char;char[3];char[4];ulong;ulong;ulong;ulong;ulong;ulong")

It looks like the problem is still different then my initial assumption. if you request DllStructGetPtr($BattInfo) it should be limited to the structure generated by Battery_Information? Or do I get back a structure within a structure BATTERY_QUERY_INFORMATION?

http://msdn.microsoft.com/en-us/library/aa372667(v=VS.85).aspx

Edited by targeter

Share this post


Link to post
Share on other sites
targeter

What information about the battery you want to get?

http://msdn.microsoft.com/en-us/library/aa372661(v=VS.85).aspx

BATTERY_INFORMATION Structure

typedef struct _BATTERY_INFORMATION {

ULONG Capabilities;

UCHAR Technology;

UCHAR Reserved[3];

UCHAR Chemistry[4];

ULONG DesignedCapacity;

ULONG FullChargedCapacity;

ULONG DefaultAlert1;

ULONG DefaultAlert2;

ULONG CriticalBias;

ULONG CycleCount;

} BATTERY_INFORMATION, *PBATTERY_INFORMATION;

I want to get chemistry, designed capacity info, but knowing how this thing is suppose to be called in general would be a lot of help

I coded a WMI32_battery version and it returns values but mostly empty. It turns out that WMI isn't the best way to go for battery information. Other programs have been made but they rely on the WIN API. I am just trying to attempt that they did in a script (compared to their C++)

Edited by targeter

Share this post


Link to post
Share on other sites
targeter

Oh, that's pretty much exactly what Ascend4nt gave us a few posts back! *facepalm*

I looked up the function for _tag it looks like it was suppose to be 0x10.... Correct me if I am wrong Ascend4nt? I haven't touched C++ in so long that this is almost like relearning everything again.

Share this post


Link to post
Share on other sites
jaberwacky

Maybe, the BATTERY_QUERY_INFORMATION struct would be defined like this?

#cs typedef struct _BATTERY_QUERY_INFORMATION {
    ULONG   BatteryTag;
    BATTERY_QUERY_INFORMATION_LEVEL InformationLevel;
    LONG    AtRate;
    } BATTERY_QUERY_INFORMATION, *PBATTERY_QUERY_INFORMATION;
#ce

Local Const $Battery_Query_Information = DllStructCreate("ulong BatteryTag;battery_query_information_level InformationLevel;long AtRate")
Local Const $PBattery_Query_Information = DllStructGetPtr($Battery_Query_Information)

What is Battery_Query_Information_Level? Another struct, a constant?

Yashied seems to understand this Windows stuff...

Share this post


Link to post
Share on other sites
targeter

Maybe, the BATTERY_QUERY_INFORMATION struct would be defined like this?

#cs typedef struct _BATTERY_QUERY_INFORMATION {
    ULONG   BatteryTag;
    BATTERY_QUERY_INFORMATION_LEVEL InformationLevel;
    LONG    AtRate;
    } BATTERY_QUERY_INFORMATION, *PBATTERY_QUERY_INFORMATION;
#ce

Local Const $Battery_Query_Information = DllStructCreate("ulong BatteryTag;battery_query_information_level InformationLevel;long AtRate")
Local Const $PBattery_Query_Information = DllStructGetPtr($Battery_Query_Information)

What is Battery_Query_Information_Level? Another struct, a constant?

Yashied seems to understand this Windows stuff...

I welcome anyhelp on this one....

http://msdn.microsoft.com/en-us/library/aa372661(v=VS.85).aspx

http://msdn.microsoft.com/en-us/library/aa372667(v=VS.85).aspx

I mean it looks like it is a structure within a structure. It seems like the BATTERY_QUERY_INFORMATION_LEVEL from the BATTERY_QUERY_INFORMATION Structure further determines a sub-structure?

Share this post


Link to post
Share on other sites
targeter

huh... welll I guess that makes some sense

BatteryDeviceName

4

Null-terminated Unicode string that contains the battery's name.

BatteryEstimatedTime

3

A ULONG that specifies the estimated battery run time, in seconds. If the rate of drain provided in the AtRate member of the BATTERY_QUERY_INFORMATION structure is zero, this calculation is based on the present rate of drain. If AtRate is nonzero, the time returned is the expected run time for the given rate. If the estimated time is unknown (for example, the battery is not discharging and the AtRate specified was zero), the return value is BATTERY_UNKNOWN_TIME. Note that this value is not very accurate on some battery systems, and may vary widely depending on present power usage, which could be affected by disk activity and other factors. There is no notification mechanism for changes in this value.

BatteryGranularityInformation

1

An array of BATTERY_REPORTING_SCALE structures, never more than four entries.

BatteryInformation

0

A BATTERY_INFORMATION structure.

BatteryManufactureDate

5

A BATTERY_MANUFACTURE_DATE structure.

BatteryManufactureName

6

Null-terminated Unicode string that specifies the name of the manufacturer of the battery.

BatterySerialNumber

8

Null-terminated Unicode string that specifies the battery's serial number.

BatteryTemperature

2

A ULONG that specifies the battery's current temperature, in 10ths of a degree Kelvin.

BatteryUniqueID

7

-----> http://msdn.microsoft.com/en-us/library/aa372667(v=VS.85).aspx according to infopage

Does this mean I just toss a 0 value into the outbuffer? I guess I am wondering how it returns the data structure then....

Edited by targeter

Share this post


Link to post
Share on other sites
jaberwacky

; =================================================================================================================================
#cs typedef enum _BATTERY_QUERY_INFORMATION_LEVEL {
    BatteryInformation = 0,
    BatteryGranularityInformation,
    BatteryTemperature,
    BatteryEstimatedTime,
    BatteryDeviceName,
    BatteryManufactureDate,
    BatteryManufactureName,
    BatteryUniqueID,
    BatterySerialNumber
#ce } BATTERY_QUERY_INFORMATION_LEVEL;

Global Enum _
        $BatteryInformation = 0, _
        $BatteryGranularityInformation, _
        $BatteryTemperature, _
        $BatteryEstimatedTime, _
        $BatteryDeviceName, _
        $BatteryManufactureDate, _
        $BatteryManufactureName, _
        $BatteryUniqueID, _
        $BatterySerialNumber
; =================================================================================================================================



; =================================================================================================================================
#cs typedef struct _BATTERY_QUERY_INFORMATION {
    ULONG BatteryTag;
    BATTERY_QUERY_INFORMATION_LEVEL InformationLevel;
    LONG    AtRate;
    } BATTERY_QUERY_INFORMATION, *PBATTERY_QUERY_INFORMATION;
#ce

Global Const $Battery_Query_Information = DllStructCreate("ulong BatteryTag;int InformationLevel;long AtRate")
Global Const $PBattery_Query_Information = DllStructGetPtr($Battery_Query_Information)
; =================================================================================================================================

No nevermind, those aren't enumerated. They are pointers to structs!

Edited by jaberwocky6669

Share this post


Link to post
Share on other sites
Yashied

Global Const $IOCTL_BATTERY_QUERY_INFORMATION  = 0x00294044
Global Const $IOCTL_BATTERY_QUERY_STATUS = 0x0029404C
Global Const $IOCTL_BATTERY_QUERY_TAG = 0x00294040

Global Const $BatteryInformation = 0
Global Const $BatteryGranularityInformation = 1
Global Const $BatteryTemperature = 2
Global Const $BatteryEstimatedTime = 3
Global Const $BatteryDeviceName = 4
Global Const $BatteryManufactureDate = 5
Global Const $BatteryManufactureName = 6
Global Const $BatteryUniqueID = 7
Global Const $BatterySerialNumber = 8

Global Const $BATTERY_CAPACITY_RELATIVE = 0x40000000
Global Const $BATTERY_IS_SHORT_TERM = 0x20000000
Global Const $BATTERY_SET_CHARGE_SUPPORTED = 0x00000001
Global Const $BATTERY_SET_DISCHARGE_SUPPORTED = 0x00000002
Global Const $BATTERY_SYSTEM_BATTERY = 0x80000000

;Global Const $BATTERY_UNKNOWN_... = 0xFFFFFFFF

Global Const $BATTERY_CHARGING = 0x00000004
Global Const $BATTERY_CRITICAL = 0x00000008
Global Const $BATTERY_DISCHARGING = 0x00000002
Global Const $BATTERY_POWER_ON_LINE = 0x00000001

Global Const $tagBATTERY_INFORMATION = 'ulong Capabilities;byte Technology;byte Reserved[3];char Chemistry[4];ulong DesignedCapacity;ulong FullChargedCapacity;ulong DefaultAlert1;ulong DefaultAlert2;ulong CriticalBias;ulong CycleCount'
Global Const $tagBATTERY_MANUFACTURE_DATE = 'byte Day;byte Month;ushort Year'
Global Const $tagBATTERY_QUERY_INFORMATION = 'ulong BatteryTag;ulong InformationLevel;long AtRate'
Global Const $tagBATTERY_REPORTING_SCALE = 'ulong Granularity;ulong Capacity'
Global Const $tagBATTERY_STATUS = 'ulong PowerState;ulong Capacity;ulong Voltage;long Rate'
Global Const $tagBATTERY_WAIT_STATUS = 'ulong BatteryTag;ulong Timeout;ulong PowerState;ulong LowCapacity;ulong HighCapacity'

Edited by Yashied

Share this post


Link to post
Share on other sites
targeter

; =================================================================================================================================
#cs typedef enum _BATTERY_QUERY_INFORMATION_LEVEL {
    BatteryInformation = 0,
    BatteryGranularityInformation,
    BatteryTemperature,
    BatteryEstimatedTime,
    BatteryDeviceName,
    BatteryManufactureDate,
    BatteryManufactureName,
    BatteryUniqueID,
    BatterySerialNumber
#ce } BATTERY_QUERY_INFORMATION_LEVEL;

Global Enum _
        $BatteryInformation = 0, _
        $BatteryGranularityInformation, _
        $BatteryTemperature, _
        $BatteryEstimatedTime, _
        $BatteryDeviceName, _
        $BatteryManufactureDate, _
        $BatteryManufactureName, _
        $BatteryUniqueID, _
        $BatterySerialNumber
; =================================================================================================================================



; =================================================================================================================================
#cs typedef struct _BATTERY_QUERY_INFORMATION {
    ULONG BatteryTag;
    BATTERY_QUERY_INFORMATION_LEVEL InformationLevel;
    LONG    AtRate;
    } BATTERY_QUERY_INFORMATION, *PBATTERY_QUERY_INFORMATION;
#ce

Global Const $Battery_Query_Information = DllStructCreate("ulong BatteryTag;int InformationLevel;long AtRate")
Global Const $PBattery_Query_Information = DllStructGetPtr($Battery_Query_Information)
; =================================================================================================================================

I hope I am interpreting this right... so its going to be a Ipoutbuffer of 0 right? and the Battery_Query Information datastructure returns

ulong Battery tag

ULONG Capabilities;

UCHAR Technology;

UCHAR Reserved[3];

UCHAR Chemistry[4];

ULONG DesignedCapacity;

ULONG FullChargedCapacity;

ULONG DefaultAlert1;

ULONG DefaultAlert2;

ULONG CriticalBias;

ULONG CycleCount;

ulong rate

??

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  

×