Hey,
In Windows "Device Manager" looking at the device properties,
some devices have a "Power management" tab. Under this tab a checkbox named
"Allow the computer to turn off this device to save power" can be found.
I'd like to change this option programmatically.
Seems that WMI should be able to do it.
Using José utility "WMi wrappers generator" TB_WMIGN I did produce some PBCC 4.04 code
that can read the "\root\WMI\MSPower_DeviceEnable" vEnable device status.
I tried to flip some device state with no success, any idea?
Thanks
Pierre
#COMPILE EXE '#CC 4.04#
#DIM ALL
#INCLUDE "Win32Api.inc"
UNION VARIANTDATA 'Thank to José Roca
bVal AS BYTE 'VT_UI1
iVal AS INTEGER 'VT_I2
lVal AS LONG 'VT_I4
fltVal AS SINGLE 'VT_R4
dblVal AS DOUBLE 'VT_R8
boolVal AS INTEGER 'VT_BOOL
scode AS LONG 'VT_ERROR
cyVal AS LONG 'VT_CY
date AS DOUBLE 'VT_DATE
bstrVal AS LONG 'VT_BSTR
punkVal AS DWORD 'VT_UNKNOWN
pdispVal AS DWORD 'VT_DISPATCH
parray AS DWORD 'VT_ARRAY|*
pbVal AS BYTE POINTER 'VT_BYREF|VT_UI1
piVal AS INTEGER POINTER 'VT_BYREF|VT_I2
plVal AS LONG POINTER 'VT_BYREF|VT_I4
pfltVal AS SINGLE POINTER 'VT_BYREF|VT_R4
pdblVal AS DOUBLE POINTER 'VT_BYREF|VT_R8
pboolVal AS INTEGER POINTER 'VT_BYREF|VT_BOOL
pscode AS LONG POINTER 'VT_BYREF|VT_ERROR
pcyVal AS LONG POINTER 'VT_BYREF|VT_CY
pdate AS DOUBLE POINTER 'VT_BYREF|VT_DATE
pbstrVal AS LONG POINTER 'VT_BYREF|VT_BSTR
ppunkVal AS DWORD POINTER 'VT_BYREF|VT_UNKNOWN
ppdispVal AS DWORD POINTER 'VT_BYREF|VT_DISPATCH
psArray AS DWORD POINTER 'VT_ARRAY|*
pVariant AS DWORD POINTER 'VT_BYREF|VT_VARIANT
pByRef AS DWORD 'Generic ByRef
END UNION
'For backwards compatibility, size = 16 bytes
TYPE VARIANTAPIjr DWORD FILL
vt AS WORD 'VARTYPE
wReserved1 AS WORD
wReserved2 AS WORD
wReserved3 AS WORD
vd AS VARIANTDATA 'VARIANTDATA_UNION
END TYPE
DECLARE FUNCTION CreateBindCtx LIB "OLE32.DLL" ALIAS "CreateBindCtx" _
(BYVAL reserved AS DWORD, BYREF ppbc AS ANY) AS LONG
DECLARE FUNCTION MkParseDisplayNameEx LIB "URLMON.DLL" ALIAS "MkParseDisplayNameEx" _
(BYVAL pbc AS DWORD, BYVAL szUserName AS STRING, _
BYREF pcchEaten AS DWORD, BYREF ppmk AS DWORD) AS LONG
'_____________________________________________________________________________
FUNCTION WmiRelease(BYVAL pthis AS DWORD POINTER) AS DWORD
LOCAL DWRESULT AS DWORD
IF pthis THEN
CALL DWORD @@pthis[2] USING WmiRelease(pthis) TO DWRESULT
FUNCTION = DWRESULT
END IF
END FUNCTION
'_____________________________________________________________________________
FUNCTION WmiEnum_Next(BYVAL pthis AS DWORD POINTER, BYVAL celt AS DWORD, _
BYVAL rgelt AS DWORD, BYREF pceltFetched AS DWORD) AS LONG
LOCAL HRESULT AS LONG
IF pthis THEN
CALL DWORD @@pthis[3] USING WmiEnum_Next(pthis, celt, rgelt, pceltFetched) TO HRESULT
FUNCTION = HRESULT
END IF
END FUNCTION
'_____________________________________________________________________________
FUNCTION WmiEnum_NextItem(BYVAL pthis AS DWORD POINTER, BYREF elt AS VARIANT) AS LONG
LOCAL HRESULT AS LONG
IF pthis THEN
CALL DWORD @@pthis[3] USING WmiEnum_Next(pthis, 1, VARPTR(elt), BYVAL %NULL) TO HRESULT
FUNCTION = HRESULT
END IF
END FUNCTION
'_____________________________________________________________________________
FUNCTION WmiMoniker_BindToObject(BYVAL pthis AS DWORD POINTER, BYVAL pbc AS DWORD, _
BYVAL pmkToLeft AS DWORD, BYREF riidResult AS GUID, BYREF ppvResult AS DWORD) AS LONG
LOCAL HRESULT AS LONG
IF pthis THEN
CALL DWORD @@pthis[8] USING WmiMoniker_BindToObject(pthis, pbc, pmkToLeft, _
riidResult, ppvResult) TO HRESULT
FUNCTION = HRESULT
END IF
END FUNCTION
'_____________________________________________________________________________
FUNCTION WmiGetObject(BYVAL strDisplayName AS STRING, BYREF vObj AS VARIANT) AS LONG
LOCAL hr AS LONG 'HRESULT
LOCAL pbc AS DWORD 'Pointer to the new bind context
LOCAL pmk AS DWORD 'IMoniker interface pointer
LOCAL pObj AS DWORD 'Interface pointer
LOCAL pcchEaten AS DWORD 'Number of characters successfully parsed
LOCAL IID_IDispatch AS GUID 'IDispatch inyterface identifier
LOCAL pvObj AS VARIANTAPIjr POINTER 'Pointer to a VARIANTAPI structure
IID_IDispatch = GUID$("{00020400-0000-0000-c000-000000000046}")
hr = CreateBindCtx(0, pbc) 'Creates a new bind context.
IF hr = %S_OK AND pbc <> 0 THEN
'Converts a string into a moniker that identifies the object named by the string.
strDisplayName = UCODE$(strDisplayName & $NUL)
hr = MkParseDisplayNameEx(pbc, strDisplayName, pcchEaten, pmk)
IF hr = %S_OK AND pmk <> 0 THEN
'Uses the moniker to bind to the object it identifies.
'The binding process involves finding the object, putting it into the running
'state if necessary, and supplying the caller with a pointer to a specified
'interface on the identified object.
hr = WmiMoniker_BindToObject(pmk, pbc, %NULL, IID_IDispatch, pObj)
IF hr = %S_OK THEN
'Makes a dispatch variant containing the reference to the object.
'Note: No need to call AddRef because IMoniker_BindToObject has
'already called it. Just don't release pObj here.
vObj = EMPTY 'Make sure is empty to avoid memory leaks
pvObj = VARPTR(vObj) 'Get the VARIANT address
@pvObj.vt = %VT_DISPATCH 'Mark it as containing a dispatch variable
@pvObj.vd.pdispVal = pObj 'Set the dispatch pointer address
END IF
WmiRelease(pmk)
END IF
WmiRelease(pbc)
END IF
FUNCTION = hr
END FUNCTION
'_____________________________________________________________________________
FUNCTION Wmi_NewEnum(BYVAL pthis AS DWORD POINTER, BYREF ppenum AS DWORD) AS LONG
LOCAL HRESULT AS LONG
IF pthis THEN
CALL DWORD @@pthis[7] USING Wmi_NewEnum(pthis, ppenum) TO HRESULT
FUNCTION = HRESULT
END IF
END FUNCTION
'_____________________________________________________________________________
SUB MKVTBOOL(BYREF vVar AS VARIANT, BYVAL fBool AS INTEGER)
LOCAL pv AS VARIANTAPIjr POINTER 'Pointer to a VARIANTAPI structure
vVar = EMPTY 'Make sure is empty to avoid memory leaks
pv = VARPTR(vVar) 'Get the VARIANT address
@pv.vt = %VT_BOOL 'Mark it as containing a boolean value
IF fBool THEN fBool = -1 'Make sure is 0 or -1
@pv.vd.boolVal = fBool 'Set the boolean value
END SUB
'_____________________________________________________________________________
SUB WMI_MSPower_DeviceEnable(OPTIONAL BYVAL strComputer AS STRING)
LOCAL hr AS LONG 'HRESULT
LOCAL oServices AS DISPATCH 'Services object
LOCAL vServices AS VARIANT 'Services object reference
LOCAL oItems AS DISPATCH 'Generic collection object
LOCAL vItems AS VARIANT 'Generic collection object reference
LOCAL oItem AS DISPATCH 'Generic item object
LOCAL vItem AS VARIANT 'Generic item object reference
LOCAL penum AS DWORD 'Generic collection's enumerator reference
LOCAL vCount AS VARIANT 'Number of items in the collection
LOCAL vQuery AS VARIANT 'Query string
LOCAL vRes AS VARIANT 'General purpose variant
LOCAL i AS LONG 'Loop counter
LOCAL zBuffer AS ASCIIZ * 512
'Variants to store the property values
LOCAL vActive AS VARIANT 'Boolean value
LOCAL vEnable AS VARIANT 'Boolean value
LOCAL vInstanceName AS VARIANT 'String
'Connect to WMI using a moniker
IF LEN(strComputer) = 0 THEN strComputer = "."
hr = WmiGetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\WMI", vServices)
IF hr <> %S_OK THEN GOTO Terminate
SET oServices = vServices
vServices = EMPTY
IF ISFALSE ISOBJECT(oServices) THEN GOTO Terminate
'Execute a query to get a reference to the collection of objects
vQuery = "SELECT * FROM MSPower_DeviceEnable"
OBJECT CALL oServices.ExecQuery(vQuery) TO vItems
IF ISTRUE OBJRESULT THEN GOTO Terminate
SET oItems = vItems
vItems = EMPTY
IF ISFALSE ISOBJECT(oItems) THEN GOTO Terminate
'Retrieve the number of items in the collection
OBJECT GET oItems.Count TO vCount
'Retrieve a reference to the collection's enumerator
hr = Wmi_NewEnum(OBJPTR(oItems), penum)
IF hr <> %S_OK OR penum = %NULL THEN GOTO Terminate
'Iterate through the collection of objects.
FOR i = 1 TO VARIANT#(vCount)
'Retrieve a reference to the next object in the collection
hr = WmiEnum_NextItem(penum, vItem)
IF hr <> %S_OK THEN EXIT FOR
SET oItem = vItem
vItem = EMPTY
IF ISFALSE ISOBJECT(oItem) THEN EXIT FOR
'Retrieve the values of the properties
OBJECT GET oItem.InstanceName TO vInstanceName
zBuffer = VARIANT$(vInstanceName)
CharToOem(zBuffer, zBuffer)
PRINT "vInsName " & zBuffer
OBJECT GET oItem.Enable TO vEnable
PRINT "vEnable " & STR$(VARIANT#(vEnable) AND 1) 'It's read/write
OBJECT GET oItem.Active TO vActive
PRINT "vActive " & STR$(VARIANT#(vActive) AND 1) 'It's read-only
IF zBuffer = "USB\VID_08E6&PID_3437\D2880DA3_0" THEN 'Replace with a valid device for your PC
PRINT "Replace with a valid device for your PC"
PRINT "Device found"
IF(VARIANT#(vEnable) AND 1) = 0 THEN '0x180000
COLOR 11
PRINT "Allow the computer to turn off this device to save power: Yes"
PRINT "Flipping it to No"
MKVTBOOL(vEnable, %TRUE)
ELSE '0x18FFFF
COLOR 12
PRINT "Allow the computer to turn off this device to save power: No"
PRINT "Flipping it to Yes"
MKVTBOOL(vEnable, %FALSE)
END IF
PRINT "Run again to see change..."
COLOR 7
'Need "Run as Admin"
OBJECT LET oItem.Enable = vEnable
OBJECT CALL oItem.Put_
END IF
PRINT
SET oItem = NOTHING 'Release the object
NEXT
WmiRelease(penum) 'Release the collection enumerator
IF ISOBJECT(oItems) THEN SET oItems = NOTHING ''Release the collection object
Terminate:
IF ISOBJECT(oServices) THEN SET oServices = NOTHING 'Release the Services object
END SUB
'_____________________________________________________________________________
FUNCTION PBMAIN
WMI_MSPower_DeviceEnable
MOUSE ON : MOUSE 3, UP : PRINT : PRINT "Strike any key or click..." : WAITKEY$
END FUNCTION
'_____________________________________________________________________________
'