Author Topic: Windows - Power management tab  (Read 3696 times)

0 Members and 1 Guest are viewing this topic.

Offline Pierre Bellisle

  • Jr. Member
  • **
  • Posts: 82
  • User-Rate: +11/-7
Windows - Power management tab
« on: June 10, 2015, 09:29:48 PM »
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
Code: [Select]
#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
'_____________________________________________________________________________
'
« Last Edit: June 22, 2015, 04:28:47 AM by Pierre Bellisle »

Offline José Roca

  • Administrator
  • Hero Member
  • *****
  • Posts: 2481
  • User-Rate: +204/-0
Re: Windows - Power management tab
« Reply #1 on: June 11, 2015, 04:13:35 PM »
I don't find documentation about this class in MSDN. What I have found are some scripts and they call the Put method after changing the Enable value.

Offline Pierre Bellisle

  • Jr. Member
  • **
  • Posts: 82
  • User-Rate: +11/-7
Re: Windows - Power management tab
« Reply #2 on: June 11, 2015, 06:57:03 PM »
Yep,
works like a charm now.

Above code updated. Need to be "Run as Admin".
To try, put a valid device name for your PC.

Thank...   

Pierre
« Last Edit: June 11, 2015, 08:54:26 PM by Pierre Bellisle »