Jump to content

USB Communication?


Recommended Posts

Would anyone be able to help in converting this to autoit?

This is an API call dump using API Monitor.

and here is my current code

#include <WinAPI.au3>

Local $sFile, $hFile, $sText, $nBytes, $tBuffer


;CreateFileA ( "\\?\usb#vid_0922&pid_0021#13122609380381#{28d78fad-5a12-11d1-ae5b-0000f803a8c2}", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL )
; 1) create file and write data to it
$sFile = "\\?\usb#vid_0922&pid_0021#13122609380381#{28d78fad-5a12-11d1-ae5b-0000f803a8c2}\PIPE00"
$sText = 'abcdefghijklmnopqrstuvwxyz'
$tBuffer = DllStructCreate("byte[" & StringLen($sText) & "]")
DllStructSetData($tBuffer, 1, $sText)
$hFile = _WinAPI_CreateFile($sFile,3,4,4)
_WinAPI_WriteFile($hFile, DllStructGetPtr($tBuffer), StringLen($sText), $nBytes)
_WinAPI_CloseHandle($hFile)
ConsoleWrite('1) ' & FileRead($sFile) & @CRLF)

FileDelete($sFile)

USB2.apmx86(NOT .au3).au3

What is what? What is what.

Link to comment
Share on other sites

Here is the execution process of usb2.exe as shown by API Monitor

#cs
===============================================================================================================================
SetupDiGetClassDevsA({28d78fad-5a12-11d1-ae5b-0000f803a8c2},NULL,NULL,DIGCF_DEVICEINTERFACE|DIGCF_PRESENT)
===============================================================================================================================
#   Type        Name        Pre-Call Value                                      Post-Call Value
1   LPGUID      ClassGuid   0x004020e8={28d78fad-5a12-11d1-ae5b-0000f803a8c2}   0x004020e8={28d78fad-5a12-11d1-ae5b-0000f803a8c2}
2   PCTSTR      Enumerator  NULL                                                NULL
3   HWND        hwndParent  NULL                                                NULL
4   DWORD       Flags       DIGCF_DEVICEINTERFACE|DIGCF_PRESENT               DIGCF_DEVICEINTERFACE|DIGCF_PRESENT
    HDEVINFO    Return      0x005ef130
===============================================================================================================================


===============================================================================================================================
SetupDiEnumDeviceInterfaces(0x005ef130,NULL,{28d78fad-5a12-11d1-ae5b-0000f803a8c2},0,0x0018fce4)
===============================================================================================================================
#   Type                                Name                            Pre-Call Value                                                                                  Post-Call Value
1   HDEVINFO                            DeviceInfoSet                   0x005ef130                                                                                      0x005ef130
2   PSP_DEVICE_INTERFACE_DATA           DeviceInterfaceData             0x0018fce4={cbSize=28,InterfaceClassGuid={28d78fad-5a12-11d1-ae5b-0000f803a8c2},Flags=1  ...}   0x0018fce4={cbSize=28,InterfaceClassGuid={28d78fad-5a12-11d1-ae5b-0000f803a8c2},Flags=1  ...}
3   PSP_DEVICE_INTERFACE_DETAIL_DATA    DeviceInterfaceDetailData       0x005b2a30={cbSize=5,DevicePath=0xc4}                                                           0x005b2a30={cbSize=5,DevicePath="\"}
4   DWORD                               DeviceInterfaceDetailDataSize   84                                                                                              84
5   PDWORD                              RequiredSize                    NULL                                                                                            NULL
6   PSP_DEVINFO_DATA                    DeviceInfoData                  NULL                                                                                            NULL
    BOOL                                Return                                                                                                                          TRUE
===============================================================================================================================


===============================================================================================================================
SetupDiGetDeviceInterfaceDetailA(0x005ef130,0x0018fce4,0x005b2a30,84,NULL,NULL)
===============================================================================================================================
#   Type                                Name                            Pre-Call Value  Post-Call Value
1   HDEVINFO                            DeviceInfoSet                   0x005ef130  0x005ef130
2   PSP_DEVICE_INTERFACE_DATA           DeviceInterfaceData             0x0018fce4={cbSize=28,InterfaceClassGuid={28d78fad-5a12-11d1-ae5b-0000f803a8c2},Flags=1  ...}   0x0018fce4={cbSize=28,InterfaceClassGuid={28d78fad-5a12-11d1-ae5b-0000f803a8c2},Flags=1  ...}
3   PSP_DEVICE_INTERFACE_DETAIL_DATA    DeviceInterfaceDetailData       0x005b2a30={cbSize=5,DevicePath=0xc4}                                                           0x005b2a30={cbSize=5,DevicePath="\"}
4   DWORD                               DeviceInterfaceDetailDataSize   84                                                                                              84
5   PDWORD                              RequiredSize                    NULL                                                                                            NULL
6   PSP_DEVINFO_DATA                    DeviceInfoData                  NULL                                                                                            NULL
    BOOL                                Return                                                                                                                          TRUE
===============================================================================================================================


===============================================================================================================================
CreateFileA("\\?\usb#vid_0922&pid_0021#13122609380381#{28d78fad-5a12-11d1-ae5b-0000f803a8c2}",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)
===============================================================================================================================
#   Type                    Name                    Pre-Call Value                                                                                  Post-Call Value
1   LPCTSTR                 lpFileName              0x005b2a34 "\\?\usb#vid_0922&pid_0021#13122609380381#{28d78fad-5a12-11d1-ae5b-0000f803a8c2}"    0x005b2a34 "\\?\usb#vid_0922&pid_0021#13122609380381#{28d78fad-5a12-11d1-ae5b-0000f803a8c2}"
2   DWORD                   dwDesiredAccess         GENERIC_READ | GENERIC_WRITE                                                                    GENERIC_READ | GENERIC_WRITE
3   DWORD                   dwShareMode             FILE_SHARE_READ | FILE_SHARE_WRITE                                                              FILE_SHARE_READ | FILE_SHARE_WRITE
4   LPSECURITY_ATTRIBUTES   lpSecurityAttributes    NULL                                                                                            NULL
5   DWORD                   dwCreationDisposition   OPEN_EXISTING                                                                                   OPEN_EXISTING
6   DWORD                   dwFlagsAndAttributes    FILE_ATTRIBUTE_NORMAL                                                                           FILE_ATTRIBUTE_NORMAL
7   HANDLE                  hTemplateFile           NULL                                                                                            NULL
    HANDLE                  Return                                                                                                                  0x000000e8
===============================================================================================================================


===============================================================================================================================
CloseHandle ( 0x000000e8 )
===============================================================================================================================
#   Type    Name    Pre-Call Value  Post-Call Value
1   HANDLE  hObject 0x000000e8      0x000000e8
    BOOL    Return                  TRUE
===============================================================================================================================


===============================================================================================================================
CreateFileA("\\?\usb#vid_0922&pid_0021#13122609380381#{28d78fad-5a12-11d1-ae5b-0000f803a8c2}\PIPE00",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)
===============================================================================================================================
#   Type                    Name                    Pre-Call Value                                                                                          Post-Call Value
1   LPCTSTR                 lpFileName              0x005b2aa0 "\\?\usb#vid_0922&pid_0021#13122609380381#{28d78fad-5a12-11d1-ae5b-0000f803a8c2}\PIPE00"     0x005b2aa0 "\\?\usb#vid_0922&pid_0021#13122609380381#{28d78fad-5a12-11d1-ae5b-0000f803a8c2}\PIPE00"
2   DWORD                   dwDesiredAccess         GENERIC_READ | GENERIC_WRITE                                                                            GENERIC_READ | GENERIC_WRITE
3   DWORD                   dwShareMode             0                                                                                                       0
4   LPSECURITY_ATTRIBUTES   lpSecurityAttributes    NULL                                                                                                    NULL
5   DWORD                   dwCreationDisposition   OPEN_EXISTING                                                                                           OPEN_EXISTING
6   DWORD                   dwFlagsAndAttributes    FILE_ATTRIBUTE_NORMAL                                                                                   FILE_ATTRIBUTE_NORMAL
7   HANDLE                  hTemplateFile           NULL                                                                                                    NULL
    HANDLE                  Return                                                                                                                          0x000000e8
===============================================================================================================================


===============================================================================================================================
fopen("E:\TechUtils\Initial.Automation\Data\OneButton\Gray.2335dn","r+b")
===============================================================================================================================
#   Type            Name        Pre-Call Value                                                              Post-Call Value
1   const char*     filename    0x005b281c "E:\TechUtils\Initial.Automation\Data\OneButton\Gray.2335dn"     0x005b281c "E:\TechUtils\Initial.Automation\Data\OneButton\Gray.2335dn"
2   const char*     mode        0x004030b8 "r+b"                                                            0x004030b8 "r+b"
    FILE*           Return                                                                                  0x758d2960
===============================================================================================================================


===============================================================================================================================
printf("
Downloading...", ...)
===============================================================================================================================
#   Type            Name    Pre-Call Value      Post-Call Value
1   const char*     format  0x00403090 "        0x00403090 "
                            Downloading..."     Downloading..."
...                 ...
    int             Return                      15
===============================================================================================================================


===============================================================================================================================
fread(0x0018eca8,1,4096,0x758d2960)
===============================================================================================================================
#   Type    Name    Pre-Call Value  Post-Call Value
1   void*   buffer  0x0018eca8      0x0018eca8
2   size_t  size    1               1
3   size_t  count   4096            4096
4   FILE*   stream  0x758d2960      0x758d2960
    size_t  Return                  759
===============================================================================================================================


===============================================================================================================================
WriteFile(0x000000e8,0x0018eca8,759,0x0018eca4,NULL)
===============================================================================================================================
#   Type        Name    Pre-Call Value      Post-Call Value
1   const char* format  0x0040308c "..."    0x0040308c "..."
...             ...
    int         Return                      3
===============================================================================================================================


===============================================================================================================================
printf("...", ...)
===============================================================================================================================
#   Type        Name    Pre-Call Value      Post-Call Value
1   const char* format  0x0040308c "..."    0x0040308c "..."
...             ...
    int         Return                      3
===============================================================================================================================


===============================================================================================================================
fread(0x0018eca8,1,4096,0x758d2960)
===============================================================================================================================
#   Type    Name    Pre-Call Value  Post-Call Value
1   void*   buffer  0x0018eca8      0x0018eca8
2   size_t  size    1               1
3   size_t  count   4096            4096
4   FILE*   stream  0x758d2960      0x758d2960
    size_t  Return                  0
===============================================================================================================================


===============================================================================================================================
printf("

Download complete!! downsize(%d)

", ...)
===============================================================================================================================
#   Type        Name    Pre-Call Value                      Post-Call Value
1   const char* format  0x00403064 "                        0x00403064 "

                        Download complete!! downsize(%d)    Download complete!! downsize(%d)

                        "                                   "
...             ...
    int         Return                                      38
===============================================================================================================================


===============================================================================================================================
fclose(0x758d2960)
===============================================================================================================================
#   Type    Name    Pre-Call Value  Post-Call Value
1   FILE*   stream  0x758d2960      0x758d2960
    int     Return                  0
===============================================================================================================================


===============================================================================================================================
CloseHandle(0x000000e8)
===============================================================================================================================
#   Type    Name    Pre-Call Value  Post-Call Value
1   HANDLE  hObject 0x000000e8      0x000000e8
    BOOL    Return                  TRUE
===============================================================================================================================


===============================================================================================================================
SetupDiEnumDeviceInterfaces(0x005ef130,NULL,{28d78fad-5a12-11d1-ae5b-0000f803a8c2},1,0x0018fce4)
===============================================================================================================================
#   Type                        Name                Pre-Call Value                                                                                  Post-Call Value
1   HDEVINFO                    DeviceInfoSet       0x005ef130                                                                                      0x005ef130
2   PSP_DEVINFO_DATA            DeviceInfoData      NULL                                                                                            NULL
3   LPGUID                      InterfaceClassGuid  0x004020e8                                                                                      0x004020e8
    GUID                                            {28d78fad-5a12-11d1-ae5b-0000f803a8c2}                                                          {28d78fad-5a12-11d1-ae5b-0000f803a8c2}
4   DWORD                       MemberIndex         2                                                                                               2
5   PSP_DEVICE_INTERFACE_DATA   DeviceInterfaceData 0x0018fce4={cbSize=28,InterfaceClassGuid={28d78fad-5a12-11d1-ae5b-0000f803a8c2},Flags=1 ...}    0x0018fce4={cbSize=28,InterfaceClassGuid={28d78fad-5a12-11d1-ae5b-0000f803a8c2},Flags=1 ...}
    BOOL                        Return                                                                                                              FALSE
===============================================================================================================================


===============================================================================================================================
GetLastError()
===============================================================================================================================
#   Type    Name    Pre-Call Value  Post-Call Value
    DWORD   Return                  ERROR_NO_MORE_ITEMS
===============================================================================================================================


===============================================================================================================================
SetupDiDestroyDeviceInfoList(0x005ef130)
===============================================================================================================================
#   Type        Name            Pre-Call Value  Post-Call Value
1   HDEVINFO    DeviceInfoSet   0x005ef130      0x005ef130
    BOOL        Return                          TRUE
===============================================================================================================================


===============================================================================================================================
exit(0)
===============================================================================================================================
#   Type    Name    Pre-Call Value  Post-Call Value
1   int     status  0
===============================================================================================================================
#ce

What is what? What is what.

Link to comment
Share on other sites

Here is a working sketch...

 

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Compression=4
#AutoIt3Wrapper_UseUpx=y
#AutoIt3Wrapper_UseX64=n
#AutoIt3Wrapper_Change2CUI=y
#AutoIt3Wrapper_Run_Au3Stripper=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#Include <Array.au3>
#Include <WInAPIDiag.au3>
#Include <SetupAPI.au3>
$hDevInfo=_SetupDiGetClassDevs(BitOR($DIGCF_DEVICEINTERFACE,$DIGCF_PRESENT),"{28d78fad-5a12-11d1-ae5b-0000f803a8c2}")
Local $tSP_DEVINFO_DATA
Local $tSP_DEVIFINFO_DATA
Local $pSP_DEVINFO_DATA
Local $pSP_DEVIFINFO_DATA
DllStructSetData($pSP_DEVIFINFO_DATA,"cbSize",DllStructGetSize($pSP_DEVIFINFO_DATA))
Local $iDevEnumIfIndex=0
Local $iDelay=0
Local $aDevs[1][7]
$aDevs[0][0]=0
$aDevs[0][1]=0
$aDevs[0][2]=0
$aDevs[0][3]=0
$aDevs[0][4]=0
$aDevs[0][5]=0
$aDevs[0][6]=0
;GUI()
;Get all Device Paths
While True
    $bDevEnumIf=_SetupDiEnumDeviceInterfaces($hDevInfo,0,"{28d78fad-5a12-11d1-ae5b-0000f803a8c2}",$iDevEnumIfIndex,$pSP_DEVIFINFO_DATA)
    If Not $bDevEnumIf Then ExitLoop
    ReDim $aDevs[UBound($aDevs,1)+1][7]
    $aDevs[UBound($aDevs,1)-1][2]=0
    Con()
    $sDevPath=_SetupDiGetDeviceInterfaceDetail($hDevInfo,$pSP_DEVIFINFO_DATA,$tSP_DEVINFO_DATA)
    If Not $sDevPath<>"" Then
        $aDevs[UBound($aDevs,1)-1][2]=-1
            Con()
        ContinueLoop
    EndIf
    $aDevs[UBound($aDevs,1)-1][1]=$sDevPath
    $aDevs[UBound($aDevs,1)-1][2]=1
    Con()
    $iDevEnumIfIndex+=1
WEnd
For $Index=0 To UBound($aDevs,1)-1
    $aDevs[$Index][0]=_WinAPI_CreateFileEx($aDevs[$Index][1], $OPEN_EXISTING,BitOR($GENERIC_READ,$GENERIC_WRITE),BitOR($FILE_SHARE_READ,$FILE_SHARE_WRITE))
    If @error Then
        $aDevs[$Index][1]=""
        $aDevs[$Index][2]=-2
            Con()
        ContinueLoop
    EndIf
    $aDevs[$Index][2]=2
    Con()
    _WinAPI_CloseHandle($aDevs[$Index][0])
    $aDevs[$Index][0]=_WinAPI_CreateFileEx($aDevs[$Index][1]&"\PIPE00",$OPEN_EXISTING,BitOR($GENERIC_READ,$GENERIC_WRITE))
    If @error Then
        $aDevs[$Index][1]=""
        $aDevs[$Index][2]=-3
            Con()
        ContinueLoop
    EndIf
    $aDevs[$Index][2]=3
    Con()
    $aDevs[$Index][3]=DllStructCreate("byte[4096]")
    $aDevs[$Index][4]=0
Next
Local $sFile=@ScriptDir&"\Blank_black.5330dn",$nBytes;"\5330dn_2.70.00.52.hd",$nBytes;",$nBytes;"\Alignment.2335dn"
$iSize=FileGetSize($sFile)
;~ $iBuffSize=4096
;~ $tBuffer=DllStructCreate("byte["&$iBuffSize&"]")
$bFile=FileRead($sFile)
;~ For $a=0 To $iSize Step $iBuffSize
;~     DllStructSetData($tBuffer,1,BinaryMid($bFile,$a,$iBuffSize))
;~     _WinAPI_WriteFile($aDevs[1][0], DllStructGetPtr($tBuffer),$iBuffSize,$nBytes)
;~ Next
$tBuffer=DllStructCreate("byte["&$iSize&"]")
DllStructSetData($tBuffer,1,$bFile)
_WinAPI_WriteFile($aDevs[1][0], DllStructGetPtr($tBuffer),$iSize,$nBytes)

;_WinAPI_CloseHandle($hFile)

;~ Local $bFile=Binary(FileRead($sFile))
;~ ;Local $hFile=_WinAPI_CreateFile($sFile,2,2)

;~ ;Semi-Asynchronous
;~ For $iPos=0 To BinaryLen($bFile) Step 4096
;~     _WinAPI_SetFilePointer($hFile,$iPos)
;~     If @error Then
;~         $aDevs[$Index][2]=-4;Failed to Set Pointer
;~         ;Con()
;~         ExitLoop
;~     EndIf
;~     ;For $Index=1 To 1;UBound($aDevs,1)-1
;~     Local $iNDEX=1
;~     ;Local $Index
;~         If $aDevs[$Index][2]=-4 Then
;~             ;Con()
;~             ExitLoop; Continue with others
;~         EndIf
;~         _WinAPI_ReadFile($hFile,DllStructGetPtr($aDevs[$Index][3]),4096,$aDevs[$Index][4])
;~         If @error Then
;~             $aDevs[$Index][2]=-4; Failed to Read File
;~             ;Con()
;~             ExitLoop; Continue with others
;~         EndIf
;~         ;$aDevs[$Index][3]
;~         MsgBox(64,BinaryLen($bFile),BinaryMid($bFile,0,256))
;~         Exit
;~         ;DllStructSetData(DllStructGetPtr($aDevs[$Index][3]),1,);
;~         _WinAPI_DisplayStruct($aDevs[$Index][3])
;~         _WinAPI_WriteFile($aDevs[$Index][0],DllStructGetPtr($aDevs[$Index][3]),4096,$aDevs[$Index][5])
;~         If @error Then
;~             $aDevs[$Index][2]=-4; Failed writing to device.
;~             ;Con()
;~             ExitLoop; Continue with others
;~         EndIf
;~         $aDevs[$Index][2]=4
;~         ;Con()
;~         $aDevs[$Index][6]=$iPos
;~     Sleep(100)
;~     ;Next
;~ Next
For $Index=0 To UBound($aDevs,1)-1
    _WinAPI_CloseHandle($aDevs[$Index][0])
        If @error Then
            $aDevs[$Index][2]=-5; Failed Closing Device
            Con()
            ContinueLoop
        EndIf
    $aDevs[$Index][2]=5; Completed
    Con()
Next
;_WinAPI_CloseHandle($hFile)
_SetupDiDestroyDeviceInfoList($hDevInfo)
Sleep(5000)
Exit 0
;Console Colums

Func CON()
    ;_WinAPI_ClearConsole()
    Local $sMsg=""
    For $Index=1 To UBound($aDevs,1)-1
        $sMsg&=$Index&". "&_StringCompact($aDevs[$Index][1],16)&"|"
        Switch $aDevs[$Index][2]
            Case 0
                $sStat="Getting Interface Devices"
            Case 1
                $sStat="Getting Device Paths"
            Case 2
                $sStat="Getting Device Handel"
            Case 3
                $sStat="Opening Device Handel"
            Case 4
                $sStat="Sending data"
            Case 5
                $sStat="Done"
            Case -0
                $sStat="Failed to get Device interface"
            Case -1
                $sStat="Failed to get device path"
            Case -2
                $sStat="Failed getting device handel"
            Case -3
                $sStat="Failed opening device handel"
            Case -4
                $sStat="Failed to send data"
            Case -5
                $sStat="Failed to close handel"
        EndSwitch
        $sMsg&=$sStat&"|"
        $sMsg&=$aDevs[$Index][2]&"|"
        $sMsg&=$aDevs[$Index][4]&"|"
        $sMsg&=$aDevs[$Index][5]&"|"
        $sMsg&=$aDevs[$Index][6]&@CRLF
    Next
    ToolTip($sMsg)
    ;ConsoleWrite($sMsg)
    If $iDelay>0 Then Sleep($iDelay)
EndFunc

; #FUNCTION# =======================================================
; Name...........: _WinAPI_ClearConsole
; Description ...: Clears console screen buffer /w six options to clear rows & characters & set cursor position
; Syntax.........: _WinAPI_ClearConsole($hConsole = -1, $iX = Default, $iY = Default)
; Parameters ....: $hConsole - (Optional) Handle to standard output device
; $iX - (Optional) zero based character column position of cursor
; Default or 0 to screen buffer max width (negative values for some modes)
; $iY - (Optional) zero based row position of cursor
; Default or 0 to screen buffer max height (negative values for some modes)
;
;No params ; clear screen (-1, Default, Default)
;(-1, Default, 0) ; clear single row: $iY = row number (0 is row 1)
;(-1, -2, -3) ; clear block of rows: -$iX = number of rows, -$iY = starting row (minimum $iX = -1, $iY = -1)
;(-1, Default, -1) ; clear all rows from start row: -$iY = starting row (minimum $iY = -1)
;(-1, 20, 2) ; clear characters to end of row: $iX = start character column, $iY = row number
;(-1, -20, 2) ; set cursor at coordinates: -$iX = start character column, $iY = row number (minimum $iX = -1)
;(-1, 0, Default) ; set cursor on bottom row of console window: $iX = start character column

; Return values .: Success - return handle to standard output device (does not have to be closed)
; Failure - return 0, set error and extended
; Author ........: rover
; Modified.......:
; Remarks .......:
; Related .......:
;
; Link ..........; @@MsdnLink@@ FillConsoleOutputCharacter
; Example .......; Yes
; ==================================================================
Func _WinAPI_ClearConsole($hConsole = -1, $iX = Default, $iY = Default)
Local $dwCoord, $fFlag = False
Local $bChar = 0x20, $iErr ; fill character: 0x20 (Space)
Local Const $STD_OUTPUT_HANDLE = -11
Local Const $INVALID_HANDLE_VALUE = -1
Local Const $tagCONSOLE_SCREEN_BUFFER_INFO = "short dwSizeX; short dwSizeY;short dwCursorPositionX;" & _
"short dwCursorPositionY; short wAttributes;short Left; short Top; short Right; short Bottom;" & _
"short dwMaximumWindowSizeX; short dwMaximumWindowSizeY"

;// get handle to standard output device (handle does not have to be closed on return)
Local $hDLLK32 = DllOpen("Kernel32.dll"), $aRet
If $hConsole = -1 Then
$aRet = DllCall($hDLLK32, "hwnd", "GetStdHandle", "dword", $STD_OUTPUT_HANDLE)
$iErr = @error
If @error Or UBound($aRet) <> 2 Or $aRet[0] = $INVALID_HANDLE_VALUE Then
Return SetError($iErr, 1, $INVALID_HANDLE_VALUE)
EndIf
$hConsole = $aRet[0]
EndIf

;// create console screen buffer struct, get buffer
Local $tCONSOLE_SCREEN_BUFFER_INFO = DllStructCreate($tagCONSOLE_SCREEN_BUFFER_INFO)
If @error Then Return SetError(@error, 2, 0)
Local $pConsoleScreenBufferInfo = DllStructGetPtr($tCONSOLE_SCREEN_BUFFER_INFO)
If @error Then Return SetError(@error, 3, 0)

$aRet = DllCall($hDLLK32, "int", "GetConsoleScreenBufferInfo", "hwnd", _
$hConsole, "ptr", $pConsoleScreenBufferInfo)
$iErr = @error
If @error Or UBound($aRet) <> 3 Or Not $aRet[0] Then Return SetError($iErr, 4, 0)

;// Get the screen buffer max width (character columns) and height (rows)
Local $dwSizeX = DllStructGetData($tCONSOLE_SCREEN_BUFFER_INFO, "dwSizeX")
Local $dwSizeY = DllStructGetData($tCONSOLE_SCREEN_BUFFER_INFO, "dwSizeY")
Local $dwConSize

;// input coordinates range check
If IsNumber($iX) And (Abs($iX) > ($dwSizeX -1)) Then $iX = $dwSizeX -1
If IsNumber($iY) And (Abs($iY) > ($dwSizeY -1)) Then $iY = $dwSizeY -1

Select
;// clear screen (Default) - max screen buffer width multiplied by height
Case IsNumber($iX) = 0 And IsNumber($iY) = 0
; handles Default keyword and strings in params
$dwConSize = ($dwSizeX * $dwSizeY)
$iX = 0
$iY = 0
;// overwrite or clear any single row - cursor now set to start of that row
Case IsKeyword($iX) = 1 And IsKeyword($iY) = 0 And $iY >= 0
$dwConSize = $dwSizeX
$iX = 0
;// overwrite or clear a number of rows from starting row
;(-$iX parameter is number of rows to overwrite, second row minimum)
Case $iX < 0 And $iY < 0
$iY = Abs($iY)
$dwConSize = ($dwSizeX * Abs($iX))
$iX = 0
;// overwrite or clear all rows from starting row to last row, second row minimum)
Case IsKeyword($iX) = 1 And $iY < 0
$iY = Abs($iY)
$dwConSize = ($dwSizeX * $dwSizeY) - ($dwSizeX * $iY)
$iX = 0
;// overwrite or clear text from character position on row to end of row
Case $iX >= 0 And IsKeyword($iY) = 0 And $iY >= 0
$dwConSize = ($dwSizeX - $iX)
If $iX = 0 And $iY = 0 Then
$fFlag = True
ContinueCase
EndIf
;// place cursor at last row of console window
Case $iX >= 0 And IsKeyword($iY) = 1
If Not $fFlag Then $iY = DllStructGetData($tCONSOLE_SCREEN_BUFFER_INFO, "Bottom")
ContinueCase
;// places cursor at coordinates for overwriting
Case $iX < 0 And $iY >= 0
$dwCoord = BitOR($iY * 0x10000, BitAND(Abs($iX), 0xFFFF))
$aRet = DllCall($hDLLK32, "int", "SetConsoleCursorPosition", "hwnd", _
$hConsole, "dword", $dwCoord)
$iErr = @error
If @error Or UBound($aRet) <> 3 Or Not $aRet[0] Then Return SetError($iErr, 5, 0)
DllClose($hDLLK32)
Return SetError(0, 0, $hConsole)
Case Else
Return SetError(@error, 6, 0)
EndSelect

;// Cursor position: make DWord of X,Y coordinates)
$dwCoord = BitOR($iY * 0x10000, BitAND($iX, 0xFFFF))

;// Fill selected rows with blanks
$aRet = DllCall($hDLLK32, "int", "FillConsoleOutputCharacterW", "hwnd", $hConsole, _
"byte", $bChar, "dword", $dwConSize, "dword", $dwCoord, "int*", 0)
$iErr = @error
If @error Or UBound($aRet) <> 6 Or $aRet[5] <> $dwConSize Then Return SetError($iErr, 7, 0)

;// Get the current text attributes
$aRet = DllCall($hDLLK32, "int", "GetConsoleScreenBufferInfo", "hwnd", _
$hConsole, "dword", $pConsoleScreenBufferInfo)
$iErr = @error
If @error Or UBound($aRet) <> 3 Or Not $aRet[0] Then Return SetError($iErr, 8, 0)
Local $wAttribute = DllStructGetData($tCONSOLE_SCREEN_BUFFER_INFO, "wAttributes")

;// Set the buffer's attributes
$aRet = DllCall($hDLLK32, "int", "FillConsoleOutputAttribute", "hwnd", $hConsole, _
"short", $wAttribute, "dword", $dwConSize, "dword", $dwCoord, "int*", 0)
$iErr = @error
If @error Or UBound($aRet) <> 6 Or $aRet[5] <> $dwConSize Then Return SetError($iErr, 9, 0)

;// Put the cursor at 0,0 or supplied coordinates
$aRet = DllCall($hDLLK32, "int", "SetConsoleCursorPosition", "hwnd", _
$hConsole, "dword", $dwCoord)
$iErr = @error
If @error Or UBound($aRet) <> 3 Or Not $aRet[0] Then Return SetError($iErr, 10, 0)
DllClose($hDLLK32)
Return SetError(@error, 0, $hConsole)
EndFunc ;==>_WinAPI_ClearConsole


; #FUNCTION# ====================================================================================================================
; Name ..........: _StringCompact
; Description ...: Compact a string to a certain number of characters left and right.
; Syntax ........: _StringCompact($sString[, $iChrsLeftAndRight = Default])
; Parameters ....: $sString             - A string to compact. Multi-lines aren't supported.
;                  $iChrsLeftAndRight   - [optional] An integer value. Default is 0, original string.
; Return values .: Compacted string.
; Author ........: guinness. Idea by AZJIO.
; Example .......: Yes
; ===============================================================================================================================
; #FUNCTION# ====================================================================================================================
; Name ..........: _StringCompact
; Description ...: Compact a string to a certain number of characters left and right.
; Syntax ........: _StringCompact($sString[, $iChrsLeftAndRight = Default])
; Parameters ....: $sString             - A string to compact. Multi-lines are supported.
;                  $iChrsLeftAndRight   - [optional] An integer value. Default is 0, original string.
; Return values .: Compacted string.
; Author ........: guinness.
; Example .......: Yes
; ===============================================================================================================================
Func _StringCompact($sString, $iChrsLeftAndRight = Default)
    $iChrsLeftAndRight = Int($iChrsLeftAndRight)
    Local $sStringCompact = $sString
    If StringLen($sString) > ($iChrsLeftAndRight * 2) Then
        $sStringCompact = StringLeft($sString, $iChrsLeftAndRight) & '...' & StringRight($sString, $iChrsLeftAndRight)
    EndIf
    Return $sStringCompact
EndFunc   ;==>_StringCompact

SetupAPI.au3

#include-once
#include <LocalSecurityAuthority.au3>

; #### HEADER INFORMATION ####
; ===============================================================================
; Title : PnP Configuration Manager
; Description   : Plug and Play (PnP) Configuration Manager that are used by class installers, co-installers, or device installation applications.
; Functions : 1 - Scaning device changes on a local or a remote system.
;       : 2 - Disable and enable an existing hardware device, on local or remote system.
;       : 3 - Install and remove device setup classes, devices and device interfaces.
;       : 4 - Create or remove resource descriptor (or get / set information) for a device instance.
;       : 5 - List the devices (or device interfaces) present in local or remote system.
;       : 6 - Read or write device interfaces.
;       : 7 - Else more ...
; Requirements  : AutoIt Version    : AutoIt v3 ++
;       : AutoIt Libraries  : Array.au3, LocalSecurityAuthority.au3
;       : Modules       : Advapi32.dll, Cfgmgr32.dll, Kernel32.dll, Newdev.dll, Setupapi.dll
;       : Minimum client    : Windows 2000 Professional
; Author    : Pusofalse @ 11/20/2009, kanxinqi@yahoo.com.cn
; ==============================================================================

; #### General size definitions ####
; ==============================================================================
Const $MAX_DEVICE_ID_LEN = 200
Const $MAX_DEVNODE_ID_LEN = $MAX_DEVICE_ID_LEN

Const $MAX_GUID_STRING_LEN = 39
Const $MAX_CLASS_NAME_LEN = 32
Const $MAX_PROFILE_LEN = 80

Const $MAX_CONFIG_VALUE = 9999
Const $MAX_INSTANCE_VALUE = 9999

Const $MAX_MEM_REGISTERS = 9 ; Win95 compatibility--not applicable to 32-bit ConfigMgr
Const $MAX_IO_PORTS = 20 ; Win95 compatibility--not applicable to 32-bit ConfigMgr
Const $MAX_IRQS = 7 ; Win95 compatibility--not applicable to 32-bit ConfigMgr
Const $MAX_DMA_CHANNELS = 7 ; Win95 compatibility--not applicable to 32-bit ConfigMgr

Const $CONFIGMG_VERSION = 0x0400
; ==============================================================================

; #### Device Node Status Constants ####
; ==============================================================================
Const $DN_ROOT_ENUMERATED = 0x00000001   ;  Was enumerated by ROOT
Const $DN_DRIVER_LOADED   = 0x00000002   ;  Has Register_Device_Driver
Const $DN_ENUM_LOADED = 0x00000004   ;  Has Register_Enumerator
Const $DN_STARTED = 0x00000008   ;  Is currently configured
Const $DN_MANUAL  = 0x00000010   ;  Manually installed
Const $DN_NEED_TO_ENUM    = 0x00000020   ;  May need reenumeration
Const $DN_NOT_FIRST_TIME  = 0x00000040   ;  Has received a config
Const $DN_HARDWARE_ENUM   = 0x00000080   ;  Enum generates hardware ID
Const $DN_LIAR    = 0x00000100   ;  Lied about can reconfig once
Const $DN_NEED_RESTART = $DN_LIAR   ; Need a system restart
Const $DN_HAS_MARK    = 0x00000200   ;  Not CM_Create_DevInst lately
Const $DN_HAS_PROBLEM = 0x00000400   ;  Need device installer
Const $DN_FILTERED    = 0x00000800   ;  Is filtered
Const $DN_MOVED   = 0x00001000   ;  Has been moved
Const $DN_DISABLEABLE = 0x00002000   ;  Can be rebalanced
Const $DN_REMOVABLE   = 0x00004000   ;  Can be removed
Const $DN_PRIVATE_PROBLEM = 0x00008000   ;  Has a private problem
Const $DN_MF_PARENT   = 0x00010000   ;  Multi function parent
Const $DN_MF_CHILD    = 0x00020000   ;  Multi function child
Const $DN_WILL_BE_REMOVED = 0x00040000   ;  DevInst is being removed
Const $DN_NOT_FIRST_TIMEE  = 0x00080000  ;   Has received a config enumerate
Const $DN_STOP_FREE_RES    = 0x00100000  ;   When child is stopped, free resources
Const $DN_REBAL_CANDIDATE  = 0x00200000  ;   Don't skip during rebalance
Const $DN_BAD_PARTIAL      = 0x00400000  ;   This devnode's log_confs do not have same resources
Const $DN_NT_ENUMERATOR    = 0x00800000  ;   This devnode's is an NT enumerator
Const $DN_NT_DRIVER        = 0x01000000  ;   This devnode's is an NT driver
Const $DN_NEEDS_LOCKING    = 0x02000000  ;   Devnode need lock resume processing
Const $DN_ARM_WAKEUP        = 0x04000000  ;   Devnode can be the wakeup device
Const $DN_APM_ENUMERATOR    = 0x08000000  ;   APM aware enumerator
Const $DN_APM_DRIVER        = 0x10000000  ;   APM aware driver
Const $DN_SILENT_INSTALL    = 0x20000000  ;   Silent install
Const $DN_NO_SHOW_IN_DM    = 0x40000000  ;   No show in device manager
Const $DN_BOOT_LOG_PROB    = 0x80000000  ;   Had a problem during pre
; ==============================================================================

; SP_DEVINSTALL_PARAMS.Flags Constants
; ===============================================================================
Const $DI_SHOWOEM = 0x00000001 ; support Other... button
Const $DI_SHOWCOMPAT = 0x00000002 ; show compatibility list
Const $DI_SHOWCLASS = 0x00000004 ; show class list
Const $DI_SHOWALL = 0x00000007 ; both class & compat list shown
Const $DI_NOVCP = 0x00000008 ; don't create a new copy queue--use caller-supplied FileQueue
Const $DI_DIDCOMPAT = 0x00000010 ; Searched for compatible devices
Const $DI_DIDCLASS = 0x00000020 ; Searched for class devices
Const $DI_AUTOASSIGNRES = 0x00000040 ; No UI for resources if possible

; flags returned by DiInstallDevice to indicate need to reboot/restart
Const $DI_NEEDRESTART = 0x00000080 ; Reboot required to take effect
Const $DI_NEEDREBOOT = 0x00000100 ; Same as DI_NEEDRESTART

; flags for device installation
Const $DI_NOBROWSE = 0x00000200 ; no Browse... in InsertDisk

; Flags set by DiBuildDriverInfoList
Const $DI_MULTMFGS = 0x00000400 ; Set if multiple manufacturers in class driver list. Flag indicates that device is disabled
Const $DI_DISABLED = 0x00000800 ; Set if device disabled

; Flags for Device/Class Properties
Const $DI_GENERALPAGE_ADDED = 0x00001000
Const $DI_RESOURCEPAGE_ADDED = 0x00002000

; Flag to indicate the setting properties for this Device (or class) caused a change so the Dev Mgr UI probably needs to be updatd.
Const $DI_PROPERTIES_CHANGE = 0x00004000

; Flag to indicate that the sorting from the INF file should be used.
Const $DI_INF_IS_SORTED = 0x00008000

; Flag to indicate that only the INF specified by SP_DEVINSTALL_PARAMS.DriverPath should be searched.
Const $DI_ENUMSINGLEINF = 0x00010000

; Flag that prevents ConfigMgr from removing/re-enumerating devices during device registration, installation, and deletion.
Const $DI_DONOTCALLCONFIGMG = 0x00020000

; The following flag can be used to install a device disabled
Const $DI_INSTALLDISABLED = 0x00040000

; Flag that causes SetupDiBuildDriverInfoList to build a device's compatible driver list from its existing class driver list, instead of the normal INF search.
Const $DI_COMPAT_FROM_CLASS = 0x00080000

; This flag is set if the Class Install params should be used.
Const $DI_CLASSINSTALLPARAMS = 0x00100000

; This flag is set if the caller of DiCallClassInstaller does NOT want the internal default action performed if the Class installer returns ERROR_DI_DO_DEFAULT.
Const $DI_NODI_DEFAULTACTION = 0x00200000

; The setupx flag, DI_NOSYNCPROCESSING (0x00400000) is not support in the Setup APIs. Flags for device installation.
Const $DI_QUIETINSTALL = 0x00800000 ; don't confuse the user with questions or excess info
Const $DI_NOFILECOPY = 0x01000000 ; No file Copy necessary
Const $DI_FORCECOPY = 0x02000000 ; Force files to be copied from install path
Const $DI_DRIVERPAGE_ADDED = 0x04000000 ; Prop provider added Driver page.
Const $DI_USECI_SELECTSTRINGS = 0x08000000 ; Use Class Installer Provided strings in the Select Device Dlg.
Const $DI_OVERRIDE_INFFLAGS = 0x10000000 ; Override INF flags
Const $DI_PROPS_NOCHANGEUSAGE = 0x20000000 ; No Enable/Disable in General Props
Const $DI_NOSELECTICONS = 0x40000000 ; No small icons in select device dialogs
Const $DI_NOWRITE_IDS = 0x80000000 ; Don't write HW & Compat IDs on install
; ======================================================================================

; SP_DEVINSTALL_PARAMS.FlagsEx Constants
; ======================================================================================
Const $DI_FLAGSEX_USEOLDINFSEARCH = 0x00000001 ; Inf Search functions should not use Index Search
Const $DI_FLAGSEX_AUTOSELECTRANK0 = 0x00000002 ; SetupDiSelectDevice doesn't prompt user if rank 0 match
Const $DI_FLAGSEX_CI_FAILED = 0x00000004 ; Failed to Load/Call class installer
Const $DI_FLAGSEX_DIDINFOLIST = 0x00000010 ; Did the Class Info List
Const $DI_FLAGSEX_DIDCOMPATINFO = 0x00000020 ; Did the Compat Info List
Const $DI_FLAGSEX_FILTERCLASSES = 0x00000040
Const $DI_FLAGSEX_SETFAILEDINSTALL = 0x00000080
Const $DI_FLAGSEX_DEVICECHANGE = 0x00000100
Const $DI_FLAGSEX_ALWAYSWRITEIDS = 0x00000200
Const $DI_FLAGSEX_ALLOWEXCLUDEDDRVS = 0x00000800
Const $DI_FLAGSEX_NOUIONQUERYREMOVE = 0x00001000
Const $DI_FLAGSEX_USECLASSFORCOMPAT = 0x00002000 ; Use the device's class when building compat drv list.
 ; (Ignored if DI_COMPAT_FROM_CLASS flag is specified.)
Const $DI_FLAGSEX_OLDINF_IN_CLASSLIST = 0x00004000 ; Search legacy INFs when building class driver list.
Const $DI_FLAGSEX_NO_DRVREG_MODIFY = 0x00008000 ; Don't run AddReg and DelReg for device's software (driver) key.
Const $DI_FLAGSEX_IN_SYSTEM_SETUP = 0x00010000 ; Installation is occurring during initial system setup.
Const $DI_FLAGSEX_INET_DRIVER = 0x00020000 ; Driver came from Windows Update
Const $DI_FLAGSEX_APPENDDRIVERLIST = 0x00040000 ; Cause SetupDiBuildDriverInfoList to append
; ===================================================================================

; Values indicating a change in a devices' state
; ====================================================================================
Const $DICS_ENABLE = 0x00000001
Const $DICS_DISABLE = 0x00000002
Const $DICS_PROPCHANGE = 0x00000003
Const $DICS_START = 0x00000004
Const $DICS_STOP = 0x00000005
; =====================================================================================

; Values specifying the scope of a device property change
; ====================================================================================
Const $DICS_FLAG_GLOBAL = 0x00000001
Const $DICS_FLAG_CONFIGSPECIFIC = 0x00000002
Const $DICS_FLAG_CONFIGGENERAL = 0x00000004
; ====================================================================================

; ####  SetupDiGetClassDevs Constants ####
; ==============================================================================
Const $DIGCF_DEFAULT = 1
Const $DIGCF_PRESENT = 2
Const $DIGCF_ALLCLASSES = 4
Const $DIGCF_PROFILE = 8
Const $DIGCF_DEVICEINTERFACE = 16
; ==============================================================================

; #### SetupDiBuildDriverInfoList Constants (internal) ####
; ==============================================================================
Const $SPDIT_NODRIVER = 0x00000000
Const $SPDIT_CLASSDRIVER = 0x00000001
Const $SPDIT_COMPATDRIVER = 0x00000002
; ==============================================================================
Const $DIBCI_NOINSTALLCLASS = 1
Const $DIBCI_NODISPLAYCLASS = 2

 ; #### Value for SP_UNREMOVEDEVICE_PARAMS.Scope ####
; ==============================================================================
Const $DI_UNREMOVEDEVICE_CONFIGSPECIFIC = 2
; ==============================================================================

; #### Device Installation Structures ####
; ==============================================================================
Const $tagSP_DEVICEINFO_DATA = "dword Size;byte Guid[16];dword DevInst;ulong_ptr Reserved"
Const $tagSP_DEVINFO_LIST_DETAIL_DATA = "dword Size;byte ClassGUID[16];hWnd MachineHandle"

Const $tagSP_DEVINSTALL_PARAMS = "dword Size;dword Flags;dword FlagsEx;hWnd hWndParent;ptr InstallMsgHandler;ptr InstallMsgHandlerContext;ptr FileQueue;ulong_ptr ClassInstallReserved;dword Reserved;char DriverPath[260]"
Const $tagSP_DRVINFO_DATA = "dword Size;dword DriverType;ulong_ptr Reserved;char Descr[256];char MfgName[256];char ProviderName[256];dword FileTime[2];int Version"
Const $tagSP_DRVINFO_DETAIL_DATA = "dword Size;dword InfTime[2];dword CompatIDsOffset;dword CompatIDsLength;ulong_ptr Reserved;char SectionName[256];char InfFileName[260];char DrvDescr[256]"
Const $tagSP_CLASSINSTALL_HEADER = "dword Size;dword DIFCode"
Const $tagSP_DETECTDEVICE_PARAMS = $tagSP_CLASSINSTALL_HEADER & ";ptr NotifyCallback;ptr NotifyParam"
Const $tagSP_PROPCHANGE_PARAMS = $tagSP_CLASSINSTALL_HEADER & ";dword State;dword Scope;dword HwProfile"
Const $tagSP_POWERMESSAGEWAKE_PARAMS = $tagSP_CLASSINSTALL_HEADER & ";char Message[256]"
Const $tagSP_UNREMOVEDEVICE_PARAMS = $tagSP_CLASSINSTALL_HEADER & ";dword Scope;dword HWProfile"
Const $tagSP_DEV_INTERFACE_DATA = "dword Size;byte Guid[16];dword Flags;ulong_ptr Reserved"
Const $tagSP_DEV_INTERFACE_DETAIL_DATA = "dword Size;char DevicePath[512]"
Const $tagSP_CLASSIMAGE_DATA = "dword Size;hWnd ImageList;dword Reserved"
Const $tagSP_DRVINSTALL_PARAMS = "dword Size;dword Rank;dword Flags;long_ptr PrivateData;dword Reserved"
Const $tagSP_INF_SIGNER_INFO = "dword Size;wchar CatalogFile[260];wchar DigitalSigner[260];wchar DigitalSignerVersion[260]"
; ==============================================================================

; #### Device Interface Classes ####
; ==============================================================================
; #### Device Interface Classes for Modem Devices ####
; ==============================================================================
Const $GUID_DEVINTERFACE_MODEM = "{2C7089AA-2E0E-11D1-B114-00C04FC2AAE4}"
; ==============================================================================

; #### Device Interface Classes for Network Devices ####
; ==============================================================================
Const $GUID_DEVINTERFACE_NET = "{CAC88484-7515-4C03-82E6-71A87ABAC361}"
; ==============================================================================

; #### Device Interface Classes for Storage Devices ####
; ==============================================================================
Const $GUID_DEVINTERFACE_CDCHANGER = "{53F56312-B6BF-11D0-94F2-00A0C91EFB8B}"
Const $GUID_DEVINTERFACE_CDROM = "{53F56308-B6BF-11D0-94F2-00A0C91EFB8B}"
Const $GUID_DEVINTERFACE_DISK = "{53F56307-B6BF-11D0-94F2-00A0C91EFB8B}"
Const $GUID_DEVINTERFACE_FLOPPY = "{53F56311-B6BF-11D0-94F2-00A0C91EFB8B}"
Const $GUID_DEVINTERFACE_MEDIUMCHANGER = "{53F56310-B6BF-11D0-94F2-00A0C91EFB8B}"
Const $GUID_DEVINTERFACE_PARTITION = "{53F5630A-B6BF-11D0-94F2-00A0C91EFB8B}"
Const $GUID_DEVINTERFACE_STORAGEPORT = "{2ACCFE60-C130-11D2-B082-00A0C91EFB8B}"
Const $GUID_DEVINTERFACE_TAPE = "{53F5630B-B6BF-11D0-94F2-00A0C91EFB8B}"
Const $GUID_DEVINTERFACE_VOLUME = "{53F5630D-B6BF-11D0-94F2-00A0C91EFB8B}"
Const $GUID_DEVINTERFACE_WRITEONCEDISK = "{53F5630C-B6BF-11D0-94F2-00A0C91EFB8B}"
; ==============================================================================

; #### Device Interface Classes for USB Devices ####
; ==============================================================================
Const $GUID_DEVINTERFACE_USB_HUB = "{F18A0E88-C30C-11D0-8815-00A0C906BED8}"
Const $GUID_DEVINTERFACE_USB_HOST_CONTROLLER = "{3ABF6F2D-71C4-462A-8A92-1E6861E6AF27}"
Const $GUID_DEVINTERFACE_USB_DEVICE = "{A5DCBF10-6530-11D2-901F-00C04FB951ED}"
Const $GUID_DEVINTERFACE_USBSTOR = "{A5DCBF10-6530-11D2-901F-00C04FB951ED}"
; ==============================================================================

; #### Device Interface Classes for Display and Image Devices ####
; ==============================================================================
Const $GUID_DEVINTERFACE_BRIGHTNESS = "{FDE5BBA4-B3F9-46FB-BDAA-0728CE3100B4}"
Const $GUID_DEVINTERFACE_DISPLAY_ADAPTER = "{5B45201D-F2F2-4F3B-85BB-30FF1F953599}"
Const $GUID_DEVINTERFACE_I2C = "{2564AA4F-DDDB-4495-B497-6AD4A84163D7}"
Const $GUID_DEVINTERFACE_IMAGE = "{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}"
Const $GUID_DEVINTERFACE_MONITOR = "{E6F07B5F-EE97-4a90-B076-33F57BF4EAA7}"
Const $GUID_DEVINTERFACE_OPM = "{BF4672DE-6B4E-4BE4-A325-68A91EA49C09}"
Const $GUID_DEVINTERFACE_VIDEO_OUTPUT_ARRIVAL = "{1AD9E4F0-F88D-4360-BAB9-4C2D55E564CD}"
; ==============================================================================

; #### Device Interface Classes for Interactive Input Devices ####
; ==============================================================================
Const $GUID_DEVINTERFACE_HID = "{4D1E55B2-F16F-11CF-88CB-001111000030}"
Const $GUID_DEVINTERFACE_KEYBOARD = "{884B96C3-56EF-11D1-BC8C-00A0C91405DD}"
Const $GUID_DEVINTERFACE_MOUSE = "{378DE44C-56EF-11D1-BC8C-00A0C91405DD}"
; ==============================================================================

; #### Device Interface Classes for Bluetooth Devices ####
; ==============================================================================
Const $GUID_BTHPORT_DEVICE_INTERFACE = "{0850302A-B344-4fda-9BE9-90576B8D46F0}"
; ==============================================================================

; #### Device Interface Classes for Battery, Disk Manager, 1394 Host Controller ... #### (??)
; ==============================================================================
Const $GUID_DEVINTERFACE_DVD = "{1186654d-47b8-48b9-beb9-7df113ae3c67}" ; ??
Const $GUID_DEVINTERFACE_FLASHMEDIA = "{2c9f2281-eb3c-11d6-80af-0001020c74d4}"
Const $GUID_DEVINTERFACE_SYSTEM_BUTTON = "{4afa3d53-74a7-11d0-be5e-00a0c9062857}"
Const $GUID_DEVINTERFACE_DISKDRIVE = "{53f5630e-b6bf-11d0-94f2-00a0c91efb8b}"
Const $GUID_DEVINTERFACE_HDAUDIO = "{54c9343c-2a17-42e8-b4fd-9f9da27b94d6}"
Const $GUID_DEVINTERFACE_AUDIO_ADAPTER = "{65E8773D-8F56-11D0-A3B9-00A0C9223196}"
Const $GUID_DEVINTERFACE_IEEE_1394_HOST_CONTROLLER = "{6bdd1fc1-810f-11d0-bec7-08002be2092f}"
Const $GUID_DEVINTERFACE_BATTERY = "{72631e54-78a4-11d0-bcf7-00aa00b7b32a}"
Const $GUID_DEVINTERFACE_STD_MODEM = "{86e0d1e0-8089-11d0-9ce4-08003e301f73}"
Const $GUID_DEVINTERFACE_PROCESSOR = "{97fadb10-4e33-40ae-359c-8bef029dbdd0}"
Const $GUID_DEVINTERFACE_NDIS = "{ad498944-762f-11d0-8dcb-00c04fc3358c}"
Const $GUID_DEVINTERFACE_HDAUDIO_MODEM = "{adb44c00-1b8d-11d4-8d5e-00a0c90d1c42}"

; ==============================================================================

; #### Device Interface Classes for Battery and ACPI Devices
; ==============================================================================
Const $GUID_DEVICE_APPLICATIONLAUNCH_BUTTON = "{629758EE-986E-4D9E-8E47-DE27F8AB054D}"
Const $GUID_DEVICE_BATTERY = "{72631E54-78A4-11D0-BCF7-00AA00B7B32A}"
Const $GUID_DEVICE_LID = "{4AFA3D52-74A7-11d0-be5e-00A0C9062857}"
Const $GUID_DEVICE_MEMORY = "{3FD0F03D-92E0-45FB-B75C-5ED8FFB01021}"
Const $GUID_DEVICE_MESSAGE_INDICATOR = "{CD48A365-FA94-4CE2-A232-A1B764E5D8B4}"
Const $GUID_DEVICE_PROCESSOR = "{97FADB10-4E33-40AE-359C-8BEF029DBDD0}"
Const $GUID_DEVICE_SYS_BUTTON = "{4AFA3D53-74A7-11d0-be5e-00A0C9062857}"
Const $GUID_DEVICE_THERMAL_ZONE = "{4AFA3D51-74A7-11d0-be5e-00A0C9062857}"
; ==============================================================================

; #### Resource Descriptor Structures ####
; ==============================================================================
Const $tagDMA_DES = "dword Count;dword Type;dword Flags;ulong AllocChannel"
Const $tagIO_DES = "dword Count;dword Type;int64 AllocBase;int64 AllocEnd;dword Flags"
Const $tagMEM_DES = $tagIO_DES & ";dword Reserved"
Const $tagIRQ_DES = "dword Count;dword Type;dword Flags;ulong AllocNum;ulong Affinity"
Const $tagBUSNUMBER_DES = "dword Count;dword Type;dword Flags;ulong AllocBase;ulong AllocEnd"
Const $tagMFCARD_DES = "dword Count;dword Type;dword Flags;byte ConfigOptions;byte IoResIndex;byte Reserved[2];dword ConfigRegisterBase"
Const $tagPCCARD_DES = "dword Count;dword Type;dword Flags;byte ConfigIndex;byte Reserved[3];dword MemCardBase1;dword MemCardBase2"
Const $tagCS_DES = "dword SignatureLength;dword LegacyDataOffset;dword LegacyDataSize;dword Flags;byte Guid[16]"
Const $tagCONFLICT_DETAILS = "ulong Size;ulong Mask;dword DevInst;int ResDes;ulong Flags;char Descr[260]"
; ==============================================================================

; #### Device Power State Constants ####
; ==============================================================================
Const $PDCAP_D0_SUPPORTED = 1
Const $PDCAP_D1_SUPPORTED = 2
Const $PDCAP_D2_SUPPORTED = 4
Const $PDCAP_D3_SUPPORTED = 8
Const $PDCAP_S0_SUPPORTED = 0x10000
Const $PDCAP_S1_SUPPORTED = 0x20000
Const $PDCAP_S2_SUPPORTED = 0x40000
Const $PDCAP_S3_SUPPORTED = 0x80000
Const $PDCAP_S4_SUPPORTED = 0x1000000
Const $PDCAP_S5_SUPPORTED = 0x2000000
Const $PDCAP_WAKE_FROM_D0_SUPPORTED = 0x10
Const $PDCAP_WAKE_FROM_D1_SUPPORTED = 0x20
Const $PDCAP_WAKE_FROM_D2_SUPPORTED = 0x40
Const $PDCAP_WAKE_FROM_D3_SUPPORTED = 0x80
Const $PDCAP_WAKE_FROM_S0_SUPPORTED = 0x100000
Const $PDCAP_WAKE_FROM_S1_SUPPORTED = 0x200000
Const $PDCAP_WAKE_FROM_S2_SUPPORTED = 0x400000
Const $PDCAP_WAKE_FROM_S3_SUPPORTED = 0x800000
Const $PDCAP_WARM_EJECT_SUPPORTED = 0x100
; ==============================================================================

; #### Flags for the SPDRP_CONFIGFLAGS in SetupDiGetDeviceRegistryProperty ####
; ==============================================================================
Const $CONFIGFLAG_DISABLED = 0x00000001 ; Set if disabled
Const $CONFIGFLAG_REMOVED = 0x00000002 ; Set if a present hardware enum device deleted
Const $CONFIGFLAG_MANUAL_INSTALL = 0x00000004 ; Set if the devnode was manually installed
Const $CONFIGFLAG_IGNORE_BOOT_LC = 0x00000008 ; Set if skip the boot config
Const $CONFIGFLAG_NET_BOOT = 0x00000010 ; Load this devnode when in net boot
Const $CONFIGFLAG_REINSTALL = 0x00000020 ; Redo install
Const $CONFIGFLAG_FAILEDINSTALL = 0x00000040 ; Failed the install
Const $CONFIGFLAG_CANTSTOPACHILD = 0x00000080 ; Can't stop/remove a single child
Const $CONFIGFLAG_OKREMOVEROM = 0x00000100 ; Can remove even if rom.
Const $CONFIGFLAG_NOREMOVEEXIT = 0x00000200 ; Don't remove at exit.
Const $CONFIGFLAG_FINISH_INSTALL = 0x00000400 ; Complete install for devnode running 'raw'
Const $CONFIGFLAG_NEEDS_FORCED_CONFIG = 0x00000800 ; This devnode requires a forced config

Const $CSCONFIGFLAG_BITS = 0x00000007 ; OR of below bits
Const $CSCONFIGFLAG_NONE = 0
Const $CSCONFIGFLAG_DISABLED = 0x00000001 ; Set if
Const $CSCONFIGFLAG_DO_NOT_CREATE = 0x00000002 ; Set if
Const $CSCONFIGFLAG_DO_NOT_START = 0x00000004 ; Set if
; ==============================================================================

; #### Device Registry Key Constants ####
; ==============================================================================
Const $REGKEY_HARDWARE_CS001_001 = "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Hardware Profiles\0001\System\CurrentControlSet\Enum\"
Const $REGKEY_HARDWARE_CS002_001 = "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Hardware Profiles\0001\System\CurrentControlSet\Enum\"
Const $REGKEY_HARDWARE_CS002_CURRENT = "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Hardware Profiles\Current\System\CurrentControlSet\Enum\"
Const $REGKEY_HARDWARE_CCS_001 = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Hardware Profiles\0001\System\CurrentControlSet\Enum\"
Const $REGKEY_HARDWARE_CCS_CURRENT = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Enum\"
Const $REGKEY_HARDWARE_CS002_ENUM = "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Enum\"

; ==============================================================================

; #### Device Registry Property Structure(s) ####
; ==============================================================================
Const $tagCM_POWER_DATA = "ulong Size;int MostRecentPowerState;ulong Capabilities;ulong D1Latency;ulong D2Latency;ulong D3Latency;int PowerStateMapping[7];int DeepestSystemWake"
Const $tagHWPROFILE_INFO = "ulong HWProfile;char FriendlyName[80];dword Flags"
; ==============================================================================

; #### Configuration Priority Value ####
; ==============================================================================
Const $LCPRI_FORCECONFIG = 0x00000000 ; Coming from a forced config
Const $LCPRI_BOOTCONFIG = 0x00000001  ; Coming from a boot config
Const $LCPRI_DESIRED = 0x00002000  ; Preferable (better performance)
Const $LCPRI_NORMAL = 0x00003000  ; Workable (acceptable performance)
Const $LCPRI_LASTBESTCONFIG = 0x00003FFF  ; CM only--do not use
Const $LCPRI_SUBOPTIMAL = 0x00005000 ;  Not desired, but will work
Const $LCPRI_LASTSOFTCONFIG = 0x00007FFF  ; CM only--do not use
Const $LCPRI_RESTART = 0x00008000 ;  Need to restart
Const $LCPRI_REBOOT = 0x00009000  ; Need to reboot
Const $LCPRI_POWEROFF = 0x0000A000 ;  Need to shutdown/power-off
Const $LCPRI_HARDRECONFIG = 0x0000C000 ;  Need to change a jumper
Const $LCPRI_HARDWIRED = 0x0000E000 ;   Cannot be changed
Const $LCPRI_IMPOSSIBLE = 0x0000F000  ; Impossible configuration
Const $LCPRI_DISABLED = 0x0000FFFF  ; Disabled configuration
Const $MAX_LCPRI = 0x0000FFFF ;  Maximum known LC Priority
; ==============================================================================

; #### Device Manager Error Code ####
; ==============================================================================
Const $CM_PROB_NOT_CONFIGURED = 0x00000001 ; no config for device
Const $CM_PROB_DEVLOADER_FAILED = 0x00000002 ; service load failed
Const $CM_PROB_OUT_OF_MEMORY = 0x00000003 ; out of memory
Const $CM_PROB_ENTRY_IS_WRONG_TYPE = 0x00000004 ;
Const $CM_PROB_LACKED_ARBITRATOR = 0x00000005 ;
Const $CM_PROB_BOOT_CONFIG_CONFLICT = 0x00000006 ; boot config conflict
Const $CM_PROB_FAILED_FILTER = 0x00000007 ;
Const $CM_PROB_DEVLOADER_NOT_FOUND = 0x00000008 ; Devloader not found
Const $CM_PROB_INVALID_DATA = 0x00000009 ;
Const $CM_PROB_FAILED_START = 0x0000000A ;
Const $CM_PROB_LIAR = 0x0000000B ;
Const $CM_PROB_NORMAL_CONFLICT = 0x0000000C ; config conflict
Const $CM_PROB_NOT_VERIFIED = 0x0000000D ;
Const $CM_PROB_NEED_RESTART = 0x0000000E ; requires restart
Const $CM_PROB_REENUMERATION = 0x0000000F ;
Const $CM_PROB_PARTIAL_LOG_CONF = 0x00000010 ;
Const $CM_PROB_UNKNOWN_RESOURCE = 0x00000011 ; unknown res type
Const $CM_PROB_REINSTALL = 0x00000012 ;
Const $CM_PROB_REGISTRY = 0x00000013 ;
Const $CM_PROB_VXDLDR = 0x00000014 ; WINDOWS 95 ONLY
Const $CM_PROB_WILL_BE_REMOVED = 0x00000015 ; devinst will remove
Const $CM_PROB_DISABLED = 0x00000016 ; devinst is disabled
Const $CM_PROB_DEVLOADER_NOT_READY = 0x00000017 ; Devloader not ready
Const $CM_PROB_DEVICE_NOT_THERE = 0x00000018 ; device doesn't exist
Const $CM_PROB_MOVED = 0x00000019 ;
Const $CM_PROB_TOO_EARLY = 0x0000001A ;
Const $CM_PROB_NO_VALID_LOG_CONF = 0x0000001B ; no valid log config
Const $CM_PROB_FAILED_INSTALL = 0x0000001C ; install failed
Const $CM_PROB_HARDWARE_DISABLED = 0x0000001D ; device disabled
Const $CM_PROB_CANT_SHARE_IRQ = 0x0000001E ; can't share IRQ
Const $CM_PROB_FAILED_ADD = 0x0000001F ; driver failed add
Const $CM_PROB_DISABLED_SERVICE = 0x00000020 ; service's Start = 4
Const $CM_PROB_TRANSLATION_FAILED = 0x00000021 ; resource translation failed
Const $CM_PROB_NO_SOFTCONFIG = 0x00000022 ; no soft config
Const $CM_PROB_BIOS_TABLE = 0x00000023 ; device missing in BIOS table
Const $CM_PROB_IRQ_TRANSLATION_FAILED = 0x00000024 ; IRQ translator failed
Const $CM_PROB_FAILED_DRIVER_ENTRY = 0x00000025 ; DriverEntry() failed.
Const $CM_PROB_DRIVER_FAILED_PRIOR_UNLOAD = 0x00000026 ; Driver should have unloaded.
Const $CM_PROB_DRIVER_FAILED_LOAD = 0x00000027 ; Driver load unsuccessful.
Const $CM_PROB_DRIVER_SERVICE_KEY_INVALID = 0x00000028 ; Error accessing driver's service key
Const $CM_PROB_LEGACY_SERVICE_NO_DEVICES = 0x00000029 ; Loaded legacy service created no devices
Const $CM_PROB_DUPLICATE_DEVICE = 0x0000002A ; Two devices were discovered with the same name
Const $CM_PROB_FAILED_POST_START = 0x0000002B ; The drivers set the device state to failed
Const $CM_PROB_HALTED = 0x0000002C ; This device was failed post start via usermode
Const $CM_PROB_PHANTOM = 0x0000002D ; The devinst currently exists only in the registry
Const $CM_PROB_SYSTEM_SHUTDOWN = 0x0000002E ; The system is shutting down
Const $CM_PROB_HELD_FOR_EJECT = 0x0000002F ; The device is offline awaiting removal
Const $CM_PROB_DRIVER_BLOCKED = 0x00000030 ; One or more drivers is blocked from loading
Const $CM_PROB_REGISTRY_TOO_LARGE = 0x00000031 ; System hive has grown too large
Const $NUM_CM_PROB = 0x00000032;
; ==============================================================================

; #### Flags for _CM_Locate_DevNode ####
; ====================================================================================
Const $CM_LOCATE_DEVNODE_NORMAL = 0x00000000
Const $CM_LOCATE_DEVNODE_PHANTOM = 0x00000001
Const $CM_LOCATE_DEVNODE_CANCELREMOVE = 0x00000002
Const $CM_LOCATE_DEVNODE_NOVALIDATION = 0x00000004
Const $CM_LOCATE_DEVNODE_BITS = 0x00000007
Const $CM_LOCATE_DEVINST_NORMAL = $CM_LOCATE_DEVNODE_NORMAL
Const $CM_LOCATE_DEVINST_PHANTOM = $CM_LOCATE_DEVNODE_PHANTOM
Const $CM_LOCATE_DEVINST_CANCELREMOVE = $CM_LOCATE_DEVNODE_CANCELREMOVE
Const $CM_LOCATE_DEVINST_NOVALIDATION = $CM_LOCATE_DEVNODE_NOVALIDATION
Const $CM_LOCATE_DEVINST_BITS = $CM_LOCATE_DEVNODE_BITS
; ====================================================================================

; #### Flags for _CM_Get_Device_ID_List, _CM_Get_Device_ID_List_Size ####
; ====================================================================================
Const $CM_GETIDLIST_FILTER_NONE = 0x00000000
Const $CM_GETIDLIST_FILTER_ENUMERATOR = 0x00000001
Const $CM_GETIDLIST_FILTER_SERVICE = 0x00000002
Const $CM_GETIDLIST_FILTER_EJECTRELATIONS = 0x00000004
Const $CM_GETIDLIST_FILTER_REMOVALRELATIONS = 0x00000008
Const $CM_GETIDLIST_FILTER_POWERRELATIONS = 0x00000010
Const $CM_GETIDLIST_FILTER_BUSRELATIONS = 0x00000020
Const $CM_GETIDLIST_DONOTGENERATE = 0x10000040
Const $CM_GETIDLIST_FILTER_BITS = 0x1000007F
; ====================================================================================

; #### Flags for CM_Get_Device_Interface_List, CM_Get_Device_Interface_List_Size ####
; ====================================================================================
Const $CM_GET_DEVICE_INTERFACE_LIST_PRESENT = 0x00000000 ; only currently 'live' device interfaces
Const $CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES = 0x00000001 ; all registered device interfaces
Const $CM_GET_DEVICE_INTERFACE_LIST_BITS = 0x00000001
; ====================================================================================

; #### Flags for _CM_Reenumerate_DevNode ####
; ====================================================================================
Const $CM_REENUMERATE_NORMAL = 0x00000000
Const $CM_REENUMERATE_SYNCHRONOUS = 0x00000001
Const $CM_REENUMERATE_BITS = 0x00000001
; ====================================================================================

; #### Flags for _CM_Query_And_Remove_SubTree ####
; ====================================================================================
Const $CM_REMOVE_UI_OK = 0x00000000
Const $CM_REMOVE_UI_NOT_OK = 0x00000001
Const $CM_REMOVE_NO_RESTART = 0x00000002
Const $CM_REMOVE_BITS = 0x00000003
; ====================================================================================

; #### Flags for _CM_Add_ID ####
; ====================================================================================
Const $CM_ADD_ID_HARDWARE = 0x00000000
Const $CM_ADD_ID_COMPATIBLE = 0x00000001
Const $CM_ADD_ID_BITS = 0x00000001
; ====================================================================================

; #### Flags for _CM_Get_First_Log_Conf ####
; ====================================================================================
Const $BASIC_LOG_CONF = 0x00000000 ; Specifies the req list.
Const $FILTERED_LOG_CONF = 0x00000001 ; Specifies the filtered req list.
Const $ALLOC_LOG_CONF = 0x00000002 ; Specifies the Alloc Element.
Const $BOOT_LOG_CONF = 0x00000003 ; Specifies the RM Alloc Element.
Const $FORCED_LOG_CONF = 0x00000004 ; Specifies the Forced Log Conf
Const $OVERRIDE_LOG_CONF = 0x00000005 ; Specifies the Override req list.
Const $NUM_LOG_CONF = 0x00000006 ; Number of Log Conf type
Const $LOG_CONF_BITS = 0x00000007 ; The bits of the log conf type.
; =====================================================================================

; #### Property for _SetupDiGetDeviceRegistryProperty ####
; ==============================================================================
Const $SPDRP_DEVICEDESC = 0x00000000 ; DeviceDesc (R/W)
Const $SPDRP_HARDWAREID = 0x00000001 ; HardwareID (R/W)
Const $SPDRP_COMPATIBLEIDS = 0x00000002 ; CompatibleIDs (R/W)
Const $SPDRP_NTDEVICEPATHS = 0x00000003 ; Unsupported, DO NOT USE
Const $SPDRP_SERVICE = 0x00000004 ; Service (R/W)
Const $SPDRP_CONFIGURATION = 0x00000005 ; Configuration (R)
Const $SPDRP_CONFIGURATIONVECTOR = 0x00000006 ; ConfigurationVector (R)
Const $SPDRP_CLASS = 0x00000007 ; Class (R)--tied to ClassGUID
Const $SPDRP_CLASSGUID = 0x00000008 ; ClassGUID (R/W)
Const $SPDRP_DRIVER = 0x00000009 ; Driver (R/W)
Const $SPDRP_CONFIGFLAGS = 0x0000000A ; ConfigFlags (R/W)
Const $SPDRP_MFG = 0x0000000B ; Mfg (R/W)
Const $SPDRP_FRIENDLYNAME = 0x0000000C ; FriendlyName (R/W)
Const $SPDRP_LOCATION_INFORMATION = 0x0000000D ; LocationInformation (R/W)
Const $SPDRP_PHYSICAL_DEVICE_OBJECT_NAME = 0x0000000E ; PhysicalDeviceObjectName (R)
Const $SPDRP_CAPABILITIES = 0x0000000F ; Capabilities (R)
Const $SPDRP_UI_NUMBER = 0x00000010 ; UiNumber (R)
Const $SPDRP_UPPERFILTERS = 0x00000011 ; UpperFilters (R/W)
Const $SPDRP_LOWERFILTERS = 0x00000012 ; LowerFilters (R/W)
Const $SPDRP_MAXIMUM_PROPERTY = 0x00000013 ; Upper bound on ordinals
Const $SPDRP_REMOVAL_POLICY = 0x1F
Const $SPDRP_REMOVAL_POLICY_HW_DEFAULT = 0x20
; ==============================================================================

; #### Removal policies (retrievable via _SetupDiGetDeviceRegistryProperty with
; the SPDRP_REMOVAL_POLICY, or SPDRP_REMOVAL_POLICY_HW_DFAULT properties) ####
; ====================================================================================
Const $CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL = 1
Const $CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL = 2
Const $CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL = 3
; ====================================================================================

; Re-enable and configuration actions (specified in call to _CM_Setup_DevInst)
; ===================================================================================
Const $CM_SETUP_DEVNODE_READY = 0x00000000; Reenable problem devinst
Const $CM_SETUP_DEVINST_READY = $CM_SETUP_DEVNODE_READY
Const $CM_SETUP_DOWNLOAD = 0x00000001; Get info about devinst
Const $CM_SETUP_WRITE_LOG_CONFS = 0x00000002
Const $CM_SETUP_PROP_CHANGE = 0x00000003
Const $CM_SETUP_DEVNODE_RESET = 0x00000004; Reset problem devinst without starting
Const $CM_SETUP_DEVINST_RESET = $CM_SETUP_DEVNODE_RESET
Const $CM_SETUP_BITS = 0x00000007
; ===================================================================================

; #### Flags for _CM_Set_DevNode_Problem ####
; ====================================================================================
Const $CM_SET_DEVNODE_PROBLEM_NORMAL = 0x00000000 ; only set problem if currently no problem
Const $CM_SET_DEVNODE_PROBLEM_OVERRIDE = 0x00000001 ; override current problem with new.
Const $CM_SET_DEVNODE_PROBLEM_BITS = 0x00000001
Const $CM_SET_DEVINST_PROBLEM_NORMAL = $CM_SET_DEVNODE_PROBLEM_NORMAL
Const $CM_SET_DEVINST_PROBLEM_OVERRIDE = $CM_SET_DEVNODE_PROBLEM_OVERRIDE
Const $CM_SET_DEVINST_PROBLEM_BITS = $CM_SET_DEVNODE_PROBLEM_BITS
; ====================================================================================

; #### DIF (device installation function) code ####
; ====================================================================================
Const $DIF_SELECTDEVICE   = 0x00000001
Const $DIF_INSTALLDEVICE           = 0x00000002
Const $DIF_ASSIGNRESOURCES         = 0x00000003
Const $DIF_PROPERTIES     = 0x00000004
Const $DIF_REMOVE         = 0x00000005
Const $DIF_FIRSTTIMESETUP          = 0x00000006
Const $DIF_FOUNDDEVICE    = 0x00000007
Const $DIF_SELECTCLASSDRIVERS      = 0x00000008
Const $DIF_VALIDATECLASSDRIVERS    = 0x00000009
Const $DIF_INSTALLCLASSDRIVERS     = 0x0000000A
Const $DIF_CALCDISKSPACE           = 0x0000000B
Const $DIF_DESTROYPRIVATEDATA      = 0x0000000C
Const $DIF_VALIDATEDRIVER          = 0x0000000D
Const $DIF_MOVEDEVICE     = 0x0000000E
Const $DIF_DETECT         = 0x0000000F
Const $DIF_INSTALLWIZARD           = 0x00000010
Const $DIF_DESTROYWIZARDDATA       = 0x00000011
Const $DIF_PROPERTYCHANGE          = 0x00000012
Const $DIF_ENABLECLASS    = 0x00000013
Const $DIF_DETECTVERIFY   = 0x00000014
Const $DIF_INSTALLDEVICEFILES      = 0x00000015
Const $DIF_UNREMOVE       = 0x00000016
Const $DIF_SELECTBESTCOMPATDRV     = 0x00000017
Const $DIF_ALLOW_INSTALL           = 0x00000018
Const $DIF_REGISTERDEVICE          = 0x00000019
Const $DIF_INSTALLINTERFACES       = 0x00000020
Const $DIF_DETECTCANCEL   = 0x00000021
Const $DIF_REGISTER_COINSTALLERS   = 0x00000022
Const $DIF_POWERMESSAGEWAKE = 0x27
; ====================================================================================

; #### Configuration Manager return status codes ####
; ====================================================================================
Const $CR_SUCCESS = 0x00000000
Const $CR_DEFAULT = 0x00000001
Const $CR_OUT_OF_MEMORY = 0x00000002
Const $CR_INVALID_POINTER = 0x00000003
Const $CR_INVALID_FLAG = 0x00000004
Const $CR_INVALID_DEVNODE = 0x00000005
Const $CR_INVALID_DEVINST = $CR_INVALID_DEVNODE
Const $CR_INVALID_RES_DES = 0x00000006
Const $CR_INVALID_LOG_CONF = 0x00000007
Const $CR_INVALID_ARBITRATOR = 0x00000008
Const $CR_INVALID_NODELIST = 0x00000009
Const $CR_DEVNODE_HAS_REQS = 0x0000000A
Const $CR_DEVINST_HAS_REQS = $CR_DEVNODE_HAS_REQS
Const $CR_INVALID_RESOURCEID = 0x0000000B
Const $CR_DLVXD_NOT_FOUND = 0x0000000C ; WIN 95 ONLY
Const $CR_NO_SUCH_DEVNODE = 0x0000000D
Const $CR_NO_SUCH_DEVINST = $CR_NO_SUCH_DEVNODE
Const $CR_NO_MORE_LOG_CONF = 0x0000000E
Const $CR_NO_MORE_RES_DES = 0x0000000F
Const $CR_ALREADY_SUCH_DEVNODE = 0x00000010
Const $CR_ALREADY_SUCH_DEVINST = $CR_ALREADY_SUCH_DEVNODE
Const $CR_INVALID_RANGE_LIST = 0x00000011
Const $CR_INVALID_RANGE = 0x00000012
Const $CR_FAILURE = 0x00000013
Const $CR_NO_SUCH_LOGICAL_DEV = 0x00000014
Const $CR_CREATE_BLOCKED = 0x00000015
Const $CR_NOT_SYSTEM_VM = 0x00000016 ; WIN 95 ONLY
Const $CR_REMOVE_VETOED = 0x00000017
Const $CR_APM_VETOED = 0x00000018
Const $CR_INVALID_LOAD_TYPE = 0x00000019
Const $CR_BUFFER_SMALL = 0x0000001A
Const $CR_NO_ARBITRATOR = 0x0000001B
Const $CR_NO_REGISTRY_HANDLE = 0x0000001C
Const $CR_REGISTRY_ERROR = 0x0000001D
Const $CR_INVALID_DEVICE_ID = 0x0000001E
Const $CR_INVALID_DATA = 0x0000001F
Const $CR_INVALID_API = 0x00000020
Const $CR_DEVLOADER_NOT_READY = 0x00000021
Const $CR_NEED_RESTART = 0x00000022
Const $CR_NO_MORE_HW_PROFILES = 0x00000023
Const $CR_DEVICE_NOT_THERE = 0x00000024
Const $CR_NO_SUCH_VALUE = 0x00000025
Const $CR_WRONG_TYPE = 0x00000026
Const $CR_INVALID_PRIORITY = 0x00000027
Const $CR_NOT_DISABLEABLE = 0x00000028
Const $CR_FREE_RESOURCES = 0x00000029
Const $CR_QUERY_VETOED = 0x0000002A
Const $CR_CANT_SHARE_IRQ = 0x0000002B
Const $CR_NO_DEPENDENT = 0x0000002C
Const $CR_SAME_RESOURCES = 0x0000002D
Const $CR_NO_SUCH_REGISTRY_KEY = 0x0000002E
Const $CR_INVALID_MACHINENAME = 0x0000002F ; NT ONLY
Const $CR_REMOTE_COMM_FAILURE = 0x00000030 ; NT ONLY
Const $CR_MACHINE_UNAVAILABLE = 0x00000031 ; NT ONLY
Const $CR_NO_CM_SERVICES = 0x00000032 ; NT ONLY
Const $CR_ACCESS_DENIED = 0x00000033 ; NT ONLY
Const $CR_CALL_NOT_IMPLEMENTED = 0x00000034
Const $CR_INVALID_PROPERTY = 0x00000035
Const $CR_DEVICE_INTERFACE_ACTIVE = 0x00000036
Const $CR_NO_SUCH_DEVICE_INTERFACE = 0x00000037
Const $CR_INVALID_REFERENCE_STRING = 0x00000038
Const $CR_INVALID_CONFLICT_LIST = 0x00000039
Const $CR_INVALID_INDEX = 0x0000003A
Const $CR_INVALID_STRUCTURE_SIZE = 0x0000003B
Const $NUM_CR_RESULTS = 0x0000003C
; ====================================================================================

; #### Resource Type for _CM_Get_Next_Res_Des ####
; ====================================================================================
Const $RESTYPE_ALL = 0x00000000 ; Return all resource types
Const $RESTYPE_NONE = 0x00000000 ; Arbitration always succeeded
Const $RESTYPE_MEM = 0x00000001 ; Physical address resource
Const $RESTYPE_IO = 0x00000002 ; Physical I/O address resource
Const $RESTYPE_DMA = 0x00000003 ; DMA channels resource
Const $RESTYPE_IRQ = 0x00000004 ; IRQ resource
Const $RESTYPE_DONOTUSE = 0x00000005 ; Used as spacer to sync subsequent ResTypes w/NT
Const $RESTYPE_BUSNUMBER = 0x00000006 ; bus number resource
Const $RESTYPE_MAX = 0x00000006 ; Maximum known (arbitrated ResType
Const $RESTYPE_IGNORED_BIT = 0x00008000 ; Ignore this resource
Const $RESTYPE_CLASSSPECIFIC = 0x0000FFFF ; class-specific resource
Const $RESTYPE_RESERVED = 0x00008000 ; reserved for internal use
Const $RESTYPE_DEVICEPRIVAT = 0x00008001 ; device private data
Const $RESTYPE_PCCARDCONFIG = 0x00008002 ; PC Card configuration data
Const $RESTYPE_MFCARDCONFIG = 0x00008003 ; MF Card configuration data
; ====================================================================================

; #### Registry properties for device instance ####
; =====================================================================================
Const $CM_DRP_DEVICEDESC = 0x00000001 ; DeviceDesc REG_SZ property (RW)
Const $CM_DRP_HARDWAREID = 0x00000002 ; HardwareID REG_MULTI_SZ property (RW)
Const $CM_DRP_COMPATIBLEIDS = 0x00000003 ; CompatibleIDs REG_MULTI_SZ property (RW)
Const $CM_DRP_UNUSED0 = 0x00000004 ; unused
Const $CM_DRP_SERVICE = 0x00000005 ; Service REG_SZ property (RW)
Const $CM_DRP_UNUSED1 = 0x00000006 ; unused
Const $CM_DRP_UNUSED2 = 0x00000007 ; unused
Const $CM_DRP_CLASS = 0x00000008 ; Class REG_SZ property (RW)
Const $CM_DRP_CLASSGUID = 0x00000009 ; ClassGUID REG_SZ property (RW)
Const $CM_DRP_DRIVER = 0x0000000A ; Driver REG_SZ property (RW)
Const $CM_DRP_CONFIGFLAGS = 0x0000000B ; ConfigFlags REG_DWORD property (RW)
Const $CM_DRP_MFG = 0x0000000C ; Mfg REG_SZ property (RW)
Const $CM_DRP_FRIENDLYNAME = 0x0000000D ; FriendlyName REG_SZ property (RW)
Const $CM_DRP_LOCATION_INFORMATION = 0x0000000E ; LocationInformation REG_SZ property (RW)
Const $CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME = 0x0000000F ; PhysicalDeviceObjectName REG_SZ property (R)
Const $CM_DRP_CAPABILITIES = 0x00000010 ; Capabilities REG_DWORD property (R)
Const $CM_DRP_UI_NUMBER = 0x00000011 ; UiNumber REG_DWORD property (R)
Const $CM_DRP_UPPERFILTERS = 0x00000012 ; UpperFilters REG_MULTI_SZ property (RW)
Const $CM_DRP_LOWERFILTERS = 0x00000013 ; LowerFilters REG_MULTI_SZ property (RW)
Const $CM_DRP_BUSTYPEGUID = 0x00000014 ; Bus Type Guid, GUID, (R)
Const $CM_DRP_LEGACYBUSTYPE = 0x00000015 ; Legacy bus type, INTERFACE_TYPE, (R)
Const $CM_DRP_BUSNUMBER = 0x00000016 ; Bus Number, DWORD, (R)
Const $CM_DRP_ENUMERATOR_NAME = 0x00000017 ; Enumerator Name REG_SZ property (R)
Const $CM_DRP_SECURITY = 0x00000018 ; Security - Device override (RW)
Const $CM_CRP_SECURITY = $CM_DRP_SECURITY ; Class default security (RW)
Const $CM_DRP_SECURITY_SDS = 0x00000019 ; Security - Device override (RW)
Const $CM_CRP_SECURITY_SDS = $CM_DRP_SECURITY_SDS ; Class default security (RW)
Const $CM_DRP_DEVTYPE = 0x0000001A ; Device Type - Device override (RW)
Const $CM_CRP_DEVTYPE = $CM_DRP_DEVTYPE ; Class default Device-type (RW)
Const $CM_DRP_EXCLUSIVE = 0x0000001B ; Exclusivity - Device override (RW)
Const $CM_CRP_EXCLUSIVE = $CM_DRP_EXCLUSIVE ; Class default (RW)
Const $CM_DRP_CHARACTERISTICS = 0x0000001C ; Characteristics - Device Override (RW)
Const $CM_CRP_CHARACTERISTICS = $CM_DRP_CHARACTERISTICS ; Class default (RW)
Const $CM_DRP_ADDRESS = 0x0000001D ; Device Address (R)
Const $CM_DRP_UI_NUMBER_DESC_FORMAT = 0x0000001E ; UINumberDescFormat REG_SZ property (RW)
Const $CM_DRP_DEVICE_POWER_DATA = 0x0000001F ; CM_POWER_DATA REG_BINARY property (R)
Const $CM_DRP_REMOVAL_POLICY = 0x00000020 ; CM_DEVICE_REMOVAL_POLICY REG_DWORD (R)
Const $CM_DRP_REMOVAL_POLICY_HW_DEFAULT = 0x00000021 ; CM_DRP_REMOVAL_POLICY_HW_DEFAULT REG_DWORD (R)
Const $CM_DRP_REMOVAL_POLICY_OVERRIDE = 0x00000022 ; CM_DRP_REMOVAL_POLICY_OVERRIDE REG_DWORD (RW)
Const $CM_DRP_INSTALL_STATE = 0x00000023 ; CM_DRP_INSTALL_STATE REG_DWORD (R)
Const $CM_DRP_MIN = 0x00000001 ; First device register
Const $CM_CRP_MIN = $CM_DRP_MIN ; First class register
Const $CM_DRP_MAX = 0x00000023 ; Last device register
Const $CM_CRP_MAX = $CM_DRP_MAX ; Last class register
; =====================================================================================

; #### Flags for MEM_DES.Flags ####
; =====================================================================================
Const $MMD_MemoryType = 0x1 ; Bitmask, whether memory is writable
Const $FMD_MemoryType = $MMD_MemoryType ; compatibility
Const $FMD_ROM = 0x0 ; Memory range is read-only
Const $FMD_RAM = 0x1 ; Memory range may be written to

Const $MMD_32_24 = 0x2 ; Bitmask, memory is 24 or 32-bit
Const $FMD_32_24 = $MMD_32_24 ; compatibility
Const $FMD_24 = 0x0 ; Memory range is 24-bit
Const $FMD_32 = 0x2 ; Memory range is 32-bit

Const $MMD_Prefetchable = 0x4 ; Bitmask,whether memory prefetchable
Const $FMD_Prefetchable = $MMD_Prefetchable ; compatibility
Const $FMD_Pref = $MMD_Prefetchable ; compatibility
Const $FMD_PrefetchDisallowed = 0x0 ; Memory range is not prefetchable
Const $FMD_PrefetchAllowed = 0x4 ; Memory range is prefetchable

Const $MMD_Readable = 0x8 ; Bitmask,whether memory is readable
Const $FMD_Readable = $MMD_Readable ; compatibility
Const $FMD_ReadAllowed = 0x0 ; Memory range is readable
Const $FMD_ReadDisallowed = 0x8 ; Memory range is write-only

Const $MMD_CombinedWrite = 0x10 ; Bitmask,supports write-behind
Const $FMD_CombinedWrite = $MMD_CombinedWrite ; compatibility
Const $FMD_CombinedWriteDisallowed = 0x0 ; no combined-write caching
Const $FMD_CombinedWriteAllowed = 0x10 ; supports combined-write caching

Const $MMD_Cacheable = 0x20 ; Bitmask,whether memory is cacheable
Const $FMD_NonCacheable = 0x0 ; Memory range is non-cacheable
Const $FMD_Cacheable = 0x20 ; Memory range is cacheable
; =====================================================================================

; #### Flags for CONFLICT_DETAILS.Flags ####
; ====================================================================================
Const $CM_CDFLAGS_DRIVER = 1 ; CONF_DETAILS.Descr reports back legacy driver name
Const $CM_CDFLAGS_ROOT_OWNED = 2 ; CONF_DETAILS.Flags, root owned device
Const $CM_CDFLAGS_RESERVED = 4 ; CONF_DETAILS.Flags specified range is not available for use
; ====================================================================================

; #### Flags for IO_DES.Flags (Port Type Flags) (DWORD) ####
; ====================================================================================
Const $FIOD_MEMORY = 0 ; The device is accessed in memory address space.
Const $FIOD_IO = 1 ; The device is accessed in I/O address space.
; ====================================================================================

; #### Flags for IO_DES.Flags (Decode Flags) (DWORD) ####
; ====================================================================================
Const $FIOD_10_BIT_DECODE = 0x04 ; The device decodes 10 bits of the port address.
Const $FIOD_12_BIT_DECODE = 0x08 ; The device decodes 12 bits of the port address.
Const $FIOD_16_BIT_DECODE = 0x10 ; The device decodes 16 bits of the port address.
Const $FIOD_POSITIVE_DECODE = 0x20 ; The device uses "positive decode" instead of "subtractive decode."
Const $FIOD_DECODE = 0xFC ; Bitmask for the bits within IO_DES.Flags that specify the decode value.
; ====================================================================================

; #### Flags for IRQ_DES.Flags (Sharing Flags) (DWORD) ####
; ====================================================================================
Const $FIRQD_EXCLUSIVE = 0 ; The IRQ line cannot be shared.
Const $FIRQD_SHARE = 1 ; The IRQ line can be shared.
; ====================================================================================

; #### Flags for IRQ_DES.Flags (Triggering Flags) (DWORD) ####
; ====================================================================================
Const $FIRQD_LEVEL = 0 ; The IRQ line is level-triggered.
Const $FIRQD_EDGE = 2 ; The IRQ line is edge-triggered.
; ====================================================================================

; #### Flags for DMA_DES.Flags (DMA Channel Width) ####
; ==============================================================================
Const $MDD_WIDTH = 0x3  ; Bitmask, width of the DMA channel:
Const $FDD_BYTE = 0x0  ; 8-bit DMA channel
Const $FDD_WORD = 0x1  ; 16-bit DMA channel
Const $FDD_DWORD = 0x2  ; 32-bit DMA channel
Const $FDD_BYTE_AND_WORD = 0x3  ; 8-bit and 16-bit DMA channel
; ==============================================================================

; #### Flags for DMA_DES.Flags (Bus Mastering Flags) ####
; ==============================================================================
Const $MDD_BUSMASTER = 0x4  ; Bitmask, whether bus mastering is supported
Const $FDD_NOBUSMASTER = 0x0  ; no bus mastering
Const $FDD_BUSMASTER = 0x4  ; bus mastering
; ==============================================================================

; #### Flags for DMA_DES.Flags (DMA Type Flags) ####
; ==============================================================================
Const $MDD_TYPE = 0x18  ; Bitmask, specifies type of DMA
Const $FDD_TYPESTANDARD = 0x00  ; standard DMA
Const $FDD_TYPEA = 0x08  ; Type-A DMA
Const $FDD_TYPEB = 0x10  ; Type-B DMA
Const $FDD_TYPEF = 0x18  ; Type-F DMA
; ==============================================================================


; #### Return code for _SetupDiVerifyDigitalSinger ####
; ================================================================================
; Indicates that the publisher is trusted because the publisher's certificate is installed in the Trusted Publishers certificate store.
Const $ERROR_AUTHENTICODE_TRUSTED_PUBLISHER = -536870335

; Indicates that trust cannot be automatically established because the publisher's signing certificate is not installed in the trusted publisher certificates store.
; However, this does not necessarily indicate an error. Instead it indicates that the caller must apply a caller-specific policy to establish trust in the publisher.
Const $ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED = -536870334
; ================================================================================

; #### Flags for SP_DRVINSTALL_PARAMS.Flags ####
; =================================================================================
; There are other providers supplying drivers that have the same description as this driver. This flag is READ-ONLY to installers.
Const $DNF_DUPDESC = 1

; This driver currently/previously controlled the associated device. This flag is READ-ONLY to installers.
Const $DNF_OLDDRIVER = 2

; Do not display this driver in any driver-select dialogs.
Const $DNF_EXCLUDEFROMLIST = 4

; Set if no physical driver is to be installed for this logical driver.
Const $DNF_NODRIVER = 8

; This driver comes from a legacy INF file. This flag is valid only for the NT-based operating system. This flag is READ-ONLY to installers.
Const $DNF_LEGACYINF = 0x10

; This driver is a class driver. This flag is read-only to installers.
Const $DNF_CLASS_DRIVER = 0x20

; This driver is a compatible driver. This flag is READ-ONLY to installers.
Const $DNF_COMPATIBLE_DRIVER = 0x40

; This driver came from the Internet or from Windows Update. This flag is READ-ONLY to installers.
Const $DNF_INET_DRIVER = 0x80

Const $DNF_UNUSED1 = 0x100

; This driver node is derived from an INF file that was included with this version of Windows.
Const $DNF_INDEXED_DRIVER = 0x200

; This driver came from the Internet, but Setup does not currently have access to its source files. This flag is READ-ONLY to installers.
; The system will not install a driver marked with this flag because Setup does not have the source files and would end up prompting the user with an invalid,
; path. The INF for such a driver can be used for everything except for installing devices.
Const $DNF_OLD_INET_DRIVER = 0x400

; Do not use this driver. Installers can read and write this flag.
; If this flag is set, SetupDiSelectBestCompatDrv and SetupDiSelectDevice ignore this driver.
; A class installer or co-installer can set this flag to prevent Setup from listing the driver in the Select Driver dialog box.
; An installer might set this flag when it handles a DIF_SELECTDEVICE or DIF_SELECTBESTCOMPATDRV request, for example.
Const $DNF_BAD_DRIVER = 0x800

; There are other providers supplying drivers that have the same description as this driver.
; The only difference between this driver and its match is the driver date. This flag is read-only to installers.
; If this flag is set, Setup displays the driver date and driver version next to the driver so that the user can distinguish it from its match.
Const $DNF_DUPPROVIDER = 0x1000

; (Windows XP and later versions of Windows)
Const $DNF_INF_IS_SIGNED = 0x2000

; Reserved. (Windows XP and later versions of Windows)
Const $DNF_OEM_F6_INF = 0x4000

; (Windows XP and later versions of Windows)
Const $DNF_DUPDRIVERVER = 0x8000

; (Windows XP and later versions of Windows)
Const $DNF_BASIC_DRIVER = 0x10000

; This driver¡¯s INF file is signed by an Authenticode signature. This flag is read-only to installers.
Const $DNF_AUTHENTICODE_SIGNED = 0x20000

; (Windows Vista and later versions of Windows)
; This driver node is currently installed for the device. This flag is read-only to installers.
Const $DNF_INSTALLEDDRIVER = 0x40000

; If set, this flag prevents the driver node from being enumerated, regardless of the client that is performing the enumeration.
Const $DNF_ALWAYSEXCLUEDFROMLIST = 0x80000
; =================================================================================

; #### Flags for SP_DRVINSTALL_PARAMS.Rank ####
; =================================================================================
Const $DRIVER_HARDWAREID_RANK = 0xFFF
Const $DRIVER_COMPATID_RANK = 0x3FFF
Const $DRIVER_UNTRUSTED_RANK = 0x8000
Const $DRIVER_UNTRUSTED_HARDWAREID_RANK = 0x8FFF
Const $DRIVER_UNTRUSTED_COMPATID_RANK = 0xBFFF
Const $DRIVER_W9X_SUSPECT_RANK = 0xC000
Const $DRIVER_W9X_SUSPECT_HARDWAREID_RANK = 0xCFFF
; =================================================================================

; #### Flags for HWPROFILE_INFO.Flags ####
; =================================================================================
Const $CM_HWPI_NOT_DOCKABLE = 0 ; Machine is not dockable
Const $CM_HWPI_UNDOCKED = 1 ; HW Profile for docked config
Const $CM_HWPI_DOCKED = 2 ; HW Profile for undocked config
; =================================================================================

; #### Flags for _CM_Bind_Device ####
; =================================================================================
Const $CM_BIND_UNUSED = 0
Const $CM_BIND_DEVINST_BIND_ID = 1
Const $CM_BIND_DEVINST_BIND_PHYSNAME = 2
Const $CM_BIND_PHYSNAME_BIND_DEVINST = 4
Const $CM_BIND_DEVINST_BIND_CLASS = 8
Const $CM_BIND_CLASS_BIND_DEVINST = 16
Const $CM_BIND_ENUMERATOR_BIND_DEVINST = 32
; =================================================================================

; ####### FUNCTIONS #######
; ==============================================================================
; _CM_Add_Empty_Log_Conf
; _CM_Add_Empty_Log_Conf_Ex
; _CM_Add_ID
; _CM_Add_ID_Ex
; _CM_Add_Res_Des
; _CM_Add_Res_Des_Ex
; _CM_Add_Res_Des_IO_Array_Ex
; _CM_Add_Res_Des_IRQ_Array_Ex
; _CM_Add_Res_Des_Mem_Array_Ex
; _CM_Assign_Var
; _CM_Cdrom_Known_Good_Digital_Playback
; _CM_Close_Handle
; _CM_Connect_Machine
; _CM_Create_Device_Devs
; _CM_Create_Device_Devs_Ex
; _CM_Create_File
; _CM_Device_IO_Control
; _CM_Disable_Cdrom_Digital_Playback
; _CM_Disable_DevNode
; _CM_Disable_DevNode_Ex
; _CM_Disconnect_Machine
; _CM_Duplicate_Buffer
; _CM_Enable_Cdrom_Digital_Playback
; _CM_Enable_DevNode
; _CM_Enable_DevNode_Ex
; _CM_Enable_Privileges
; _CM_Enum_Device_Info
; _CM_Enum_Device_Info_Ex
; _CM_Enum_Device_Info_Notify_Progress
; _CM_Enumerate_Children
; _CM_Enumerate_Children_Ex
; _CM_Enumerate_Classes
; _CM_Enumerate_Classes_Ex
; _CM_Enumerate_Enumerators
; _CM_Enumerate_Enumerators_Ex
; _CM_Enumerate_Physical_Disks
; _CM_Format_Error_Message
; _CM_Format_Problem_Message
; _CM_Free_Log_Conf
; _CM_Free_Log_Conf_Ex
; _CM_Free_Log_Conf_Handle
; _CM_Free_Res_Des
; _CM_Free_Res_Des_Ex
; _CM_Free_Res_Des_Handle
; _CM_Free_Resource_Conflict_Handle
; _CM_Free_Variable
; _CM_Get_Child
; _CM_Get_Child_By_Index
; _CM_Get_Child_By_Index_Ex
; _CM_Get_Child_Ex
; _CM_Get_Children_Count
; _CM_Get_Children_Count_Ex
; _CM_Get_Class_Registry_Property_Ex
; _CM_Get_Depth
; _CM_Get_Depth_Ex
; _CM_Get_Device_Driver_Files
; _CM_Get_Device_ID
; _CM_Get_Device_ID_By_Name_Ex
; _CM_Get_Device_ID_Ex
; _CM_Get_Device_ID_List
; _CM_Get_Device_ID_List_Ex
; _CM_Get_Device_ID_List_Size
; _CM_Get_Device_ID_List_Size_Ex
; _CM_Get_Device_ID_Size
; _CM_Get_Device_ID_Size_Ex
; _CM_Get_Device_Interface_List
; _CM_Get_Device_Interface_List_Ex
; _CM_Get_Device_Interface_List_Size
; _CM_Get_Device_Interface_List_Size_Ex
; _CM_Get_Device_Resources
; _CM_Get_Device_Resources_Ex
; _CM_Get_DevNode_Registry_Property
; _CM_Get_DevNode_Registry_Property_Ex
; _CM_Get_DevNode_Status
; _CM_Get_DevNode_Status_Ex
; _CM_Get_Drive_Disk_Number
; _CM_Get_Drive_Type
; _CM_Get_First_Log_Conf
; _CM_Get_First_Log_Conf_Ex
; _CM_Get_HW_Prof_Flags
; _CM_Get_HW_Prof_Flags_Ex
; _CM_Get_Last_Error
; _CM_Get_Log_Conf_Priority_Ex
; _CM_Get_Next_Log_Conf
; _CM_Get_Next_Log_Conf_Ex
; _CM_Get_Next_Res_Des
; _CM_Get_Next_Res_Des_Ex
; _CM_Get_Parent
; _CM_Get_Parent_Ex
; _CM_Get_Process_Heap
; _CM_Get_Res_Des_By_Index
; _CM_Get_Res_Des_By_Index_Ex
; _CM_Get_Res_Des_Data
; _CM_Get_Res_Des_Data_Ex
; _CM_Get_Res_Des_Data_Size
; _CM_Get_Res_Des_Data_Size_Ex
; _CM_Get_Resource_Conflict_Count
; _CM_Get_Resource_Conflict_Details
; _CM_Get_Sibling
; _CM_Get_Sibling_Ex
; _CM_Get_Version
; _CM_Get_Version_Ex
; _CM_Get_Volume_Name
; _CM_Get_Volume_Path
; _CM_GUID_From_String
; _CM_Heap_Alloc
; _CM_Heap_Free
; _CM_Heap_Size
; _CM_Install_Device_Driver
; _CM_Install_DevInst_Ex
; _CM_Install_New_Device
; _CM_Install_Selected_Device
; _CM_Install_Selected_Driver
; _CM_Is_Cdrom_Digital_Playback_Enabled
; _CM_Is_Device_Disabled
; _CM_Is_Dock_Station_Present
; _CM_Is_Dock_Station_Present_Ex
; _CM_Is_Version_Available
; _CM_Is_Version_Available_Ex
; _CM_Locate_DevNode
; _CM_Locate_DevNode_Ex
; _CM_Lock_Cdrom
; _CM_Modify_Res_Des
; _CM_Modify_Res_Des_Ex
; _CM_Query_And_Remove_SubTree
; _CM_Query_And_Remove_SubTree_Ex
; _CM_Query_Device_Problem
; _CM_Query_Device_Problem_Ex
; _CM_Query_DevNode_Resource_Conflicts_Ex
; _CM_Query_Resource_Conflict_List
; _CM_Reenumerate_DevNode
; _CM_Reenumerate_DevNode_Ex
; _CM_Request_Device_Eject
; _CM_Request_Device_Eject_Ex
; _CM_Request_Eject_PC
; _CM_Request_Eject_PC_Ex
; _CM_Safely_Eject_Disk
; _CM_Scan_Device_Changes
; _CM_Scan_Device_Changes_Ex
; _CM_Set_DevNode_CSConfigFlags
; _CM_Set_DevNode_Problem
; _CM_Set_DevNode_Problem_Ex
; _CM_Setup_DevNode
; _CM_String_From_GUID
; _CM_Uninstall_DevNode
; _CM_Update_PnP_Device
; _CM_Validate_Res_Des_Conflict_Ex
; _InstallNewDevice
; _SetupCloseInfFile
; _SetupDiApiBufferFree
; _SetupDiAskForOEMDisk
; _SetupDiBuildClassInfoList
; _SetupDiBuildDriverInfoList
; _SetupDiCallClassInstaller
; _SetupDiChangeState
; _SetupDiClassGuidsFromName
; _SetupDiClassNameFromGuid
; _SetupDiCreateDeviceDevs
; _SetupDiCreateDeviceDevsEx
; _SetupDiCreateDeviceInfo
; _SetupDiCreateDeviceInfoList
; _SetupDiCreateDeviceInfoListEx
; _SetupDiCreateDeviceInterface
; _SetupDiCreateDeviceInterfaceRegKey
; _SetupDiDeleteDeviceInfo
; _SetupDiDeleteDeviceInterfaceData
; _SetupDiDestroyClassImageList
; _SetupDiDestroyDeviceInfoList
; _SetupDiDestroyDriverInfoList
; _SetupDiDisableDevice
; _SetupDiEnumDeviceInfo
; _SetupDiEnumDeviceInterfaces
; _SetupDiEnumDriverInfo
; _SetupDiGetClassBitmapIndex
; _SetupDiGetClassDescription
; _SetupDiGetClassDescriptionEx
; _SetupDiGetClassDevs
; _SetupDiGetClassDevsEx
; _SetupDiGetClassImageIndex
; _SetupDiGetClassImageList
; _SetupDiGetDeviceInstallParams
; _SetupDiGetDeviceInstanceId
; _SetupDiGetDeviceInterfaceDetail
; _SetupDiGetDeviceInterfaceDevInst
; _SetupDiGetDeviceInterfaceDevs
; _SetupDiGetDeviceInterfaceDevsEx
; _SetupDiGetDevicePowerCapabilities
; _SetupDiGetDevicePowerMapping
; _SetupDiGetDevicePowerState
; _SetupDiGetDeviceRegistryProperty
; _SetupDiGetDevNodeStatus
; _SetupDiGetDriverInfoDetail
; _SetupDiGetDriverInstallParams
; _SetupDiGetDriverSigner
; _SetupDiGetHwProfileFriendlyName
; _SetupDiGetHwProfileList
; _SetupDiGetINFClass
; _SetupDiGetSelectedDriver
; _SetupDiInstallClass
; _SetupDiInstallClassEx
; _SetupDiInstallDevice
; _SetupDiInstallDeviceInterfaces
; _SetupDiLoadClassIcon
; _SetupDiLoadDeviceIcon
; _SetupDiOpenDeviceInfo
; _SetupDiOpenDeviceInterface
; _SetupDiOpenDeviceInterfaceRegKey
; _SetupDiOpenDevRegKey
; _SetupDiRegisterDeviceInfo
; _SetupDiRemoveDevice
; _SetupDiRemoveDeviceInterface
; _SetupDiSelectBestCompatDrv
; _SetupDiSelectDevice
; _SetupDiSelectOEMDrv
; _SetupDiSetClassInstallParams
; _SetupDiSetDeviceInstallParams
; _SetupDiSetDeviceInterfaceDefault
; _SetupDiSetDeviceRegistryProperty
; _SetupDiSetDriverInstallParams
; _SetupDiSetSelectedDevice
; _SetupDiSetSelectedDriver
; _SetupDiUnremoveDevice
; _SetupDiVerifyDigitalSigner
; _SetupGetLineByIndex
; _SetupGetLineCount
; _SetupGetLineText
; _SetupGetTargetPath
; _SetupOpenInfFile
; ==============================================================================

; #### Handle to the modules ####
; ==============================================================================================
Const $SETUPAPI_DllHandle = DllOpen("SetupApi.dll")
Const $KERNEL32_DllHandleA = DllOpen("Kernel32.dll")
Const $NEWDEV_DllHandle = DllOpen("Newdev.dll")
Const $DEVMGR_DllHandle = DllOpen("DevMgr.dll")
Const $STORP_DllHandle = DllOpen("StorProp.dll")
; ==============================================================================================

; #### FUNCTION ####
; ==============================================================================
; Name  : _SetupDiGetClassDevs
; Description   : Retrieves A handle to device information set.
; Parameter(s)  : $iFlags   - A value of type DWORD that specifies control options that filter the device information elements that are added to the device information set. This parameter can be a bitwise OR of zero or more of the following flags, can be a combination of the following values:
;       :   - $DIGCF_ALLCLASSES
;       :   - Return a list of installed devices for all device setup classes or all device interface classes.
;       :   - $DIGCF_DEVICEINTERFACE
;       :   - Return devices that support device interfaces for the specified device interface classes. This flag must be set in the Flags parameter if the Enumerator parameter specifies a device instance ID.
;       :   - $DIGCF_DEFAULT
;       :   - Return only the device that is associated with the system default device interface, if one is set, for the specified device interface classes.
;       :   - $DIGCF_PRESENT
;       :   - Return only devices that are currently present in a system.
;       :   - $DIGCF_PROFILE
;       :   - Return only devices that are a part of the current hardware profile
;       : $vGuid    - An optional variable-type GUID value for a device setup class or a device interface class.
;       : $sEnumerator  - Enumerator for this device information set (PCI/SCSI/PCMCIA...).
; Return values : If succeeds, returns a handle to device information set contains the control options. Otherwise, returns ERROR_INVALID_HANDLE (-1) and sets @error to a system error code.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiGetClassDevs($iFlags, $vGuid = 0, $sEnumerator = "")
    Local $iResult, $tGuid, $pGuid = 0, $sType = "ptr"

    If $sEnumerator <> "" Then $sType = "str"
    If IsString($vGuid) Then
        If StringLeft($vGuid, 1) & StringRight($vGuid, 1) = "{}" Then
            $tGUID = _CM_GUID_From_String($vGuid)
            $pGuid = DllStructGetPtr($tGUID)
        ElseIf $vGuid <> "" Then
            $tGuid = _SetupDiClassGuidsFromName($vGuid)
            $pGuid = DllStructGetPtr($tGuid)
        EndIf
    ElseIf IsDllStruct($vGuid) Then
        $pGuid = DllStructGetPtr($vGuid)
    ElseIf IsPtr($vGuid) Then
        $pGuid = $vGuid
    Else
        $pGuid = 0
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "ptr", "SetupDiGetClassDevs", "ptr", $pGuid, _
            $sType, $sEnumerator, "hWnd", 0, "dword", $iFlags)
    Return SetError(_CM_Get_Last_Error(), _SetupDiApiBufferFree($tGuid), $iResult[0])
EndFunc ;==>_SetupDiGetClassDevs

; #### FUNCTION ####
; =========================================================================
; Name  : _SetupDiClassGuidsFromName
; Description   : Return the GUID of the specified device class.
; Parameter(s)  : $sClassName   - The name of the device class, (NET/Keyboard...).
; Return values : If succeeds, returns a GUID structure (contains one member - Guid), and @extended is set to non-zero. If fails, returns a GUID structure either, but @extended is set to zero.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiClassGuidsFromName($sClassName)
    Local $tGuid, $pGuid, $iResult

    $tGuid = DllStructCreate("byte Guid[16]")
    $pGuid = DllStructGetPtr($tGuid)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiClassGuidsFromName", _
            "str", $sClassName, "ptr", $pGuid, "dword", 1, "int*", 0)
    Return SetError(_CM_Get_Last_Error(), $iResult[4], $tGuid)
EndFunc ;==>_SetupDiClassGuidsFromName

; #### FUNCTION ####
; =========================================================================
; Name  : _SetupDiApiBufferFree
; Description   : Frees a memory buffer, internal used only.
; Parameter(s)  : $vBuffer - Buffer to be freed.
; Return values : None.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiApiBufferFree(ByRef $vBuffer, $vValue = 0, $vReturn = "", _
            $iError = @error, $iExtended = @Extended)
    $vBuffer = $vValue
    Return SetError($iError, $iExtended, $vReturn)
EndFunc ;==>_SetupDiApiBufferFree

Func _SetupDiBuildClassInfoList($iFlags = 0)
    Local $iResult, $tBuffer, $pBuffer, $tagBuffer, $aResult[1][2] = [[0]]

    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiBuildClassInfoList", "dword", $iFlags, _
            "ptr", 0, "dword", 0, "dword*", 0)
    If $iResult[4] = 0 Then Return SetError(_CM_Get_Last_Error(), 0, $aResult)
    $aResult[0][0] = $iResult[4]
    Redim $aResult[$iResult[4] + 1][2]
    For $i = 1 to $iResult[4]
        $tagBuffer &= "ubyte[16];"
    Next
    $tBuffer = DllStructCreate($tagBuffer)
    $pBuffer = DllStructGetPtr($tBuffer)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiBuildClassInfoList", "dword", $iFlags, _
            "ptr", $pBuffer, "dword", $iResult[4], "dword*", 0)
    For $i = 1 to $iResult[4]
        $pBuffer = DllStructGetPtr($tBuffer, $i)
        $aResult[$i][0] = _CM_String_From_GUID($pBuffer)
        $aResult[$i][1] = _SetupDiGetClassDescription($pBuffer)
    Next
    _SetupDiApiBufferFree($tBuffer)
    Return SetExtended($iResult[4], $aResult)
EndFunc ;==>_SetupDiBuildClassInfoList

; #### FUNCTION ####
; =========================================================================
; Name  : _SetupDiGetClassDescription
; Description   : Retrieves the class description associated with the specified setup class GUID.
; Parameter(s)  : $vGuid    - A variable-type Class-GUID value, can be in one of the following formats:
;       :   - Class name: NET/Display/Mouse...
;       :   - Class GUID string: {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
;       :   - Class GUID structure.
;       :   - Class GUID pointer.
; Return values : If succeeds, returns the class description, on failure, @extended is set to zero.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiGetClassDescription($vGuid)
    Local $iResult, $pGuid

    If IsDllStruct($vGuid) Then
        $pGuid = DllStructGetPtr($vGuid)
    ElseIf IsString($vGuid) Then
        Local $tGUID = _CM_GUID_From_String($vGuid)
        $pGuid = DllStructGetPtr($tGUID)
    ElseIf IsPtr($vGuid) Then
        $pGuid = $vGuid
    EndIf

    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetClassDescription", _
            "ptr", $pGuid, "ptr", 0, "dword", 0, "dword*", 0)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetClassDescription", _
            "ptr", $pGuid, "str", "", "dword", $iResult[4], "dword*", 0)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[2])
EndFunc ;==>_SetupDiGetClassDescription

; #### FUNCTION ####
; =========================================================================
; Name  : _SetupDiClassNameFromGuid
; Description   : Retrieves the class name associated with a class GUID.
; Parameter(s)  : $vGuid    - A variable-type Class-GUID value, can be in one of the following formats:
;       :   - Class GUID string: {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
;       :   - Class GUID structure.
;       :   - Class GUID pointer.
; Return values : If succeeds, return the class name and sets @extended to non-zero, else return NULL and sets @error.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiClassNameFromGuid($vGuid)
    Local $pGuid, $iResult

    If IsDllStruct($vGuid) Then
        $pGuid = DllStructGetPtr($vGuid)
    ElseIf IsString($vGuid) Then
        Local $tGUID = _CM_GUID_From_String($vGuid)
        $pGuid = DllStructGetPtr($tGUID)
    ElseIf IsPtr($vGuid) Then
        $pGuid = $vGuid
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiClassNameFromGuid", _
            "ptr", $pGuid, "str", "", "dword", 64, "dword*", 0)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[2])
EndFunc ;==>_SetupDiClassNameFromGuid

; #### FUNCTION ####
; =========================================================================
; Name  : _SetupDiEnumDeviceInfo
; Description   : Enumerates a device information element in the device information set.
; Parameter(s)  : $hDevs    - A handle to the device information set.
;       : $iIndex   - The zero-based index of the device information element to retrieve.
;       : $tSP_DEVINFO_DATA - A variable receives a SP_DEVINFO_DATA structure contains the device information element.
; Return values : True indicates success, false to failure, in which case, @error is set to a system error code.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiEnumDeviceInfo($hDevs, $iIndex, ByRef $tSP_DEVINFO_DATA)
    Local $iResult, $pSP_DEVINFO_DATA

    If Not IsDllStruct($tSP_DEVINFO_DATA) Then
        $tSP_DEVINFO_DATA = DllStructCreate($tagSP_DEVICEINFO_DATA)
        DllStructSetData($tSP_DEVINFO_DATA, "Size", 28)
    EndIf
    $pSP_DEVINFO_DATA = DllStructGetPtr($tSP_DEVINFO_DATA)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiEnumDeviceInfo", _
            "ptr", $hDevs, "int", $iIndex, "ptr", $pSP_DEVINFO_DATA)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiEnumDeviceInfo

; #### FUNCTION ####
; =========================================================================
; Name  : _SetupDiGetDeviceRegistryProperty
; Description   : Retrieve the device registry property.
; Parameter(s)  : $hDevs    - A handle to a device information set, obtain the handle by using _SetupDiGetClassDevs function.
;       : $pSP_DEVINFO_DATA - A pointer to/or a SP_DEVICEINFO_DATA structure contains the device information from which the property information is retrieved.
;       : $iProperty    - A value indicates the property required, see SPDRP_* constants for a value.
; Return values : If success, returns the requested property. If failure, returns NULL and sets @error to a system error code, pass @error to FormatMessage for an explicit error message.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiGetDeviceRegistryProperty($hDevs, $pSP_DEVINFO_DATA, $iProperty)
    Local $iResult, $pBuffer, $tBuffer, $sVal, $vVar, $iSysError

    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetDeviceRegistryProperty", _
            "ptr", $hDevs, "ptr", $pSP_DEVINFO_DATA, "dword", $iProperty, _
            "dword*", 0, "ptr", 0, "dword", 0, "dword*", 0)
    $pBuffer = _CM_Heap_Alloc($iResult[7])
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetDeviceRegistryProperty", _
            "ptr", $hDevs, "ptr", $pSP_DEVINFO_DATA, "dword", $iProperty, _
            "dword*", 0, "ptr", $pBuffer, "dword", $iResult[7], "dword*", 0)
    $iSysError = _CM_Get_Last_Error()
    Switch $iResult[4]
    Case 1, 2, 7
        $tBuffer = DllStructCreate("char Data[" & $iResult[7] & "]", $pBuffer)
    Case 4, 5
        $tBuffer = DllStructCreate("dword Data", $pBuffer)
    Case 6
        $tBuffer = DllStructCreate("wchar Data[" & $iResult[7] / 2 & "]", $pBuffer)
    Case Else
        $tBuffer = DllStructCreate("byte Data[" & $iResult[7] & "]", $pBuffer)
    EndSwitch
    If $iResult[4] <> 7 Then
        $vVar = DllStructGetData($tBuffer, "Data")
        _CM_Heap_Free($pBuffer)
        Return SetError($iSysError, _CM_Free_Variable($tBuffer) + $iResult[4], $vVar)
    EndIf
    For $i = 1 To $iResult[7]
        $sVal = DllStructGetData($tBuffer, "Data", $i)
        If $sVal = Chr(0) Then
            $vVar &= @LF
            ContinueLoop
        EndIf
        $vVar &= $sVal
    Next
    _CM_Heap_Free($pBuffer)
    Return SetError($iSysError, 7 + _CM_Free_Variable($tBuffer), $vVar)
EndFunc ;==>_SetupDiGetDeviceRegistryProperty

; #### FUNCTION #####
; =========================================================================
; Name  : _SetupDiSetDeviceRegistryProperty
; Description   : This function sets property for a device instance.
; Parameter(s)  : $hDevs    - Handle to the device information set.
;       : $pSP_DEVINFO_DATA - A pointer to an SP_DEVINFO_DATA structure contains the device information element.
;       : $iProperty - Property to be set.
;       : $pBuffer - Property value.
;       : $iBufferSize  - Size of $pBuffer.
;       : $sBufferType  - Variable type of $pBuffer parameter, default to recognize as a pointer (PTR).
; Return values : True is returned if succeeds, otherwise returns false and sets @error to a system error code.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiSetDeviceRegistryProperty($hDevs, $pSP_DEVINFO_DATA, $iProperty, $pBuffer, $iBufferSize, $sBufferType = "ptr")
    Local $iResult

    If IsDllStruct($pBuffer) Then $pBuffer = DllStructGetPtr($pBuffer)
    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiSetDeviceRegistryProperty", _
            "ptr", $hDevs, "ptr", $pSP_DEVINFO_DATA, "dword", $iProperty, _
            $sBufferType, $pBuffer, "dword", $iBufferSize)
    Return SetError(_CM_Get_Last_Error(), 0, $iResult[0])
EndFunc ;==>_SetupDiSetDeviceRegistryProperty

Func _SetupDiGetDevicePowerCapabilities($hDevs, $tDevInfo)
    Local $bData, $tData, $pData, $tPower, $iCapValue

    $bData = _SetupDiGetDeviceRegistryProperty($hDevs, $tDevInfo, 0x1E);, 0)
    If @error Then Return SetError(@error, 0, 0)

    $tData = DllStructCreate("byte Data[" & BinaryLen($bData) & "]")
    $pData = DllStructGetPtr($tData)
    $tPower = DllStructCreate($tagCM_POWER_DATA, $pData)
    DllStructSetData($tData, "Data", $bData)

    $iCapValue = "0x" & Hex(DllStructGetData($tPower, "Capabilities"))
    _CM_Free_Variable($tPower)
    Return SetExtended(_CM_Free_Variable($tData), $iCapValue)
EndFunc ;==>_SetupDiGetDevicePowerCapabilities

Func _SetupDiGetDevicePowerMapping($hDevs, $tDevInfo)
    Local $aResult[6], $bData, $tData, $pData, $tPower, $iValue

    $bData = _SetupDiGetDeviceRegistryProperty($hDevs, $tDevInfo, 0x1E);, 0)
    If @error Then Return SetError(@error, 0, $aResult)
    $tData = DllStructCreate("byte Data[" & BinaryLen($bData) & "]")
    $pData = DllStructGetPtr($tData)
    $tPower = DllStructCreate($tagCM_POWER_DATA, $pData)
    DllStructSetData($tData, "Data", $bData)

    For $i = 2 to 7
        $iValue = DllStructGetData($tPower, "PowerStateMapping", $i)
        Switch $iValue
        Case 0
            $iValue = "Unspecified"
        Case 1
            $iValue = "D0"
        Case 2
            $iValue = "D1"
        Case 3
            $iValue = "D2"
        Case 4
            $iValue = "D3"
        Case 5
            $iValue = "Maximum"
        Case Else
            $iValue = "Unknown"
        EndSwitch
        $aResult[$i - 2] = "S" & ($i - 2) & " -> " & $iValue
    Next
    _CM_Free_Variable($tPower)
    Return SetExtended(_CM_Free_Variable($tData), $aResult)
EndFunc ;==>_SetupDiGetDevicePowerMapping

Func _SetupDiGetDevicePowerState($hDevs, $tDevInfo)
    Local $bData, $tData, $pData, $tPower, $sValue

    $bData = _SetupDiGetDeviceRegistryProperty($hDevs, $tDevInfo, 0x1E);, 0)
    If @error Then Return SetError(@error, 0, "")

    $tData = DllStructCreate("byte Data[" & BinaryLen($bData) & "]")
    $pData = DllStructGetPtr($tData)
    $tPower = DllStructCreate($tagCM_POWER_DATA, $pData)
    DllStructSetData($tData, "Data", $bData)
    Switch DllStructGetData($tPower, "MostRecentPowerState")
    Case 0
        $sValue = "Unspecified"
    Case 1
        $sValue = "D0"
    Case 2
        $sValue = "D1"
    Case 3
        $sValue = "D2"
    Case 4
        $sValue = "D3"
    Case 5
        $sValue = "Maximum"
    Case Else
        $sValue = "Unknown"
    EndSwitch
    _CM_Free_Variable($tPower)
    Return SetExtended(_CM_Free_Variable($tData), $sValue)
EndFunc ;==>_SetupDiGetDevicePowerState

; #### FUNCTION ####
; =========================================================================
; Name  : _SetupDiGetDeviceInstanceId
; Description   : Retrieve the instance identifier of the specified device.
; Parameter(s)  : $hDevs    - A handle to a device information set.
;       : $pSP_DEVINFO_DATA - A pointer to/or a SP_DEVICEINFO_DATA structure contains the device information.
; Return values : If succeeds, returns an instance identifier string, else returns NULL and sets @error.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiGetDeviceInstanceId($hDevs, $pSP_DEVINFO_DATA)
    Local $iResult
    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetDeviceInstanceId", _
            "ptr", $hDevs, "ptr", $pSP_DEVINFO_DATA, _
            "ptr", 0, "dword", 0, "dword*", 0)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetDeviceInstanceId", _
            "ptr", $hDevs, "ptr", $pSP_DEVINFO_DATA, _
            "str", "", "dword", $iResult[5], "dword*", 0)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[3])
EndFunc ;==>_SetupDiGetDeviceInstanceId

; #### FUNCTION ####
; =========================================================================
; Name  : _SetupDiCreateDeviceInfoList
; Description   : This function creates an empty device information set.
; Parameter(s)  : $vGuid - GUID for device setup class, can be NULL.
;       : $hWnd - Parent window handle, can be NULL.
; Return values : A valid handle is returned if succeeds, otherwise returns -1 and sets @error.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiCreateDeviceInfoList($vGuid = "", $hWnd = 0)
    Local $iResult, $pGuid
    If IsString($vGuid) Then
        If (StringLeft($vGuid, 1) & StringRight($vGuid, 1) = "{}") Then
            $pGuid = DllStructGetPtr(_CM_GUID_From_String($vGuid))
        ElseIf $vGuid <> "" Then
            $tGuid = _SetupDiClassGuidsFromName($vGuid)
            $pGuid = DllStructGetPtr($tGuid)
        EndIf
    ElseIf IsDllStruct($vGuid) Then
        $pGuid = DllStructGetPtr($vGuid)
    ElseIf IsPtr($vGuid) Then
        $pGuid = $vGuid
    Else
        $pGuid = 0
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "ptr", "SetupDiCreateDeviceInfoList", _
            "ptr", $pGuid, "hWnd", $hWnd)
    Return SetError(_CM_Get_Last_Error(), $iResult[0] <> -1, $iResult[0])
EndFunc ;==>_SetupDiCreateDeviceInfoList

; #### FUNCTION ####
; =========================================================================
; Name  : _SetupDiSetSelectedDevice
; Description   : This function selectes a device element for a device information set.
; Parameter(s)  : $hDevs    - Handle to the device information set.
;       : $pSP_DEVINFO_DATA - A pointer to SP_DEVINFO_DATA contains the device information element.
; Return values : True indicates success, False indicates failure, sets @error to a system error code.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiSetSelectedDevice($hDevs, $pSP_DEVINFO_DATA)
    Local $iResult

    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiSetSelectedDevice", _
            "ptr", $hDevs, "ptr", $pSP_DEVINFO_DATA)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiSetSelectedDevice

; #### FUNCTION ####
; =========================================================================
; Name  : _SetupDiSetSelectedDriver
; Description   : The _SetupDiSetSelectedDriver function sets, or resets, the selected driver for a device information element or the selected class driver for a device information set.
; Parameter(s)  : $hDevs - Handle to the device information set.
;       : $pSP_DEVINFO_DATA - A pointer to an SP_DEVINFO_DATA structure contains the device information element.
;       : $tSP_DRVINFO_DATA - An SP_DRVINFO_DATA structure contains the driver to be selected.
; Return values : True is returned if succeeds, otherwise returns False.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiSetSelectedDriver($hDevs, $pSP_DEVINFO_DATA, ByRef $tSP_DRVINFO_DATA)
    Local $iResult, $pSP_DRVINFO_DATA

    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    $pSP_DRVINFO_DATA = DllStructGetPtr($tSP_DRVINFO_DATA)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiSetSelectedDriver", _
            "ptr", $hDevs, "ptr", $pSP_DEVINFO_DATA, _
            "ptr", $pSP_DRVINFO_DATA)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiSetSelectedDriver

; #### FUNCTION ####
; =========================================================================
; Name  : _SetupDiOpenDeviceInfo
; Description   : This function adds a device information element for a device instance to a device information set, if one does not already exist in the device information set, and retrieves information that identifies the device information element for the device instance in the device information set.
; Parameter(s)  : $hDevs    - Supplies a handle to the device information set.
;       : $sInstanceID  - Supplies a device instance identifier, in string format.
;       : $tSP_DEVINFO_DATA - A variable receives a SP_DEVINFO_DATA that contains the specified device information element.
;       : $iFlags - A variable of DWORD type that controls how the device information element is opened, a value of zero is default.
; Return values : If succeeds, returns True. Else returns False and sets @error to a system error code.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiOpenDeviceInfo($hDevs, $sInstanceId, ByRef $tSP_DEVINFO_DATA, $iFlag = 0)
    Local $iResult, $pSP_DEVINFO_DATA

    If Not IsDllStruct($tSP_DEVINFO_DATA) Then
        $tSP_DEVINFO_DATA = DllStructCreate($tagSP_DEVICEINFO_DATA)
        DllStructSetData($tSP_DEVINFO_DATA, "Size", 28)
    EndIf
    $pSP_DEVINFO_DATA = DllStructGetPtr($tSP_DEVINFO_DATA)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiOpenDeviceInfo", _
            "ptr", $hDevs, "str", $sInstanceId, "hWnd", 0, _
            "dword", $iFlag, "ptr", $pSP_DEVINFO_DATA)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiOpenDeviceInfo

; #### FUNCTION ####
; =========================================================================
; Name  : _SetupDiGetDeviceInstallParams
; Description   : This function is used to retrieve the device installation parameters for a selected device information element.
; Parameter(s)  : $hDevs    - Supplies a handle to the device information set.
;       : $pSP_DEVINFO_DATA - A pointer to an SP_DEVINFO_DATA structure contains the device information element from which the installation is retrieved.
;       : ByRef $tSP_DEVINST_PARAMS - Supplies a variable that receives an SP_DEVINSTALL_PARAMS structure fills with the requested data.
; Return values : Returns TRUE if succeeds, FALSE otherwise, the logged error is set in @error.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiGetDeviceInstallParams($hDevs, $pSP_DEVINFO_DATA, ByRef $tSP_DEVINST_PARAMS)
    Local $iResult, $pSP_DEVINST_PARAMS

    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    If Not IsDllStruct($tSP_DEVINST_PARAMS) Then
        $tSP_DEVINST_PARAMS = DllStructCreate($tagSP_DEVINSTALL_PARAMS)
        DllStructSetData($tSP_DEVINST_PARAMS, 1, DllStructGetSize($tSP_DEVINST_PARAMS))
    EndIf
    $pSP_DEVINST_PARAMS = DllStructGetPtr($tSP_DEVINST_PARAMS)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetDeviceInstallParams", _
            "ptr", $hDevs, "ptr", $pSP_DEVINFO_DATA, _
            "ptr", $pSP_DEVINST_PARAMS)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiGetDeviceInstallParams

; #### FUNCTION ####
; =========================================================================
; Name  : _SetupDiBuildDriverInfoList
; Description   : This function is used to create the driver information set for a selected device information element.
; Parameter(s)  : $hDevs - Supplies a device information set handle.
;       : $pSP_DEVINFO_DATA - Supplies a pointer to an SP_DEVINFO_DATA contains the device information element.
; Return values : Returns TRUE if succeeds, FALSE otherwise, the logged error is set in @error.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiBuildDriverInfoList($hDevs, $pSP_DEVINFO_DATA)
    Local $iResult, $iType = $SPDIT_CLASSDRIVER

    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    If IsPtr($pSP_DEVINFO_DATA) Then $iType = $SPDIT_COMPATDRIVER
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiBuildDriverInfoList", _
            "ptr", $hDevs, "ptr", $pSP_DEVINFO_DATA, "int", $iType)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiBuildDriverInfoList

; #### FUNCTION ####
; =========================================================================
; Name  : _SetupDiCallClassInstaller
; Description   : The function calls the appropriate class installer, and any registered co-installers, with the specified installation request (DIF code).
; Parameter(s)  : $hDevs    - A handle to the device information set.
;       : $pSP_DEVINFO_DATA - A pointer (or a structure) to an SP_DEVINFO_DATA contains the device information element.
;       : $iDIFCode - The device installation request (DIF request) to pass to the co-installers and class installer.
; Return values : Returns TRUE if succeeds, FALSE otherwise, the error code is set to in @error.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiCallClassInstaller($hDevs, $pSP_DEVINFO_DATA, $iDIFCode)
    Local $iResult

    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiCallClassInstaller", _
            "dword", $iDifCode, "ptr", $hDevs, "ptr", $pSP_DEVINFO_DATA)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiCallClassInstaller

Func _SetupDiGetSelectedDriver($hDevs, $pSP_DEVINFO_DATA, ByRef $tSP_DRVINFO_DATA)
    Local $iResult, $pSP_DRVINFO_DATA

    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    If Not IsDllStruct($tSP_DRVINFO_DATA) Then
        $tSP_DRVINFO_DATA = DllStructCreate($tagSP_DRVINFO_DATA)
        DllStructSetData($tSP_DRVINFO_DATA,1,DllStructGetSize($tSP_DRVINFO_DATA)-12)
    EndIf
    $pSP_DRVINFO_DATA = DllStructGetPtr($tSP_DRVINFO_DATA)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetSelectedDriver", _
            "ptr", $hDevs, "ptr", $pSP_DEVINFO_DATA, _
            "ptr", $pSP_DRVINFO_DATA)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiGetSelectedDriver

Func _SetupDiGetDriverInfoDetail($hDevs, $pSP_DEVINFO_DATA, $pSP_DRVINFO_DATA, ByRef $tSP_DRVINFO_DETAIL_DATA)
    Local $iResult, $pSP_DRVINFO_DETAIL_DATA, $iLength, $tagBuffer

    Select
    Case IsDllStruct($pSP_DEVINFO_DATA)
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
        ContinueCase
    Case IsDllStruct($pSP_DRVINFO_DATA)
        $pSP_DRVINFO_DATA = DllStructGetPtr($pSP_DRVINFO_DATA)
        ContinueCase
    Case IsDllStruct($tSP_DRVINFO_DETAIL_DATA) = 0
        $tSP_DRVINFO_DETAIL_DATA = DllStructCreate($tagSP_DRVINFO_DETAIL_DATA)
    EndSelect
    $iLength = DllStructGetSize($tSP_DRVINFO_DETAIL_DATA)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetDriverInfoDetail", _
            "ptr", $hDevs, "ptr", $pSP_DEVINFO_DATA, _
            "ptr", $pSP_DRVINFO_DATA, _
            "ptr", 0, "dword", 0, "dword*", 0)
    $iLength = $iResult[6] - $iLength
    If $iLength > 0 Then
        _SetupDiApiBufferFree($tSP_DRVINFO_DETAIL_DATA)
        $tagBuffer = $tagSP_DRVINFO_DETAIL_DATA & ";char HardwareId[" & $iLength & "]"
        $tSP_DRVINFO_DETAIL_DATA = DllStructCreate($tagBuffer)
        DllStructSetData($tSP_DRVINFO_DETAIL_DATA, 1, $iResult[6] - $iLength + 1)
    EndIf
    $pSP_DRVINFO_DETAIL_DATA = DllStructGetPtr($tSP_DRVINFO_DETAIL_DATA)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetDriverInfoDetail", _
            "ptr", $hDevs, "ptr", $pSP_DEVINFO_DATA, _
            "ptr", $pSP_DRVINFO_DATA, _
            "ptr", $pSP_DRVINFO_DETAIL_DATA, _
            "dword", $iResult[6], "dword*", 0)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiGetDriverInfoDetail

; #### FUNCTION ####
; =================================================================================
; Name  : _SetupDiSetDriverInstallParams
; Description   : The function sets driver installation parameters for a driver information element.
; Parameter(s)  : $hDevs    - A handle to a device information set that contains a driver information element that represents the driver for which to set installation parameters.
;       : $pSP_DEVINFO_DATA - A pointer to an SP_DEVINFO_DATA structure that specifies a device information element in DeviceInfoSet. This parameter is optional and can be set to NULL. If this parameter is specified, _SetupDiSetDriverInstallParams sets the driver installation parameters for the specified device. If this parameter is NULL, SetupDiSetDriverInstallParams sets driver installation parameters for DeviceInfoSet ($hDevs).
;       : $pSP_DRVINFO_DATA - A pointer to an SP_DRVINFO_DATA structure that specifies the driver for which installation parameters are set. If DeviceInfoData is specified, this driver must be a member of a driver list that is associated with DeviceInfoData. If DeviceInfoData is NULL, this driver must be a member of the global class driver list for DeviceInfoSet ($hDevs).
;       : $pSP_DRVINSTALL_PARAMS - A pointer to an SP_DRVINSTALL_PARAMS structure that specifies the new driver install parameters.
; Return values : The function returns TRUE if it is successful. Otherwise, it returns FALSE and the logged error can be retrieved in @error.
; Author    : Pusofalse
; =================================================================================
Func _SetupDiSetDriverInstallParams($hDevs, $pSP_DEVINFO_DATA, $pSP_DRVINFO_DATA, $pSP_DRVINSTALL_PARAMS)
    Local $iResult

    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    If IsDllStruct($pSP_DRVINFO_DATA) Then
        $pSP_DRVINFO_DATA = DllStructGetPtr($pSP_DRVINFO_DATA)
    EndIf
    If IsDllStruct($pSP_DRVINSTALL_PARAMS) Then
        $pSP_DRVINSTALL_PARAMS = DllStructGetPtr($pSP_DRVINSTALL_PARAMS)
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiSetDriverInstallParams", "ptr", $hDevs, _
            "ptr", $pSP_DEVINFO_DATA, "ptr", $pSP_DRVINFO_DATA, _
            "ptr", $pSP_DRVINSTALL_PARAMS)
    Return SetError(_CM_Get_Last_Error(), 0, $iResult[0])
EndFunc ;==>_SetupDiSetDriverInstallParams

; #### FUNCTION ####
; =================================================================================
; Name  : _SetupDiGetDriverInstallParams
; Description   : The _SetupDiGetDriverInstallParams function retrieves driver installation parameters for a device information set or a particular device information element.
; Parameter(s)  : $hDevs    - A handle to a device information set that contains a driver information element that represents the driver for which to retrieve installation parameters.
;       : $pSP_DEVINFO_DATA - A pointer to an SP_DEVINFO_DATA structure that contains a device information element that represents the device for which to retrieve installation parameters. This parameter is optional and can be NULL. If this parameter is specified, SetupDiGetDriverInstallParams retrieves information about a driver that is a member of a driver list for the specified device. If this parameter is NULL, SetupDiGetDriverInstallParams retrieves information about a driver that is a member of the global class driver list for DeviceInfoSet ($hDevs).
;       : $pSP_DRVINFO_DATA - A pointer to an SP_DRVINFO_DATA structure that specifies the driver information element that represents the driver for which to retrieve installation parameters. If DeviceInfoData is supplied, the driver must be a member of the driver list for the device that is specified by DeviceInfoData. Otherwise, the driver must be a member of the global class driver list for DeviceInfoSet ($hDevs).
;       : $tSP_DRVINSTALL_PARAMS - A variable that receives an SP_DRVINSTALL_PARAMS structure contains the driver installation parameters.
; Return values : TRUE is returned if the function completed without an error. Otherwise, the function returns FALSE, the logged error is set in @error.
; Author    : Pusofalse
; =================================================================================
Func _SetupDiGetDriverInstallParams($hDevs, $pSP_DEVINFO_DATA, $pSP_DRVINFO_DATA, ByRef $tSP_DRVINSTALL_PARAMS)
    Local $iResult, $pSP_DRVINSTALL_PARAMS, $iSizeofParams

    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    If IsDllStruct($pSP_DRVINFO_DATA) Then
        $pSP_DRVINFO_DATA = DllStructGetPtr($pSP_DRVINFO_DATA)
    EndIf
    If Not IsDllStruct($tSP_DRVINSTALL_PARAMS) Then
        $tSP_DRVINSTALL_PARAMS = DllStructCreate($tagSP_DRVINSTALL_PARAMS)
        $iSizeofParams = DllStructGetSize($tSP_DRVINSTALL_PARAMS)
        DllStructSetData($tSP_DRVINSTALL_PARAMS, "Size", $iSizeofParams)
    EndIf
    $pSP_DRVINSTALL_PARAMS = DllStructGetPtr($tSP_DRVINSTALL_PARAMS)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetDriverInstallParams", "ptr", $hDevs, _
            "ptr", $pSP_DEVINFO_DATA, "ptr", $pSP_DRVINFO_DATA, _
            "ptr", $pSP_DRVINSTALL_PARAMS)
    Return SetError(_CM_Get_Last_Error(), 0, $iResult[0])
EndFunc ;==>_SetupDiGetDriverInstallParams

; #### FUNCTION ####
; ================================================================================
; Name  : _SetupDiGetDriverSigner
; Description   : Retrieves the digital signature for a device instance.
; Parameter(s)  : $hDevs    - Handle to the device information set.
;       : $pSP_DEVINFO_DATA - A pointer to/or an SP_DEVINFO_DATA structure contains the device information element for which to retrieve the digital signature.
; Return values : Returns signature if succeeds, in text format. Else returns NULL and sets @error to a system error code.
; Author    : Pusofalse
; ================================================================================
Func _SetupDiGetDriverSigner($hDevs, $pSP_DEVINFO_DATA)
    Local $aSigner, $tDrvInfo, $tDrvDetail, $sInf

    Select
    Case _SetupDiBuildDriverInfoList($hDevs, $pSP_DEVINFO_DATA) = 0
        Return SetError(@error, 0, "")
    Case _SetupDiSelectBestCompatDrv($hDevs, $pSP_DEVINFO_DATA) = 0
        Return SetError(@error, 0, "")
    Case _SetupDiGetSelectedDriver($hDevs, $pSP_DEVINFO_DATA, $tDrvInfo) = 0
        Return SetError(@error, 0, "")
    Case _SetupDiGetDriverInfoDetail($hDevs, $pSP_DEVINFO_DATA, $tDrvInfo, $tDrvDetail) = 0
        Return SetError(@error, 0, "")
    Case _SetupDiDestroyDriverInfoList($hDevs, $pSP_DEVINFO_DATA) = 0
        Return SetError(@error, 0, "")
    Case Else
        $sInf = DllStructGetData($tDrvDetail, "InfFileName")
        $aSigner = _SetupDiVerifyDigitalSigner($sInf)
        Return SetError(@error, 0, $aSigner[1])
    EndSelect
EndFunc ;==>_SetupDiGetDriverSigner

; #### FUNCTION ####
; ================================================================================
; Name  : _SetupDiVerifyDigitalSigner
; Description   : Verify an INF file and retrieves its digital signer.
; Parameter(s)  : $sInfFile - INF file, may specify the full path.
; Return values : An array in the form:
;       : $aArray[0] - Catalog file.
;       : $aArray[1] - Signature.
;       : $aArray[2] - Signature version.
;       : If fails, all elements of the array are set to NULL, the logged error is set in @error.
; Author    : Pusofalse
; ================================================================================
Func _SetupDiVerifyDigitalSigner($sInfFile)
    Local $iResult, $tBuffer, $aResult[3], $iSysError

    $tBuffer = DllStructCreate($tagSP_INF_SIGNER_INFO)
    DllStructSetData($tBuffer, "Size", DllStructGetSize($tBuffer))

    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupVerifyInfFileW", "wstr", $sInfFile, _
            "ptr", 0, "ptr", DllStructGetPtr($tBuffer))
    If $iResult[0] = 0 Then $iSysError = _CM_Get_Last_Error()
    $aResult[0] = DllStructGetData($tBuffer, "CatalogFile")
    $aResult[1] = DllStructGetData($tBuffer, "DigitalSigner")
    $aResult[2] = DllStructGetData($tBuffer, "DigitalSignerVersion")
    Return SetError($iSysError, _SetupDiApiBufferFree($tBuffer), $aResult)
EndFunc ;==>_SetupDiVerifyDigitalSigner

Func _CM_Update_PnP_Device($sDeviceID, $sInfPath, $iFlags, $hWnd = 0)
    Local $iResult
    $iResult = DllCall($NEWDEV_DllHandle, "int", "UpdateDriverForPlugAndPlayDevices", "hWnd", $hWnd, _
            "str", $sDeviceID, "str", $sInfPath, "dword", $iFlags, "int*", 0)
    Return SetError(_CM_Get_Last_Error(), $iResult[5], $iResult[0])
EndFunc ;==>_CM_Update_PnP_Device

; #### FUNCTION ####
; =========================================================================
; Name  : _CM_Install_Selected_Driver
; Description   : This function installs a selected driver on a selected device.
; Parameter(s)  : $hDevs    - A handle to a device information set that contains the device information element that represents a selected device and a selected driver for the device.
;       : $fBackup  - A BOOL value indicates the backup option, true indicates backs up the currently installed drivers for the selected device, default to true.
;       : $hWnd - A handle to the top-level window that the this function uses to display user interface components that are associated with installing the driver, can be NULL.
; Return values : Returns true if the driver was installed on the selected device, in this case, @extended is set to a DWORD value indicate whether a system restart is required to complete the installation. If system restart is required, the value is set to DI_NEEDREBOOT, application should prompt user to restart system to finish the installation.
; Author    : Pusofalse
; =========================================================================
Func _CM_Install_Selected_Driver($hDevs, $fBackup = True, $hWnd = 0)
    Local $iResult
    $iResult = DllCall($NEWDEV_DllHandle, "int", "InstallSelectedDriver", "hWnd", $hWnd, _
            "ptr", $hDevs, "str", "", "int", $fBackup, "dword*", 0)
    Return SetError(_CM_Get_Last_Error(), $iResult[5], $iResult[0])
EndFunc ;==>_CM_Install_Selected_Driver

; #### FUNCTION ####
; =========================================================================
; Name  : _CM_Install_Device_Driver
; Description   : This function updates or installs the device driver for a device instance.
; Parameter(s)  : $sDeviceInstID - Supplies a device instance identifier for which the driver files are installed.
;       : $fBackup - True indicates backup the file installed, False otheriwise, default is True.
;       : $hWnd - Parent window owns the user interface, can be NULL.
; Return values : If succeeds, returns TRUE, if the device installation needs a system reboot, the function sets @extended to non-zero. If an error occured during the installation, function returns FALSE.
; Author    : Pusofalse
; =========================================================================
Func _CM_Install_Device_Driver($sDeviceInstID, $fBackup = True, $hWnd = 0)
    Local $iResult, $hDevs, $tDevInfo

    Select
    Case _SetupDiCreateDeviceDevs($sDeviceInstID, $hDevs, $tDevInfo) = 0
        Return SetError(@error, 0, 0)
    Case _SetupDiBuildDriverInfoList($hDevs, $tDevInfo) = 0
        Return SetError(@error, _SetupDiDestroyDeviceInfoList($hDevs) * 0, 0)
    Case _SetupDiSelectBestCompatDrv($hDevs, $tDevInfo) = 0
        Return SetError(@error, _SetupDiDestroyDeviceInfoList($hDevs) * 0, 0)
    Case _CM_Install_Selected_Driver($hDevs, $fBackup, $hWnd) = 0
        Return SetError(@error, _SetupDiDestroyDeviceInfoList($hDevs) * 0, 0)
    Case Else
        Return SetError(0, @extended + _SetupDiDestroyDeviceInfoList($hDevs) * 0, 1)
    EndSelect
EndFunc ;==>_CM_Install_Device_Driver

; #### FUNCTION ####
; =========================================================================
; Name  : _CM_Install_New_Device
; Description   : This function installs a new device.
; Parameter(s)  : $vGUID - An optional device class GUID.
;       : $hWnd - Window handle that owns the user interface, can be NULL.
; Return values : True if succeeded, otherwise FALSE. If a system reboot is requested to finish the device installation, @extended is set to non-zero.
; Author    : Pusofalse
; =========================================================================
Func _CM_Install_New_Device($vGUID = "", $hWnd = 0)
    Local $pGUID, $iResult, $tGUID

    Select
    Case IsDllStruct($vGUID)
        $pGUID = DllStructGetPtr($vGUID)
    Case IsString($vGUID)
        If StringLeft($vGUID, 1) & StringRight($vGUID, 1) = "{}" Then
            $tGUID = _CM_GUID_From_String($vGUID)
        Else
            $tGUID = _SetupDiClassGuidsFromName($vGUID)
        EndIf
        $pGUID = DllStructGetPtr($tGUID)
    EndSelect
    $iResult = DllCall($NEWDEV_DllHandle, "int", "InstallNewDevice", "hWnd", $hWnd, _
            "ptr", $pGUID, "dword*", 0)
    Return SetError(_CM_Get_Last_Error(), $iResult[3], $iResult[0])
EndFunc ;==>_CM_Install_New_Device

; #### FUNCTION ####
; =================================================================================
; Name  : _CM_Install_Selected_Device
; Description   : This function installs a device instance selected in device information set.
; Parameter(s)  : $hDevs    - Supplies a handle to the device information set.
;       : $hWnd - Window handle related to device installation, can be NULL.
; Return values : TRUE if succeeds (does not mean the device was installed or updated), FALSE if fails, @error returns the winerror code. If the device installation needs a system reboot, @extended is set to non-zero.
; Author    : Pusofalse
; =================================================================================
Func _CM_Install_Selected_Device($hDevs, $hWnd = 0)
    Local $iResult
    $iResult = DllCall($NEWDEV_DllHandle, "int", "InstallSelectedDevice", "hWnd", $hWnd, _
            "ptr", $hDevs, "dword*", 0)
    Return SetError(_CM_Get_Last_Error(), $iResult[3], $iResult[0])
EndFunc ;==>_CM_Install_Selected_Device

; #### FUNCION ####
; =================================================================================
; Name  : _CM_Install_DevInst_Ex
; Description   : This function is used to install a device instance.
; Parameter(s)  : $sDeviceID    - Supplies the device instance identifier string.
;       : $fUpdateDriver    - TRUE only newer or higher rank drivers are installed.
;       : $fSilent  - TRUE means "Found new device" dialog will not be displayed, default to display (FALSE).
;       : $hWnd - Window handle of the top-level window to use for any UI related to installing the device, can be NULL specified.
; Return values : TRUE is returned if succeeds (does not mean the device was installed or updated). FALSE otherwise. If the installation needs a system restart, @extended is set to non-zero.
; Author    : Pusofalse
; =================================================================================
Func _CM_Install_DevInst_Ex($sDeviceID, $fUpdateDriver, $fSilent = False, $hWnd = 0)
    Local $iResult
    $iResult = DllCall($NEWDEV_DllHandle, "int", "InstallDevInstEx", "hWnd", $hWnd, _
            "wstr", $sDeviceID, "int", $fUpdateDriver, "dword*", 0, "int", $fSilent)
    Return SetError(_CM_Get_Last_Error(), $iResult[4], $iResult[0])
EndFunc ;==>_CM_Install_DevInst_Ex

; #### FUNCTION ####
; =========================================================================
; Name  : _InstallNewDevice, obsolete, call _CM_Install_New_Device instead.
; Description   : This function installs a new device. The user is prompted to select the device.
; Parameter(s)  : $vGuid    - A vaiable-type value, indicates the GUID of the device class to install. If NULL is specified for this parameter, the user starts at the detection choice page, if non-NULL for this parameter, it must be in one of the following formats:
;       :   - Class name: NET/Display/Mouse...
;       :   - Class GUID string: {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
;       :   - Class GUID structure.
;       :   - Class GUID pointer.
;       : $hWndOwner    - A handle to the top-level window to be used for any required user interface, can set to NULL.
; Return values : If no error is occurred, returns true and sets @extended to a DWORD value indicates a system restart whether is requird (DI_NEEDREBOOT indicates the restart behavior is required), else returns false and sets @error to a system code.
; Author    : Pusofalse
; =========================================================================
Func _InstallNewDevice($vGuid = 0, $hWndOwner = 0)
    Local $iResult, $pGuid
    If IsString($vGuid) Then
        If (StringLeft($vGuid, 1) & StringRight($vGuid, 1) = "{}") Then
            $pGuid = DllStructGetPtr(_CM_GUID_From_String($vGuid))
        ElseIf $vGuid <> "" Then
            $tGuid = _SetupDiClassGuidsFromName($vGuid)
            $pGuid = DllStructGetPtr($tGuid)
        EndIf
    ElseIf IsDllStruct($vGuid) Then
        $pGuid = DllStructGetPtr($vGuid)
    ElseIf IsPtr($vGuid) Then
        $pGuid = $vGuid
    Else
        $pGuid = 0
    EndIf

    $iResult = DllCall($NEWDEV_DllHandle, "int", "InstallNewDevice", "hWnd", $hWndOwner, _
            "ptr", $pGuid, "dword*", 0)
    Return SetError(_CM_Get_Last_Error(), $iResult[3], $iResult[0])
EndFunc ;==>_InstallNewDevice

Func _SetupDiCreateDeviceInfo($hDevs, $sDeviceName, $vClassGuid, $iCreationFlags, ByRef $tSP_DEVINFO_DATA, $sDescr = "", $hWndParent = 0)
    Local $iResult, $tClassGuid, $pClassGuid, $pSP_DEVINFO_DATA

    If IsString($vClassGuid) Then
        If (StringLeft($vClassGuid, 1) & StringRight($vClassGuid, 1) = "{}") Then
            $pClassGuid = DllStructGetPtr(_CM_GUID_From_String($vClassGuid))
        ElseIf ($vClassGuid) <> "" Then
            $tClassGuid = _SetupDiClassGuidsFromName($vClassGuid)
            $pClassGuid = DllStructGetPtr($tClassGuid)
        EndIf
    ElseIf IsDllStruct($vClassGuid) Then
        $pClassGuid = DllStructGetPtr($vClassGuid)
    ElseIf IsPtr($vClassGuid) Then
        $pClassGuid = ($vClassGuid)
    Else
        $pClassGuid = 0
    EndIf
    If $pClassGuid = 0 Then Return SetError(87, 0, 0)

    $tClassGuid = DllStructCreate("byte[16]", $pClassGuid)

    If Not IsDllStruct($tSP_DEVINFO_DATA) Then
        $tSP_DEVINFO_DATA = DllStructCreate($tagSP_DEVICEINFO_DATA)
        DllStructSetData($tSP_DEVINFO_DATA, "Size", 28)
        DllStructSetData($tSP_DEVINFO_DATA, "Guid", DllStructGetData($tClassGuid, 1))
    EndIf
    $pSP_DEVINFO_DATA = DllStructGetPtr($tSP_DEVINFO_DATA)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiCreateDeviceInfo", _
            "ptr", $hDevs, "str", $sDeviceName, "ptr", $pClassGuid, _
            "str", $sDescr, "hWnd", $hWndParent, "dword", $iCreationFlags, _
            "ptr", $pSP_DEVINFO_DATA)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiCreateDeviceInfo

Func _SetupDiGetDevNodeStatus($hDevInst)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_DevNode_Status", _
            "ulong*", 0, "ulong*", 0, "dword", $hDevInst, "ulong", 0)
    Return SetError($iResult[0], $iResult[2], $iResult[1])
EndFunc ;==>_SetupDiGetDevNodeStatus

; #### FUNCTOIN ####
; =========================================================================
; Name  : _SetupDiChangeState
; Description   : Default handler of DIF_PROPERCHANGE.
; Parameter(s)  : $hDevs    - A pointer to a device information set that contains the device information element.
;       : $pSP_DEVINFO_DATA - A pointer to an SP_DEVINFO_DATA structure contains the device information element for which to change the state.
; Return values : TRUE is returned if succeeds, FALSE otherwise, the logged error can be get in @error macro.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiChangeState($hDevs, $pSP_DEVINFO_DATA)
    Local $iResult
    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiChangeState", "hWnd", $hDevs, _
            "ptr", $pSP_DEVINFO_DATA)
    Return SetError(_CM_Get_Last_Error(), 0, $iResult[0])
EndFunc ;==>_SetupDiChangeState

; ##### FUNCTION ####
; =========================================================================
; Name  : _SetupDiSetClassInstallParams
; Description   : Sets the installation parameters for a device class.
; Parameter(s)  : $hDevs    - Supplies a handle to the device information set.
;       : $pSP_DEVINFO_DATA - A pointer to an SP_DEVINFO_DATA structure contains the device information set.
;       : $pInst    - A pointer to an SP_CLASSINSTALL_PARAMS structure contains the data to be set.
;       : $iSizeInst    - Size of the $pInst.
; Return values : TRUE is returned if succeeds, FALSE otherwise, in which case, @error is set to the reason of the failure.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiSetClassInstallParams($hDevs, $pSP_DEVINFO_DATA, $pInst, $iSizeInst)
    Local $iResult

    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    If IsDllStruct($pInst) Then $pInst = DllStructGetPtr($pInst)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiSetClassInstallParams", _
            "ptr", $hDevs, "ptr", $pSP_DEVINFO_DATA, _
            "ptr", $pInst, "dword", $iSizeInst)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiSetClassInstallParams

; #### FUNCTION ####
; =========================================================================
; Name  : _SetupDiDeviceInstallParams
; Description   : This function sets the installation parameters for a device instance.
; Parameter(s)  : $hDevs    - A handle to the device information set.
;       : $pSP_DEVINFO_DATA - A pointer to an SP_DEVINFO_DATA.
;       : $pSP_DEVINSTALL_PARAMS - A pointer to an SP_DEVINSTALL_PARAMS, contains the installation parameters.
; Return values : True indicates success, False to failure, in this case, @error is set to a system error code.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiSetDeviceInstallParams($hDevs, $pSP_DEVINFO_DATA, $pSP_DEVINSTALL_PARAMS)
    Local $iResult
    Select
    Case IsDllStruct($pSP_DEVINFO_DATA)
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
        ContinueCase
    Case IsDllStruct($pSP_DEVINSTALL_PARAMS)
        $pSP_DEVINSTALL_PARAMS = DllStructGetPtr($pSP_DEVINSTALL_PARAMS)
    EndSelect
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiSetDeviceInstallParams", _
            "ptr", $hDevs, "ptr", $pSP_DEVINFO_DATA, _
            "ptr", $pSP_DEVINSTALL_PARAMS)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiSetDeviceInstallParams

; #### FUNCTION ####
; =========================================================================
; Name  : _SetupDiEnumDeviceInterfaces
; Description   : This function enumerates the device interfaces for a device instance.
; Parameter(s)  : $hDevs    - A device information set handle.
;       : $pSP_DEVINFO_DATA - A pointer to an SP_DEVINFO_DATA, can be ZERO specified.
;       : $vGUID - GUID for device setup interface.
;       : $iIndex   - Specifies the index to enumerate, zero-based.
;       : $tSP_DEVIFINFO_DATA - Supplies a variable receives a SP_DEVINTERFACE_DATA structure contains the device interface.
; Return values : TRUE is returned if succeeds, FALSE otherwise. If the enumeration is finished, @error is set to 259.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiEnumDeviceInterfaces($hDevs, $pSP_DEVINFO_DATA, $vGuid, $iIndex, ByRef $tSP_DEVIFINFO_DATA)
    Local $iResult, $pSP_DEVIFINFO

    If IsString($vGuid) Then
        If StringLeft($vGuid, 1) & StringRight($vGuid, 1) = "{}" Then
            Local $tGUID = _CM_GUID_From_String($vGuid)
            $pGuid = DllStructGetPtr($tGUID)
        ElseIf $vGuid <> "" Then
            $tGuid = _SetupDiClassGuidsFromName($vGuid)
            $pGuid = DllStructGetPtr($tGuid)
        EndIf
    ElseIf IsDllStruct($vGuid) Then
        $pGuid = DllStructGetPtr($vGuid)
    ElseIf IsPtr($vGuid) Then
        $pGuid = $vGuid
    Else
        $pGuid = 0
    EndIf
    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    If Not IsDllStruct($tSP_DEVIFINFO_DATA) Then
        $tSP_DEVIFINFO_DATA = DllStructCreate($tagSP_DEV_INTERFACE_DATA)
        DllStructSetData($tSP_DEVIFINFO_DATA, "Size", 28)
    EndIf
    $pSP_DEVIFINFO = DllStructGetPtr($tSP_DEVIFINFO_DATA)

    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiEnumDeviceInterfaces", "hWnd", $hDevs, _
            "ptr", $pSP_DEVINFO_DATA, "ptr", $pGuid, "dword", $iIndex, _
            "ptr", $pSP_DEVIFINFO)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiEnumDeviceInterfaces

Func _SetupDiGetDeviceInterfaceDetail($hDevs, $pSP_DEVIFINFO_DATA, ByRef $tSP_DEVINFO_DATA)
    Local $iResult, $pBuffer, $tBuffer, $sDevicePath, $iSysError = 0, $pSP_DEVINFO_DATA

    Select
    Case Not IsDllStruct($tSP_DEVINFO_DATA)
        $tSP_DEVINFO_DATA = DllStructCreate($tagSP_DEVICEINFO_DATA)
        DllStructSetData($tSP_DEVINFO_DATA, "Size", 28)
        ContinueCase
    Case IsDllStruct($pSP_DEVIFINFO_DATA)
        $pSP_DEVIFINFO_DATA = DllStructGetPtr($pSP_DEVIFINFO_DATA)
    EndSelect

    $pSP_DEVINFO_DATA = DllStructGetPtr($tSP_DEVINFO_DATA)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetDeviceInterfaceDetail", _
            "hWnd", $hDevs, "ptr", $pSP_DEVIFINFO_DATA, _
            "ptr", 0, "dword", 0, "dword*", 0, "ptr", $pSP_DEVINFO_DATA)
    $tBuffer = DllStructCreate("dword;char[" & $iResult[5] - 4 & "]")
    $pBuffer = DllStructGetPtr($tBuffer)
    DllStructSetData($tBuffer, 1, 5)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetDeviceInterfaceDetail", _
            "hWnd", $hDevs, "ptr", $pSP_DEVIFINFO_DATA, _
            "ptr", $pBuffer, "dword", $iResult[5], "dword*", 0, _
            "ptr", $pSP_DEVINFO_DATA)
    If $iResult[0] = 0 Then
        $iSysError = _CM_Get_Last_Error()
    Else
        $sDevicePath = DllStructGetData($tBuffer, 2)
    EndIf
    Return SetError($iSysError, _SetupDiApiBufferFree($tBuffer) or $iResult[0], $sDevicePath)
EndFunc ;==>_SetupDiGetDeviceInterfaceDetail

; #### FUNCTION ####
; =========================================================================
; Name  : _SetupDiDestroyDeviceInfoList
; Description   : Release a device information set.
; Parameter(s)  : $hDevs    - Supplies a handle to the device information set, typically obtained by the following functions:
;       :       _SetupDiCreateDeviceDevs
;       :       _SetupDiCreateDeviceDevsEx
;       :       _SetupDiCreateDeviceInfo
;       :       _SetupDiCreateDeviceInfoEx
;       :       _SetupDiGetClassDevs
;       :       _SetupDiGetClassDevsEx
; Return values : TRUE indicates success, FALSE indicates failure.
; Author    : Pusofalse
; =========================================================================
Func _SetupDiDestroyDeviceInfoList($hDevs)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiDestroyDeviceInfoList", "hWnd", $hDevs)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiDestroyDeviceInfoList


Func _SetupDiGetHwProfileList()
    Local $iResult, $tBuffer, $pBuffer, $aResult[1][2] = [[0]]

    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetHwProfileList", "ptr", 0, _
            "dword", 0, "dword*", 0, "dword*", 0)
    If $iResult[3] = 0 Then Return SetError(_CM_Get_Last_Error(), -1, $aResult)

    $tBuffer = DllStructCreate("dword ProfileID[" & $iResult[3] & "]")
    $pBuffer = DllStructGetPtr($tBuffer)

    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetHwProfileList", "ptr", $pBuffer, _
            "dword", $iResult[3], "dword*", 0, "dword*", 0)
    If $iResult[0] = 0 Then Return SetError(_CM_Get_Last_Error(), -1, $aResult)
    $aResult[0][0] = $iResult[3]
    Redim $aResult[$iResult[3] + 1][2]
    For $i = 1 to $iResult[3]
        $aResult[$i][0] = DllStructGetData($tBuffer, "ProfileID", $i)
        $aResult[$i][1] = _SetupDiGetHwProfileFriendlyName($aResult[$i][1])
    Next
    Return SetExtended(_SetupDiApiBufferFree($tBuffer) + $iResult[4], $aResult)
EndFunc ;==>_SetupDiGetHwProfileList

Func _SetupDiGetHwProfileFriendlyName($iProfileID = 0)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetHwProfileFriendlyName", _
            "dword", $iProfileID, "ptr", 0, "dword", 0, "dword*", 0)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetHwProfileFriendlyName", _
            "dword", $iProfileID, "str", "", "dword", $iResult[4], "dword*", 0)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[2])
EndFunc ;==>_SetupDiGetHwProfileFriendlyName

; #### FUNCTION (internal used only) ####
; =========================================================================
; _CM_Free_Variable is used to free a dll-structure-typed variable.
; =========================================================================
Func _CM_Free_Variable(ByRef $vVariable)
    $vVariable = 0
EndFunc ;==>_CM_Free_Variable

; #### FUNCTION ####
; =========================================================================
; Name  : _CM_Get_Child
; Description   : Retrieves the first child device instance for a specified devnode, on local system.
; Parameter(s)  : $hDevInst - A handle to the device instance.
; Return values : Handle to the first child device instance is returned if success, or zero if failure.
; Related   : _CM_Get_Child_Ex, _CM_Get_Parent, _CM_Get_Sibling
; Author    : Pusofalse
; =========================================================================
Func _CM_Get_Child($hDevInst)
    Local $iResult

    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Child", "dword*", 0, _
            "dword", $hDevInst, "ulong", 0)
    Return SetError($iResult[0], $iResult[0] = 0, $iResult[1])
EndFunc ;==>_CM_Get_Child

; #### FUNCTION ####
; =========================================================================
; Name  : _CM_Get_Parent
; Description   : Retrieves the parent node for a device instance in device tree, on local system.
; Parameter(s)  : $hDevInst - A device instance handle for which to retrieve the parent node.
; Return values : Handle to the parent node is returned if success, otherwise returns a value less one.
; Author    : Pusofalse
; =========================================================================
Func _CM_Get_Parent($hDevInst)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Parent", "dword*", 0, _
            "dword", $hDevInst, "ulong", 0)
    Return SetError($iResult[0], $iResult[0] = 0, $iResult[1])
EndFunc ;==>_CM_Get_Parent

Func _CM_Get_Sibling($hDevInst)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Sibling", "dword*", 0, _
            "dword", $hDevInst, "ulong", 0)
    Return SetError($iResult[0], $iResult[0] = 0, $iResult[1])
EndFunc ;==>_CM_Get_Sibling

Func _CM_Get_Depth($hDevInst)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Depth", "dword*", 0, _
            "dword", $hDevInst, "ulong", 0)
    Return SetError($iResult[0], $iResult[0] = 0, $iResult[1])
EndFunc ;==>_CM_Get_Depth

Func _CM_Get_Device_ID($hDevInst)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Device_ID", "dword", $hDevInst, _
            "str", "", "dword", _CM_Get_Device_ID_Size($hDevInst) + 1, "ulong", 0)
    Return SetError(_CM_Get_Last_Error(), $iResult[0] = 0, $iResult[2])
EndFunc ;==>_CM_Get_Device_ID

Func _CM_Get_Device_ID_Size($hDevInst)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Device_ID_Size", "ulong*", 0, _
            "dword", $hDevInst, "ulong", 0)
    Return SetError($iResult[0], 0, $iResult[1])
EndFunc ;==>_CM_Get_Device_ID_Size

; #### FUNCTION ####
; ===================================================================================
; Name  : _CM_Get_Device_ID_List
; Description   : This function retrieves the device ID strings for the device instance in an array, on the local system.
; Parameter(s)  : See _CM_Get_Device_ID_List_Ex for details.
; Return values : The return value is same to _CM_Get_Device_ID_List_Ex's.
; Author    : Pusofalse
; ===================================================================================
Func _CM_Get_Device_ID_List($sFilter = "", $iFlags = $CM_GETIDLIST_FILTER_NONE)
    Local $iResult, $iLength, $aResult[1] = [0], $pBuffer, $tBuffer, $iPointer, $pBuffer1, $iLength2

    $iLength = _CM_Get_Device_ID_List_Size($sFilter, $iFlags) + 1
    If $iLength < 2 Then Return SetError(@error, 0, $aResult)
    $pBuffer = _CM_Heap_Alloc($iLength)

    Do
        $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Device_ID_List", "str", $sFilter, _
                "ptr", $pBuffer, "ulong", $iLength, "ulong", $iFlags)
        If $iResult[0] = $CR_BUFFER_SMALL Then
            _CM_Heap_Free($pBuffer)
            $iLength += 2
            $pBuffer = _CM_Heap_Alloc($iLength + 128)
        EndIf
    Until   $iResult[0] <> $CR_BUFFER_SMALL
    $pBuffer1 = $pBuffer

    While $iPointer < $iLength
        $tBuffer = DllStructCreate("char DeviceID[512]", $pBuffer)
        $aResult[0] += 1
        Redim $aResult[$aResult[0] + 1]
        $aResult[$aResult[0]] = DllStructGetData($tBuffer, "DeviceID")
        If $aResult[$aResult[0]] = "" Then ExitLoop
        $iLength2 = StringLen($aResult[$aResult[0]]) + 1
        $iPointer += $iLength2
        $pBuffer += $iLength2
    WEnd

    _CM_Heap_Free($pBuffer1)
    If $aResult[0] = 0 Then Return SetError($iResult[0], 0, $aResult)
    $aResult[0] -= 1
    Redim $aResult[$aResult[0] + 1]
    Return SetError($iResult[0], 0, $aResult)
EndFunc ;==>_CM_Get_Device_ID_List

; #### FUNCTION ####
; ===================================================================================
; Name  : _CM_Get_Device_ID_List_Size
; Description   : Return the buffer length required to hold the device ID strings.
; Parameter(s)  : See _CM_Get_Device_ID_List_Size_Ex for details.
; Return values : Length required.
; Author    : Pusofalse
; ===================================================================================
Func _CM_Get_Device_ID_List_Size($sFilter = "", $iFlags = $CM_GETIDLIST_FILTER_NONE)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Device_ID_List_Size", "ulong*", 0, _
            "str", $sFilter, "ulong", $iFlags)
    Return SetError($iResult[0], 0, $iResult[1])
EndFunc ;==>_CM_Get_Device_ID_List_Size

; #### FUNCTION ####
; ===================================================================================
; Name  : _CM_Enumerate_Enumerators
; Description   : Lists the device enumerators on the local system.
; Parameter(s)  : This function has no parameters.
; Return values : If succeeds, returns an array with following format:
;       :   - $aArray[0] - The number of returned entries.
;       :   - $aArray[1] - 1st enumerator's name.
;       :   - $aArray[2] - 2nd enumerator's name.
;       :   - ... ...
; Author    : Pusofalse
; ===================================================================================
Func _CM_Enumerate_Enumerators()
    Local $aResult[1] = [0], $iResult

    While 1
        $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Enumerate_Enumerators", _
                "ulong", $aResult[0], "str", "", "ulong*", 32, "ulong", 0)
        If $iResult[0] Then ExitLoop
        $aResult[0] += 1
        Redim $aResult[$aResult[0] + 1]
        $aResult[$aResult[0]] = $iResult[2]
    WEnd
    Return SetError($iResult[0], 0, $aResult)
EndFunc ;==>_CM_Enumerate_Enumerators

; #### FUNCTION ####
; ===================================================================================
; Name  : _CM_Enumerate_Classes
; Description   : This function lists the device setup classes on the local system.
; Parameter(s)  : This function has no parameters.
; Return values : An array in the following form:
;       :   - $aArray[0][0] - The number of returned classes.
;       :   - $aArray[1][0] - The GUID of 1st class, in string format.
;       :   - $aArray[1][1] - Description for 1st class.
;       :   - $aArray[2][0] - The GUID of 2nd class, in string format.
;       :   - $aArray[2][1] - Description for 2nd class.
;       :   - ... ...
; Author    : Pusofalse
; ===================================================================================
Func _CM_Enumerate_Classes()
    Local $iResult, $pGUID, $aResult[1][2] = [[0]]

    $pGUID = _CM_Heap_Alloc(32)
    While 1
        $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Enumerate_Classes", _
                "ulong", $aResult[0][0], "ptr", $pGUID, "ulong", 0)
        If $iResult[0] = $CR_NO_SUCH_VALUE Then ExitLoop
        $aResult[0][0] += 1
        Redim $aResult[$aResult[0][0] + 1][2]
        $aResult[$aResult[0][0]][0] = _CM_String_From_GUID($pGUID)
        $aResult[$aResult[0][0]][1] = _SetupDiGetClassDescription($pGUID)
    WEnd
    Return SetError($iResult[0], _CM_Heap_Free($pGUID), $aResult)
EndFunc ;==>_CM_Enumerate_Classes

Func _CM_Get_DevNode_Status($hDevInst)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_DevNode_Status", _
            "ulong*", 0, "ulong*", 0, "dword", $hDevInst, "ulong", 0)
    Return SetError($iResult[0], $iResult[2], $iResult[1])
EndFunc ;==>_CM_Get_DevNode_Status


Func _CM_Request_Device_Eject($hDevInst, ByRef $sVetoName)
    Local $iResult, $hToken
    Local $aPriv[2][2] = [[$SE_UNDOCK_NAME, 2], [$SE_LOAD_DRIVER_NAME, 2]]

    $hToken = _OpenProcessToken(-1)
    _AdjustTokenPrivileges($hToken, $aPriv)
    _LsaCloseHandle($hToken)

    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Request_Device_Eject", "dword", $hDevInst, _
            "int*", 0, "str", "", "ulong", 260, "ulong", 0)
    $sVetoName = $iResult[3]
    Return SetError($iResult[0], $iResult[2], $iResult[0] = 0)
EndFunc ;==>_CM_Request_Device_Eject

Func _CM_Query_And_Remove_SubTree($hDevInst, $iFlags, ByRef $sVeto)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Query_And_Remove_SubTree", _
            "dword", $hDevInst, "int*", 0, "str", "", "ulong", 260, "ulong", $iFlags)
    $sVeto = $iResult[3]
    Return SetError($iResult[0], $iResult[2], $iResult[0] = 0)
EndFunc ;==>_CM_Query_And_Remove_SubTree


Func _CM_Get_Device_Interface_List_Size($pInterfaceClassGuid, $sDevId = "", $iFlags = 0)
    Local $iResult

    If IsDllStruct($pInterfaceClassGuid) Then
        $pInterfaceClassGuid = DllStructGetPtr($pInterfaceClassGuid)
    ElseIf IsString($pInterfaceClassGuid) Then
        Local $tGUID = _CM_GUID_From_String($pInterfaceClassGuid)
        $pInterfaceClassGuid = DllStructGetPtr($tGUID)
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Device_Interface_List_Size", _
            "ulong*", 0, "ptr", $pInterfaceClassGuid, "str", $sDevId, "ulong", $iFlags)
    Return SetError($iResult[0], $iResult[0] = 0, $iResult[1])
EndFunc ;==>_CM_Get_Device_Interface_List_Size

Func _CM_Get_Device_Interface_List($pInterfaceClassGuid, $sDevId = "", $iFlags = 0)
    Local $iResult, $iLength, $tBuffer, $pBuffer, $pBuffer1, $aResult[1] = [0], $iLen

    If IsDllStruct($pInterfaceClassGuid) Then
        $pInterfaceClassGuid = DllStructGetPtr($pInterfaceClassGuid)
    ElseIf IsString($pInterfaceClassGuid) Then
        Local $tGUID = _CM_GUID_From_String($pInterfaceClassGuid)
        $pInterfaceClassGuid = DllStructGetPtr($tGUID)
    EndIf
    $iLength = _CM_Get_Device_Interface_List_Size($pInterfaceClassGuid, $sDevId, $iFlags)
    $tBuffer = DllStructCreate("char ID[" & $iLength & "]") - 1
    $pBuffer = DllStructGetPtr($tBuffer)
    $pBuffer1 = $pBuffer + $iLength

    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Device_Interface_List", _
            "ptr", $pInterfaceClassGuid, "str", $sDevId, "ptr", $pBuffer, _
            "ulong", $iLength, "ulong", $iFlags)

    While Number($pBuffer) < Number($pBuffer1) - 1
        $aResult[0] += 1
        Redim $aResult[$aResult[0] + 1]
        $aResult[$aResult[0]] = DllStructGetData($tBuffer, "ID")
        $pBuffer += StringLen($aResult[$aResult[0]]) + 1
        $iLength -= StringLen($aResult[$aResult[0]]) + 1
        $tBuffer = 0
        $tBuffer = DllStructCreate("char ID[" & $iLength & "]", $pBuffer)
    WEnd
    Return SetError($iResult[0], _CM_Free_Variable($tBuffer), $aResult)
EndFunc ;==>_CM_Get_Device_Interface_List


Func _CM_Get_Next_Res_Des(ByRef $iResDes, $iResourceID)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Next_Res_Des", _
            "long*", 0, "long", $iResDes, "long", $iResourceID, _
            "long*", 0, "ulong", 0)
    If $iResult[0] Then Return SetError($iResult[0], 0, 0)
    _CM_Free_Res_Des_Handle($iResDes)
    $iResDes = $iResult[1]
    Return SetExtended($iResult[4], 1)
EndFunc ;==>_CM_Get_Next_Res_Des

Func _CM_Get_Res_Des_Data_Size(ByRef $iResDes)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Res_Des_Data_Size", _
            "ulong*", 0, "long", $iResDes, "ulong", 0)
    Return SetError($iResult[0], $iResult[0] = 0, $iResult[1])
EndFunc ;==>_CM_Get_Res_Des_Data_Size

Func _CM_Get_Res_Des_Data(ByRef $iResDes)
    Local $pBuffer, $iLength, $iResult

    $iLength = _CM_Get_Res_Des_Data_Size($iResDes)
    $pBuffer = _CM_Heap_Alloc($iLength)

    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Res_Des_Data", _
            "long", $iResDes, "ptr", $pBuffer, "ulong", $iLength, "ulong", 0)
    Return SetError($iResult[0], ($iResult[0] = 0), $pBuffer)
EndFunc ;==>_CM_Get_Res_Des_Data

; #### FUNCTION ####
; ================================================================================
; Function      : Obsolete, do not use. Call _CM_Get_Device_Resources_Ex instead.
; ================================================================================
Func _CM_Get_Device_Resources($hDevInst, $iResourceType)
    Local $hConf, $aResult[1] = [0], $pBuffer, $tagStructure, $tBuffer

    Switch $iResourceType
    Case $RESTYPE_IO
        $tagStructure = $tagIO_DES
    Case $RESTYPE_MEM
        $tagStructure = $tagMEM_DES
    Case $RESTYPE_IRQ
        $tagStructure = $tagIRQ_DES
    Case $RESTYPE_DMA
        $tagStructure = $tagDMA_DES
    Case $RESTYPE_BUSNUMBER
        $tagStructure = $tagBUSNUMBER_DES
    Case Else
        Return SetError(50, 0, $aResult)
    EndSwitch

    $hConf = _CM_Get_First_Log_Conf($hDevInst, 2)
    If @error or $hConf = 0 Then Return SetError(@error, 0, $aResult)

    While _CM_Get_Next_Res_Des($hConf, $iResourceType)
        $aResult[0] += 1
        Redim $aResult[$aResult[0] + 1]
        $pBuffer = _CM_Get_Res_Des_Data($hConf)
        $tBuffer = DllStructCreate($tagStructure, $pBuffer)
        Switch $iResourceType
        Case $RESTYPE_MEM, $RESTYPE_IO, $RESTYPE_BUSNUMBER
            $aResult[$aResult[0]] &= "0x" & Hex(DllStructGetData($tBuffer, "AllocBase"))
            $aResult[$aResult[0]] &= " - 0x" & Hex(DllStructGetData($tBuffer, "AllocEnd"))
        Case $RESTYPE_IRQ
            $aResult[$aResult[0]] = DllStructGetData($tBuffer, "AllocNum")
        Case $RESTYPE_DMA
            $aResult[$aResult[0]] = DllStructGetData($tBuffer, "AllocChannel")
        EndSwitch
        _CM_Heap_Free($pBuffer)
        _CM_Free_Variable($tBuffer)
    WEnd
    Return $aResult
EndFunc ;==>_CM_Get_Device_Resources

Func _CM_Get_First_Log_Conf($hDevInst, $iFlags)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_First_Log_Conf", "long*", 0, _
            "dword", $hDevInst, "ulong", $iFlags)
    Return SetError($iResult[0], $iResult[0] = 0, $iResult[1])
EndFunc ;==>_CM_Get_First_Log_Conf

Func _CM_Get_Process_Heap()
    Local $iResult
    $iResult = DllCall($Kernel32_DllHandleA, "long", "GetProcessHeap")
    Return $iResult[0]
EndFunc ;==>_CM_Get_Process_Heap

Func _CM_Heap_Alloc($iLength, $iFlags = 8)
    If $iLength < 1 Then Return 0

    Local $pMem, $hHeap = _CM_Get_Process_Heap()
    $pMem = DllCall($Kernel32_DllHandleA, "ptr", "HeapAlloc", "hWnd", $hHeap, _
            "dword", $iFlags, "dword", $iLength)
    Return $pMem[0]
EndFunc ;==>_CM_Heap_Alloc

Func _CM_Heap_Free(ByRef $pMem)
    If $pMem < 1 Then Return SetError(87, 0, False)

    Local $iResult, $hHeap = _CM_Get_Process_Heap()
    $iResult = DllCall($Kernel32_DllHandleA, "int", "HeapFree", "hWnd", $hHeap, _
            "dword", 0, "ptr", $pMem)
    If $iResult[0] Then $pMem = Ptr(0)
    Return $iResult[0] <> 0
EndFunc ;==>_CM_Heap_Free

Func _CM_Heap_Size($pMem)
    If $pMem < 1 Then Return SetError(87, 0, 0)

    Local $iResult, $hHeap = _CM_Get_Process_Heap()
    $iResult = DllCall($Kernel32_DllHandleA, "long", "HeapSize", "hWnd", $hHeap, _
            "dword", 0, "ptr", $pMem)
    Return $iResult[0]
EndFunc ;==>_CM_Heap_Size

Func _CM_Modify_Res_Des($iResDes, $iResourceID, $pData, $iLength)
    Local $iResult

    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Modify_Res_Des", "long*", 0, _
            "long", $iResDes, "long", $iResourceID, "ptr", $pData, _
            "ulong", $iLength, "ulong", 0)
    Return SetError($iResult[0], $iResult[0] = 0, $iResult[0] = 0)
EndFunc ;==>_CM_Modify_Res_Des

Func _CM_Free_Res_Des(ByRef $iResDes)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Free_Res_Des", "long*", 0, _
            "ulong", $iResDes, "ulong", 0)
    Return SetError($iResult[0], $iResult[0] = 0, $iResult[1])
EndFunc ;==>_CM_Free_Res_Des

Func _CM_Free_Res_Des_Handle(ByRef $iResDes)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Free_Res_Des_Handle", "long", $iResDes)
    Return SetError($iResult[0], $iResult[0] = 0, $iResult[0] = 0)
EndFunc ;==>_CM_Free_Res_Des_Handle

Func _CM_Free_Log_Conf(ByRef $hLogConf)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Free_Log_Conf", "long", $hLogConf, "long", 0)
    Return SetError($iResult[0], $iResult[0] = 0, $iResult[0] = 0)
EndFunc ;==>_CM_Free_Log_Conf

Func _CM_Free_Log_Conf_Handle(ByRef $hLogConf)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Free_Log_Conf_Handle", "long", $hLogConf)
    Return SetError($iResult[0], $iResult[0] = 0, $iResult[0] = 0)
EndFunc ;==>_CM_Free_Log_Conf_Handle

Func _CM_Add_Res_Des(ByRef $hLogConf, $iResourceID, $pData, $iLength)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Add_Res_Des", "long*", 0, _
            "long", $hLogConf, "long", $iResourceID, "ptr", $pData, _
            "ulong", $iLength, "ulong", 0)
    Return SetError($iResult[0], $iResult[0] = 0, $iResult[1])
EndFunc ;==>_CM_Add_Res_Des

Func _CM_Get_Next_Log_Conf(ByRef $hLogConf)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Next_Log_Conf", "long*", 0, _
            "long", $hLogConf, "ulong", 0)
    If $iResult[0] Then Return SetError($iResult[0], 0, 0)
    _CM_Free_Log_Conf_Handle($hLogConf)
    $hLogConf = $iResult[1]
    Return SetExtended(1, 1)
EndFunc ;==>_CM_Get_Next_Log_Conf

Func _CM_Get_Last_Error()
    Local $iResult
    $iResult = DllCall($Kernel32_DllHandleA, "long", "GetLastError")
    Return $iResult[0]
EndFunc ;==>_CM_Get_Last_Error

Func _CM_GUID_From_String($sGUID)
    Local $tGUID = DllStructCreate("byte Guid[16]"), $iResult

    $iResult = DllCall("Ole32.dll", "int", "CLSIDFromString", "wstr", $sGUID, "ptr", DllStructGetPtr($tGUID))
    Return SetError($iResult[0], 0, $tGUID)
EndFunc ;==>_CM_GUID_From_String

Func _CM_String_From_GUID($pGUID)
    Local $iResult

    If IsDllStruct($pGUID) Then $pGUID = DllStructGetPtr($pGUID)
    $iResult = DllCall("Ole32.dll", "int", "StringFromGUID2", _
            "ptr", $pGUID, "wstr", "", "int", 128)
    Return $iResult[2]
EndFunc ;==>_CM_String_From_GUID

; #### FUNCTION ####
; ===================================================================================
; Name  : _CM_Device_IO_Control
; Description   : Control a device.
; Parameter(s)  : $hDevice  - Handle to the device, returned by _CM_Create_File.
;       : $iCtrlCode    - Control code.
;       : $pIn  - A pointer to a buffer as a IN parameter.
;       : $iSizeIn  - Size of $pIn.
;       : $pOut - A pointer to a buffer as a OUT parameter.
;       : $iSizeOut - Size of $pOut.
;       : $pOverlapped  - A pointer to a OVERLAPPED structure, if $hDevice is created without OVERLAPPED flag, this parameter can be NULL.
; Return values : Returns TRUE if succeeds, otherwise returns FALSE.
; Author    : Pusofalse
; ===================================================================================
Func _CM_Device_IO_Control($hDevice, $iCtrlCode, $pIn, $iSizeIn, $pOut, $iSizeOut, $pOverlapped = 0)
    Local $iResult

    If IsDllStruct($pIn) Then $pIn = DllStructGetPtr($pIn)
    If IsDllStruct($pOut) Then $pOut = DllStructGetPtr($pOut)
    If IsDllStruct($pOverlapped) Then $pOverlapped = DllStructGetPtr($pOverLapped)
    $iResult = DllCall($Kernel32_DllHandleA, "int", "DeviceIoControl", "ptr", $hDevice, _
            "dword", $iCtrlCode, "ptr", $pIn, "dword", $iSizeIn, _
            "ptr", $pOut, "dword", $iSizeOut, "int*", 0, "ptr", $pOverlapped)
    Return SetError(_CM_Get_Last_Error(), $iResult[7], $iResult[0])
EndFunc ;==>_CM_Device_IO_Control

Func _CM_Write_Device($hFile, $pBuffer, $iSizeofBuffer, $pOverlap = 0, $sBufferType = "ptr")
    Local $iResult

    If IsDllStruct($pBuffer) Then $pBuffer = DllStructGetPtr($pBuffer)
    $iResult = DllCall($Kernel32_DllHandleA, "int", "WriteFile", "hWnd", $hFile, _
            $sBufferType, $pBuffer, "dword", $iSizeofBuffer, _
            "dword*", 0, "ptr", $pOverlap)
    If @error Then Return SetError(1, 0, 0)
    Return SetError(_CM_Get_Last_Error(), $iResult[4], $iResult[0])
EndFunc ;==>_CM_Write_Device

Func _CM_Read_Device($hFile, $pBuffer, $iSizeofBuffer, $pOverlap = 0)
    Local $iResult

    $iResult = DllCall($Kernel32_DllHandleA, "int", "ReadFile", "hWnd", $hFile, _
            "ptr", $pBuffer, "dword", $iSizeofBuffer, "dword*", 0, "ptr", $pOverlap)
    Return SetError(_CM_Get_Last_Error(), $iResult[4], $iResult[0])
EndFunc ;==>_CM_Read_Device

Func _CM_Create_File($sFile, $iAccess, $iShare, $pSecurAttr, $iCreation, $iFlags, $hTemplate = 0)
    Local $iResult

    $iResult = DllCall($Kernel32_DllHandleA, "long", "CreateFile", "str", $sFile, _
            "dword", $iAccess, "dword", $iShare, "ptr", $pSecurAttr, _
            "dword", $iCreation, "dword", $iFlags, "long", $hTemplate)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_CM_Create_File

Func _CM_Open_File(Byref $hFile, $iDesiredAccess, $pObject, $iShareAccess, $iFlags)
    Local $iResult, $pIO = _CM_Heap_Alloc(16)

    $iResult = DllCall("Ntdll.dll", "dword", "NtOpenFile", "hWnd*", 0, "dword", $iDesiredAccess, _
            "ptr", $pObject, "ptr", $pIO, "ulong", $iShareAccess, "ulong", $iFlags)
    $hFile = $iResult[1]
    _CM_Heap_Free($pIO)
    Return SetError(_LsaNtStatusToWinError($iResult[0]), 0, $iResult[0] = 0)
EndFunc ;==>_CM_Open_File

Func _CM_Open_Device(ByRef $hDevice, $hDevInst, $iDesiredAccess, $iShareAccess, $iFlags)
    Local $sPhysName, $pObject, $tBuffer, $iSysError, $fResult, $pBufferW

    $sPhysName = _CM_Get_DevNode_Registry_Property($hDevInst, 0xF)
    If $sPhysName = "" Then Return SetError(@error, 0, 0)

    $pObject = _LsaInitializeObjectAttributes($sPhysName)
    $fResult = _CM_Open_File($hDevice, $iDesiredAccess, $pObject, $iShareAccess, $iFlags)
    $iSysError = @error
    $tBuffer = DllStructCreate($tagOBJECT_ATTRIBUTES, $pObject)
    $pBufferW = DllStructGetData($tBuffer, "BufferW")
    _CM_Heap_Free($pBufferW)
    _CM_Heap_Free($pObject)
    _CM_Free_Variable($tBuffer)
    Return SetError($iSysError, 0, $fResult)
EndFunc ;==>_CM_Open_Device

Func _CM_Close_Handle($hHandle)
    Local $iResult
    $iResult = DllCall($Kernel32_DllHandleA, "int", "CloseHandle", "long", $hHandle)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_CM_Close_Handle

Func _CM_Assign_Var(ByRef $vVariable, $vValue = 0, $vReturn = "", $iError = 0, $iExtended = 0)
    $vVariable = $vValue
    Return SetError($iError, $iExtended, $vReturn)
EndFunc ;==>_CM_Assign_Var

Func _SetupDiOpenDeviceInterface($hDevs, $sDevicePath, ByRef $tSP_DEVIFINFO_DATA, $iFlags = 0)
    Local $iResult, $pSP_DEVIFINFO_DATA

    If Not IsDllStruct($tSP_DEVIFINFO_DATA) Then
        $tSP_DEVIFINFO_DATA = DllStructCreate($tagSP_DEV_INTERFACE_DATA)
        DllStructSetData($tSP_DEVIFINFO_DATA, "Size", 28)
    EndIf
    $pSP_DEVIFINFO_DATA = DllStructGetPtr($tSP_DEVIFINFO_DATA)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiOpenDeviceInterface", _
            "hWnd", $hDevs, "str", $sDevicePath, "dword", $iFlags, _
            "ptr", $pSP_DEVIFINFO_DATA)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiOpenDeviceInterface


; #### FUNCTION ####
; ===================================================================================
; Name  : _SetupDiGetDeviceInterfaceDevInst
; Description   : Specifies the device path, retrieves the device instance handle.
; Parameter(s)  : $sDevicePath  - Device path, in string format.
; Return values : A value of non-zero indicates the handle to the device instance if succeeds.
; Author    : Pusofalse
; ===================================================================================
Func _SetupDiGetDeviceInterfaceDevInst($sDevicePath)
    Local $iResult, $hDevs, $tDevIfInfo, $tDevInfo, $hDevInst

    $hDevs = _SetupDiGetClassDevs($DIGCF_ALLCLASSES)
    Select
    Case _SetupDiOpenDeviceInterface($hDevs, $sDevicePath, $tDevIfInfo) = 0
        Return SetError(@error, 0, _SetupDiDestroyDeviceInfoList($hDevs) * 0)
    Case _SetupDiGetDeviceInterfaceDetail($hDevs, $tDevIfInfo, $tDevInfo) <> $sDevicePath
        Return SetError(@error, 0, _SetupDiDestroyDeviceInfoList($hDevs) * 0)
    EndSelect
    $hDevInst = DllStructGetData($tDevInfo, "DevInst")
    _CM_Assign_Var($tDevInfo)
    _CM_Assign_Var($tDevIfInfo)
    _SetupDiDestroyDeviceInfoList($hDevs)
    Return $hDevInst
EndFunc ;==>_SetupDiGetDeviceInterfaceDevInst

; #### FUNCTION ####
; ===================================================================================
; Name  : _SetupDiRemoveDevice
; Description   : This function removes a device.
; Parameter(s)  : $hDevs    - Supplies a device information set handle.
;       : $pSP_DEVINFO_DATA - A pointer to a SP_DEVINFO_DATA structure contains the device information element to be removed.
;       : $fForce   - A BOOL value. If device information element specified in $pSP_DEVINFO_DATA is a non-removable device and this value is set  to FALSE, the function failed with ERROR_INVALID_PARAMETER. Otherwise, this parameter is ignored.
; Return values : True indicates success, False indicates failure.
; Author    : Pusofalse
; ===================================================================================
Func _SetupDiRemoveDevice($hDevs, $pSP_DEVINFO_DATA, $fForce = False)
    Local $iResult, $hDevInst, $iNodeStat, $tDevInfo

    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    If Not IsPtr($pSP_DEVINFO_DATA) Then Return SetError(87, 0, 0)

    $tDevInfo = DllStructCreate($tagSP_DEVICEINFO_DATA, $pSP_DEVINFO_DATA)
    $hDevInst = DllStructGetData($tDevInfo, "DevInst")
    If $hDevInst = 0 Then Return SetError(87, 0, 0)
    $iNodeStat = _SetupDiGetDevNodeStatus($hDevInst)
    If $fForce = False AND bitAND($iNodeStat, $DN_REMOVABLE) <> $DN_REMOVABLE Then
        Return SetError(87, 0, 0)
    EndIf

    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiRemoveDevice", _
            "ptr", $hDevs, "ptr", $pSP_DEVINFO_DATA)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiRemoveDevice

Func _SetupDiUnremoveDevice($hDevs, $pSP_DEVINFO_DATA)
    Local $iResult

    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiUnremoveDevice", _
            "ptr", $hDevs, "ptr", $pSP_DEVINFO_DATA)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiUnremoveDevice

; #### FUNCTION ####
; ===================================================================================
; Name  : _SetupDiCreateDeviceDevs
; Description   : Creates a device information set for a device instance.
; Parameter(s)  : $sDeviceID    - Device instance identifier, in string format.
;       : $hDevs    - A variable receives the handle the device information set.
;       : $tDevInfo - A variable receives an SP_DEVINFO_DATA structure that contains the device information element.
;       : $vGUID    - A device class GUID, can be NULL.
;       : $hWnd - A window handle owns the handle the device information set, can be NULL.
; Return values : True indicates success, False indicates failure, in which case, @error is set to a system error code.
; Author    : Pusofalse
; ===================================================================================
Func _SetupDiCreateDeviceDevs($sDeviceID, ByRef $hDevs, ByRef $tDevInfo, $vGuid = "", $hWnd = 0)
    $hDevs = _SetupDiCreateDeviceInfoList($vGuid, $hWnd)
    If Number($hDevs) < 1 Then Return SetError(@error, 0, 0)
    If _SetupDiOpenDeviceInfo($hDevs, $sDeviceID, $tDevInfo) = 0 Then
        Return SetError(@error, 0, _SetupDiDestroyDeviceInfoList($hDevs) * 0)
    ElseIf _SetupDiSetSelectedDevice($hDevs, $tDevInfo) = 0 Then
        Return SetError(@error, 0, _SetupDiDestroyDeviceInfoList($hDevs) * 0)
    EndIf
    Return 1
EndFunc ;==>_SetupDiCreateDeviceDevs

; #### FUNCTION ####
; ===================================================================================
; Name  : _SetupDiDisableDevice
; Description   : Disables or enables a device instance.
; Parameter(s)  : $hDevs    - Handle to the device information set.
;       : $pSP_DEVINFO_DATA - A pointer to a SP_DEVINFO_DATA structure contains the device information element to be disabled.
;       : $fDisable - True to disable, False to enable, default to True.
; Return values : If succeeds, returns true. Otherwise returns False and sets @error to a system error code.
; Author    : Pusofalse
; ===================================================================================
Func _SetupDiDisableDevice($hDevs, $pSP_DEVINFO_DATA, $fDisable = True)
    Local $hDevInst, $iDevNode, $tInstParam, $tDevInfo

    If $hDevs = 0 Then Return SetError(87, 0, 0)
    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf

    $tDevInfo = DllStructCreate($tagSP_DEVICEINFO_DATA, $pSP_DEVINFO_DATA)
    $hDevInst = DllStructGetData($tDevInfo, "DevInst")
    If $hDevInst = 0 Then Return SetError(87, 0, 0)

    $iDevNode = _CM_Get_DevNode_Status($hDevInst)
    If ($fDisable = (@extended = 22)) Then Return SetError(85, 0, 1)
    If bitAND($iDevNode, $DN_DISABLEABLE) <> $DN_DISABLEABLE Then
        Return SetError(50, 0, 0)
    EndIf

    $tInstParam = DllStructCreate($tagSP_PROPCHANGE_PARAMS)
    DllStructSetData($tInstParam, "Size", 8)
    DllStructSetData($tInstParam, "DIFCode", $DIF_PROPERTYCHANGE)
    DllStructSetData($tInstParam, "Scope", $DICS_FLAG_GLOBAL)
    DllStructSetData($tInstParam, "HWProfile", 0)
    If $fDisable = True Then
        DllStructSetData($tInstParam, "State", $DICS_DISABLE)
        _CM_Set_DevNode_CSConfigFlags($hDevInst, $CSCONFIGFLAG_DISABLED)
    Else
        DllStructSetData($tInstParam, "State", $DICS_ENABLE)
        _CM_Set_DevNode_CSConfigFlags($hDevInst, $CSCONFIGFLAG_NONE)
    EndIf

    Select
    Case _SetupDiSetClassInstallParams($hDevs, $pSP_DEVINFO_DATA, $tInstParam, 20) = 0
        Return SetError(@error, _CM_Free_Variable($tInstParam), 0)
    Case _SetupDiChangeState($hDevs, $pSP_DEVINFO_DATA) = 0
        Return SetError(@error, _CM_Free_Variable($tInstParam), 0)
    Case Else
        Return SetError(@error, _CM_Free_Variable($tInstParam), 1)
    EndSelect
EndFunc ;==>_SetupDiDisableDevice

; #### FUNCTION ####
; ===================================================================================
; Name  : _CM_Format_Problem_Message
; Description   : Retrieves the problem message text for a problem code.
; Parameter(s)  : $iProblemCode - A value of problem code.
; Return values : Error message, or NULL if failed.
; Author    : Pusofalse
; ===================================================================================
Func _CM_Format_Problem_Message($iProblemCode)
    Local $sErrMsgs, $aErrMsgs, $sMsg

    If $iProblemCode = 0 Then Return "This deivce is working properly."
    If $iProblemCode < 1 OR $iProblemCode > 50 Then Return ""
    $sErrMsgs = "This device is not configured correctly. (Code 1)" & @LF & _
"Windows could not load the driver for this device because the computer is reporting two <bustype> bus types. (Code 2)" & @LF & _
"The driver for this device might be corrupted, or your system may be running low on memory or other resources. (Code 3)" & @LF & _
"This device is not working properly because one of its drivers may be bad, or your registry may be bad. (Code 4)" & @LF & _
"The driver for this device requested a resource that Windows does not know how to handle. (Code 5)" & @LF & _
"Another device is using the resources this device needs. (Code 6)" & @LF & _
"The drivers for this device need to be reinstalled. (Code 7)" & @LF & _
"Device failure: Try changing the driver for this device. If that doesn't work, see your hardware documentation. (Code 8)" & @LF & _
"Windows cannot identify this hardware because it does not have a valid hardware identification number. (Code 9)" & @LF & _
"This device cannot start. (Code 10)" & @LF & _
"Windows stopped responding while attempting to start this device, and therefore will never attempt to start this device again. (Code 11)" & @LF & _
"This device cannot find enough free resources that it can use. (Code 12)" & @LF & _
"This device is either not present, not working properly, or does not have all the drivers installed. (Code 13)" & @LF & _
"This device cannot work properly until you restart your computer. (Code 14)" & @LF & _
"This device is causing a resource conflict. (Code 15)" & @LF & _
"Windows cannot identify all the resources this device uses. (Code 16)" & @LF & _
"The driver information file (INF-file-name) is telling this child device to use a resource that the parent device does not have or recognize. (Code 17)" & @LF & _
"Reinstall the drivers for this device. (Code 18)" & @LF & _
"Windows cannot start this hardware device because its configuration information (in the registry) is incomplete or damaged. (Code 19)" & @LF & _
"Windows could not load one of the drivers for this device. (Code 20)" & @LF & _
"Windows is removing this device. (Code 21)" & @LF & _
"This device is disabled. (Code 22)" & @LF & _
"This display adapter is functioning correctly. (Code 23)" & @LF & _
"This device is not present, is not working properly, or does not have all its drivers installed. (Code 24)" & @LF & _
"Windows is in the process of setting up this device. (Code 25)" & @LF & _
"Windows is in the process of setting up this device. (Code 26)" & @LF & _
"Windows can't specify the resources for this device. (Code 27)" & @LF & _
"The drivers for this device are not installed. (Code 28)" & @LF & _
"This device is disabled because the firmware of the device did not give it the required resources. (Code 29)" & @LF & _
"This device is using an Interrupt Request (IRQ) resource that is in use by another device and cannot be shared. You must change the conflicting setting or remove the real-mode driver causing the conflict. (Code 30)" & @LF & _
"This device is not working properly because Windows cannot load the drivers required for this device. (Code 31)" & @LF & _
"A driver (service) for this device has been disabled. An alternate driver may be providing this functionality. (Code 32)" & @LF & _
"Windows cannot determine which resources are required for this device. (Code 33)" & @LF & _
"Windows cannot determine the settings for this device. Consult the documentation that came with this device and use the Resource tab to set the configuration. (Code 34)" & @LF & _
"Your computer's system firmware does not include enough information to properly configure and use this device. To use this device, contact your computer manufacturer to obtain a firmware or BIOS update. (Code 35)" & @LF & _
"This device is requesting a PCI interrupt but is configured for an ISA interrupt (or vice versa). Please use the computer's system setup program to reconfigure the interrupt for this device. (Code 36)" & @LF & _
"Windows cannot initialize the device driver for this hardware. (Code 37)"

$sErrMsgs &= @LF &"Windows cannot load the device driver for this hardware because a previous instance of the device driver is still in memory. (Code 38)" & @LF & _
"Windows cannot load the device driver for this hardware. The driver may be corrupted or missing. (Code 39)" & @LF & _
"Windows cannot access this hardware because its service key information in the registry is missing or recorded incorrectly (Code 40)" & @LF & _
"Windows successfully loaded the device driver for this hardware but cannot find the hardware device. (Code 41)" & @LF & _
"Windows cannot load the device driver for this hardware becuse there is a duplicate device already running in the system. (Code 42)" & @LF & _
"Windows has stopped this device because it has reported problems. (Code 43)" & @LF & _
"An application or service has shut down this hardware device. (Code 44)" & @LF & _
"Currently, this hardware device is not connected to the computer. (Code 45)" & @LF & _
"Windows cannot gain access to this hardware device because the operating system is in the process of shutting down. (Code 46)" & @LF & _
"Windows cannot use this hardware device because it has been prepared for 'safe removal', but it has not been removed from the computer. (Code 47)" & @LF & _
"The software for this device has been blocked from starting because it is known to have problems with Windows. Contact the hardware vendor for a new driver. (Code 48)" & @LF & _
"Windows cannot start new hardware devices because the system hive is too large (exceeds the Registry Size Limit). (Code 49)" & @LF & _
"Windows cannot apply all of the properties for this device. Device properties may include information that describes the device's capabilities and settings (such as security settings for example). (Code 50)"
    $aErrMsgs = StringSplit($sErrMsgs, @LF)
    $sMsg = $aErrMsgs[$iProblemCode]
    _CM_Free_Variable($aErrMsgs)
    Return SetError(_CM_Assign_Var($sErrMsgs, ""), "", $sMsg)
EndFunc ;==>_CM_Format_Problem_Message

Func _CM_Get_Version()
    Local $iResult = DllCall($SETUPAPI_DllHandle, "ushort", "CM_Get_Version")
    Return $iResult[0]
EndFunc ;==>_CM_Get_Version

Func _CM_Is_Version_Available($wVersion)
    Local $iResult = DllCall($SETUPAPI_DllHandle, "int", "CM_Is_Version_Available", "short", $wVersion)
    Return $iResult[0] <> 0
EndFunc ;==>CM_Is_Version_Available

Func _CM_Locate_DevNode($sDeviceID, $iFlags = $CM_LOCATE_DEVNODE_NORMAL)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Locate_DevNode", "dword*", 0, _
            "str", $sDeviceID, "ulong", $iFlags)
    Return SetError($iResult[0], $iResult[0] = 0, $iResult[1])
EndFunc ;==>_CM_Locate_DevNode

Func _CM_Reenumerate_DevNode($hDevInst, $iFlags = $CM_REENUMERATE_NORMAL)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Reenumerate_DevNode", _
            "dword", $hDevInst, "ulong", $iFlags)
    Return SetError($iResult[0], $iResult[0] = 0, $iResult[0] = 0)
EndFunc ;==>_CM_Reenumerate_DevNode

Func _SetupDiSelectBestCompatDrv($hDevs, $pSP_DEVINFO_DATA)
    Local $iResult
    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiSelectBestCompatDrv", _
            "long", $hDevs, "ptr", $pSP_DEVINFO_DATA)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiSelectBestCompatDrv

Func _SetupDiSelectDevice($hDevs, $pSP_DEVINFO_DATA)
    Local $iResult
    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiSelectDevice", _
            "long", $hDevs, "ptr", $pSP_DEVINFO_DATA)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>SetupDiSelectDevice

Func _SetupDiInstallDevice($hDevs, $pSP_DEVINFO_DATA)
    Local $iResult
    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiInstallDevice", _
            "long", $hDevs, "ptr", $pSP_DEVINFO_DATA)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiInstallDevice

Func _SetupDiRegisterDeviceInfo($hDevs, $pSP_DEVINFO_DATA, $iFlags, ByRef $tSP_DEVINFO_DATA_DUP)
    Local $iResult, $pSP_DEVINFO_DATA_DUP

    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    If Not IsDllStruct($tSP_DEVINFO_DATA_DUP) Then
        $tSP_DEVINFO_DATA_DUP = DllStructCreate($tagSP_DEVICEINFO_DATA)
        DllStructSetData($tSP_DEVINFO_DATA_DUP, "Size", 28)
    EndIf
    $pSP_DEVINFO_DATA_DUP = DllStructGetPtr($tSP_DEVINFO_DATA_DUP)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiRegisterDeviceInfo", "long", $hDevs, _
            "ptr", $pSP_DEVINFO_DATA, "dword", $iFlags, "ptr", 0, "ptr", 0, _
            "ptr", $pSP_DEVINFO_DATA_DUP)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiRegisterDeviceInfo

Func _CM_Set_DevNode_Problem($hDevInst, $iProblemCode)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Set_DevNode_Problem", _
            "dword", $hDevInst, "ulong", $iProblemCode, "ulong", 0)
    Return SetError($iResult[0], $iResult[0] = 0, $iResult[0] = 0)
EndFunc ;==>_CM_Set_DevNode_Problem

Func _SetupDiCreateDeviceInterface($hDevs, $pSP_DEVINFO_DATA, $vGUID, ByRef $tSP_DEVIFINFO_DATA, $sReference = "")
    Local $iResult, $pSP_DEVIFINFO_DATA, $tGUID, $pGUID
    If IsString($vGUID) Then
        If StringLeft($vGUID, 1) & StringRight($vGUID, 1) = "{}" Then
            $tGUID = _CM_GUID_From_String($vGUID)
            $pGUID = DllStructGetPtr($tGUID)
        ElseIf $vGuid <> "" Then
            $tGUID = _SetupDiClassGuidsFromName($vGUID)
            $pGUID = DllStructGetPtr($tGUID)
        EndIf
    ElseIf IsDllStruct($vGUID) Then
        $pGUID = DllStructGetPtr($vGUID)
    ElseIf IsPtr($vGUID) Then
        $pGUID = $vGUID
    Else
        $pGUID = 0
    EndIf
    If $pGUID = 0 Then Return SetError(87, 0, 0)

    Select
    Case IsDllStruct($pSP_DEVINFO_DATA)
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
        ContinueCase
    Case IsDllStruct($tSP_DEVIFINFO_DATA) = 0
        $tSP_DEVIFINFO_DATA = DllStructCreate($tagSP_DEV_INTERFACE_DATA)
        DllStructSetData($tSP_DEVIFINFO_DATA, "Size", 28)
    EndSelect
    If Not IsPtr($pSP_DEVINFO_DATA) Then Return SetError(87, 0, 0)
    $pSP_DEVIFINFO_DATA = DllStructGetPtr($tSP_DEVIFINFO_DATA)

    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiCreateDeviceInterface", _
            "long", $hDevs, "ptr", $pSP_DEVINFO_DATA, _
            "ptr", $pGUID, "str", $sReference, "dword", 0, _
            "ptr", $pSP_DEVIFINFO_DATA)
    Return SetError(_CM_Get_Last_Error(), _CM_Free_Variable($tGUID), $iResult[0])
EndFunc ;==>_SetupDiCreateDeviceInterface

Func _SetupDiEnumDriverInfo($hDevs, $pSP_DEVINFO_DATA, $iIndex, ByRef $tSP_DRVINFO_DATA)
    Local $iResult, $pSP_DRVINFO_DATA, $iType = $SPDIT_CLASSDRIVER

    Select
    Case IsDllStruct($pSP_DEVINFO_DATA)
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
        ContinueCase
    Case IsDllStruct($tSP_DRVINFO_DATA) = 0
        $tSP_DRVINFO_DATA = DllStructCreate($tagSP_DRVINFO_DATA)
        DllStructSetData($tSP_DRVINFO_DATA, 1, DllStructGetSize($tSP_DRVINFO_DATA) - 12)
    EndSelect
    $pSP_DRVINFO_DATA = DllStructGetPtr($tSP_DRVINFO_DATA)
    If IsPtr($pSP_DEVINFO_DATA) Then $iType = $SPDIT_COMPATDRIVER

    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiEnumDriverInfo", "long", $hDevs, _
            "ptr", $pSP_DEVINFO_DATA, "dword", $iType, _
            "dword", $iIndex, "ptr", $pSP_DRVINFO_DATA)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiEnumDriverInfo

Func _SetupDiDestroyDriverInfoList($hDevs, $pSP_DEVINFO_DATA)
    Local $iResult, $iType = $SPDIT_CLASSDRIVER

    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    If IsPtr($pSP_DEVINFO_DATA) Then $iType = $SPDIT_COMPATDRIVER
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiDestroyDriverInfoList", _
            "long", $hDevs, "ptr", $pSP_DEVINFO_DATA, "dword", $iType)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiDestroyDriverInfoList


Func _SetupDiGetClassBitmapIndex($vGUID)
    Local $iResult, $pGUID

    If IsString($vGUID) Then
        If StringLeft($vGUID, 1) & StringRight($vGUID, 1) = "{}" Then
            $tGUID = _CM_GUID_From_String($vGUID)
            $pGUID = DllStructGetPtr($tGUID)
        ElseIf $vGuid <> "" Then
            $tGUID = _SetupDiClassGuidsFromName($vGUID)
            $pGUID = DllStructGetPtr($tGUID)
        EndIf
    ElseIf IsDllStruct($vGUID) Then
        $pGUID = DllStructGetPtr($vGUID)
    ElseIf IsPtr($vGUID) Then
        $pGUID = $vGUID
    Else
        $pGUID = 0
    EndIf

    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetClassBitmapIndex", _
            "ptr", $pGUID, "uint*", 0)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[2])
EndFunc ;==>_SetupDiGetClassBitmapIndex

Func _SetupDiGetClassImageList(ByRef $tSP_CLASSIMAGE_DATA)
    Local $iResult, $pSP_CLASSIMAGE_DATA

    If Not IsDllStruct($tSP_CLASSIMAGE_DATA) Then
        $tSP_CLASSIMAGE_DATA = DllStructCreate($tagSP_CLASSIMAGE_DATA)
        DllStructSetData($tSP_CLASSIMAGE_DATA, "Size", 12)
    EndIf
    $pSP_CLASSIMAGE_DATA = DllStructGetPtr($tSP_CLASSIMAGE_DATA)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetClassImageList", _
            "ptr", $pSP_CLASSIMAGE_DATA)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], DllStructGetData($tSP_CLASSIMAGE_DATA, 2))
EndFunc ;==>_SetupDiGetClassImageList

Func _SetupDiDestroyClassImageList($pSP_CLASSIMAGELIST_DATA)
    Local $iResult
    If IsDllStruct($pSP_CLASSIMAGELIST_DATA) Then
        $pSP_CLASSIMAGELIST_DATA = DllStructGetPtr($pSP_CLASSIMAGELIST_DATA)
    EndIf
    If Not IsPtr($pSP_CLASSIMAGELIST_DATA) Then Return SetError(87, 0, 0)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiDestroyClassImageList", _
            "ptr", $pSP_CLASSIMAGELIST_DATA)
    Return SetError(_CM_Get_Last_Error(), $iResult[0], $iResult[0])
EndFunc ;==>_SetupDiDestroyClassImageList

Func _SetupDiGetClassImageIndex($vGUID, $pSP_CLASSIMAGE_DATA = 0)
    Local $iResult, $tSP_CLASSIMAGE_DATA, $pGUID, $iError, $tGUID

    If $pSP_CLASSIMAGE_DATA = 0 Then
        _SetupDiGetClassImageList($tSP_CLASSIMAGE_DATA)
        $pSP_CLASSIMAGE_DATA = DllStructGetPtr($tSP_CLASSIMAGE_DATA)
    ElseIf IsDllStruct($pSP_CLASSIMAGE_DATA) Then
        $pSP_CLASSIMAGE_DATA = DllStructGetPtr($pSP_CLASSIMAGE_DATA)
    EndIf
    If Not IsPtr($pSP_CLASSIMAGE_DATA) Then Return SetError(87, 0, -1)

    If IsString($vGUID) Then
        If StringLeft($vGUID, 1) & StringRight($vGUID, 1) = "{}" Then
            $tGUID = _CM_GUID_From_String($vGUID)
            $pGUID = DllStructGetPtr($tGUID)
        ElseIf $vGuid <> "" Then
            $tGUID = _SetupDiClassGuidsFromName($vGUID)
            $pGUID = DllStructGetPtr($tGUID)
        EndIf
    ElseIf IsDllStruct($vGUID) Then
        $pGUID = DllStructGetPtr($vGUID)
    ElseIf IsPtr($vGUID) Then
        $pGUID = $vGUID
    Else
        $pGUID = 0
    EndIf
    If $pGUID = 0 Then Return SetError(87, 0, -1)
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetClassImageIndex", _
            "ptr", $pSP_CLASSIMAGE_DATA, "ptr", $pGUID, "int*", -1)
    $iError = _CM_Get_Last_Error()
    If IsDllStruct($tSP_CLASSIMAGE_DATA) Then
        _SetupDiDestroyClassImageList($pSP_CLASSIMAGE_DATA)
    EndIf
    $tGUID = 0
    Return SetError($iError, $iResult[0], $iResult[3])
EndFunc ;==>_SetupDiGetClassImageIndex

Func _CM_Get_Volume_Path($sVolumeGUID)
    Local $iResult
    $iResult = DllCall($Kernel32_DllHandleA, "int", "GetVolumePathNamesForVolumeName", _
            "str", $sVolumeGUID, "str", "", "dword", 32, "dword*", 0)
    If StringRight($iResult[2], 1) = "\" Then $iResult[2] = StringTrimRight($iResult[2], 1)
    Return $iResult[2]
EndFunc ;==>_CM_Get_Volume_Path

Func _CM_Get_Volume_Name($sVolume)
    Local $iResult
    If StringRight($sVolume, 1) <> "\" Then $sVolume &= "\"
    $iResult = DllCall($Kernel32_DllHandleA, "int", "GetVolumeNameForVolumeMountPoint", _
            "str", $sVolume, "str", "", "dword", 260)
    Return SetError(_CM_Get_Last_Error(), 0, $iResult[2])
EndFunc ;==>_CM_Get_Volume_Name

Func _CM_Scan_Device_Changes($sDevNode = "")
    Local $hDevInst, $fResult

    $hDevInst = _CM_Locate_DevNode($sDevNode)
    If $hDevInst < 1 Then Return SetError(@error, 0, 0)
    $fResult = _CM_Reenumerate_DevNode($hDevInst)
    Return SetError(@error, 0, $fResult)
EndFunc ;==>_CM_Scan_Device_Changes

Func _CM_Scan_Device_Changes_Ex($hMachine, $sDevNode = "")
    Local $hDevIntst, $iResult

    $hDevInst = _CM_Locate_DevNode_Ex($sDevNode, $hMachine)
    If $hDevInst < 1 Then Return SetError(@error, 0, 0)
    $iResult = _CM_Reenumerate_DevNode_Ex($hDevInst, $hMachine)
    Return SetError(@error, 0, $iResult)
EndFunc ;==>_CM_Scan_Device_Changes_Ex


Func _CM_Query_Device_Problem($hDevInst)
    Return _CM_Query_Device_Problem_Ex($hDevInst, 0)
EndFunc ;==>_CM_Query_Device_Problem

Func _CM_Query_Device_Problem_Ex($hDevInst, $hMachine)
    Local $iDevNodeStat, $iProblemCode

    $iDevNodeStat = _CM_Get_DevNode_Status_Ex($hDevInst, $hMachine)
    $iProblemCode = @extended
    If bitAND($iDevNodeStat, $DN_HAS_PROBLEM) = $DN_HAS_PROBLEM Then
        Return _CM_Format_Problem_Message($iProblemCode)
    ElseIf bitAND($iDevNodeStat, $DN_NEED_RESTART) = $DN_NEED_RESTART Then
        Return "A system reboot is requested to finish with the device installation."
    EndIf
    Return "This device is working properly."
EndFunc ;==>_CM_Query_Device_Problem_Ex

Func _SetupDiGetINFClass($sInfFileName, ByRef $sGUID)
    Local $iResult, $pGUID = _CM_Heap_Alloc(16)

    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetINFClass", "str", $sInfFileName, _
            "ptr", $pGUID, "str", "", "dword", 0, "dword*", 0)
    If $iResult[5] = 0 Then Return SetError(_CM_Get_Last_Error(), 0, "")
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiGetINFClass", "str", $sInfFileName, _
            "ptr", $pGUID, "str", "", "dword", $iResult[5], "dword*", 0)
    $sGUID = _CM_String_From_GUID($pGUID)
    Return SetExtended(_CM_Heap_Free($pGuid), $iResult[3])
EndFunc ;==>_SetupDiGetINFClass

Func _SetupDiLoadDeviceIcon($hDevs, $pSP_DEVINFO_DATA, $iWidth = 32, $iHeight = 32)
    Local $iResult
    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiLoadDeviceIcon", "ptr", $hDevs, _
            "ptr", $pSP_DEVINFO_DATA, "uint", $iWidth, "uint", $iHeight, _
            "dword", 0, "hWnd*", 0)
    If @error Then Return SetError(1, 0, -1)
    Return SetError(_CM_Get_Last_Error(), 0, $iResult[6])
EndFunc ;==>_SetupDiLoadDeviceIcon

Func _SetupDiLoadClassIcon($vGUID)
    Local $iResult, $tGUID, $pGUID

    If IsString($vGUID) Then
        If StringLeft($vGUID, 1) & StringRight($vGUID, 1) = "{}" Then
            $tGUID = _CM_GUID_From_String($vGUID)
        Else
            $tGUID = _SetupDiClassGuidsFromName($vGUID)
        EndIf
        $pGUID = DllStructGetPtr($tGUID)
    ElseIf IsDllStruct($vGUID) Then
        $pGUID = DllStructGetPtr($vGUID)
    ElseIf IsPtr($vGUID) Then
        $pGUID = $vGUID
    Else
        Return SetError(87, 0, -1)
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "int", "SetupDiLoadClassIcon", "ptr", $pGUID, _
            "hWnd*", 0, "int*", 0)
    Return SetError(_CM_Get_Last_Error(), $iResult[3], $iResult[2])
EndFunc ;==>_SetupDiLoadClassIcon


Func _SetupDiOpenDevRegKey($hDevs, $pSP_DEVINFO_DATA, $iAccess, $iScope = 1, $iHwProfile = 0, $iKeyType = 1)
    Local $iResult
    If IsDllStruct($pSP_DEVINFO_DATA) Then
        $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
    EndIf
    $iResult = DllCall($SETUPAPI_DllHandle, "hWnd", "SetupDiOpenDevRegKey", "ptr", $hDevs, _
            "ptr", $pSP_DEVINFO_DATA, "dword", $iScope, "dword", $iHwProfile, _
            "dword", $iKeyType, "dword", $iAccess)
    If $iResult[0] = 0 Then Return SetError(_CM_Get_Last_Error(), 0, 0)
    Return $iResult[0]
EndFunc ;==>_SetupDiOpenDevRegKey

Func _CM_Create_Device_Devs($hDevInst, ByRef $hDevs, ByRef $tSP_DEVINFO_DATA)
    Local $sDevInstID = _CM_Get_Device_ID($hDevInst)
    If _SetupDiCreateDeviceDevs($sDevInstID, $hDevs, $tSP_DEVINFO_DATA) = 0 Then
        Return SetError(@error, 0, 0)
    EndIf
    Return 1
EndFunc ;==>_CM_Create_Device_Devs

Func _CM_Create_Device_Devs_Ex($hDevInst, ByRef $hDevs, ByRef $tSP_DEVINFO_DATA, $sMachine)
    Local $hMachine, $sDeviceID, $fResult

    $hMachine = _CM_Connect_Machine($sMachine)
    If @error Then Return SetError(@error, 0, 0)
    $sDeviceID = _CM_Get_Device_ID_Ex($hDevInst, $hMachine)
    If @error Then Return SetError(@error, _CM_Disconnect_Machine($hMachine), 0)
    _CM_Disconnect_Machine($hMachine)

    If _SetupDiCreateDeviceDevsEx($sDeviceID, $hDevs, $tSP_DEVINFO_DATA, $sMachine) Then
        Return 1
    Else
        Return SetError(@error, 0, _SetupDiApiBufferFree($tSP_DEVINFO_DATA) * 0)
    EndIf
EndFunc ;==>_CM_Create_Device_Devs_Ex

; #### FUNCTION ####
; ====================================================================================
; Name  : _SetupDiGetClassDevsEx
; Description   : This function obtains a device information set on a local or a remote system.
; Parameter(s)  : $iFlags   - One or more of the following values:
;       : - DIGCF_ALLCLASSES: Return a list of installed devices for the specified device setup classes or device interface classes.
;       : - DIGCF_DEVICEINTERFACE: Return devices that support device interfaces for the specified device interface classes. This flag must be set in the $iFlags parameter if the $sEnumerator parameter specifies a device instance ID.
;       : - DIGCF_DEFAULT: Return only the device that is associated with the system default device interface, if one is set, for the specified device interface classes.
;       : - DIGCF_PRESENT: Return only devices that are currently present.
;       : - DIGCF_PROFILE: Return only devices that are a part of the current hardware profile.
;       : $vGUID    - Device class GUID, for examples, specifiy 'NET' for this parameter to retrieve the net adapters device information set.
;       : $sEnumerator -  A pointer to a NULL-terminated string that specifies: An identifier (ID) of a Plug and Play (PnP) enumerator. This ID can either be the enumerator¡¯s globally unique identifier (GUID) or symbolic name. For example, ¡°PCI¡± can be used to specify the PCI PnP enumerator. Other examples of symbolic names for PnP enumerators include ¡°USB¡±, ¡°PCMCIA¡±, and ¡°SCSI¡±. A PnP device instance IDs. When specifying a PnP device instance ID, DIGCF_DEVICEINTERFACE must be set in the $Flags parameter. This parameter is optional and can be set to NULL.
;       : $sMachine - Specifies the system on which the function executes, default to local.
;       : $hDevs    - The handle to an existing device information set to which SetupDiGetClassDevsEx adds the requested device information elements. This parameter is optional and can be set to NULL.
; Return values : Returns a handle to the device information set contains the device information elements, if succeeds; otherwise returns INVALID_HANDLE_VALUE (-1), in which case, @error is set to a system error code.
; Author    : Pusofalse
; ====================================================================================
Func _SetupDiGetClassDevsEx($iFlags, $vGUID = "", $sEnumerator = "", Const $sMachine = "", $hDevs = 0)
    Local $iResult, $tGUID, $pGUID, $sType = "ptr"

    If $sEnumerator <> "" Then $sType = "str"
    If IsString($vGUID) Then
        If StringLeft($vGUID, 1) & StringRight($vGUID, 1) = "{}" Then
            $tGUID = _CM_GUID_From_String($vGUID)
            $pGUID = DllStructGetPtr($tGUID)
        ElseIf $vGUID <> "" Then
            $tGUID = _SetupDiClassGUIDsFromName($vGUID)
            $pGUID = DllStructGetPtr($tGUID)
        EndIf
    ElseIf IsDllStruct($vGUID) Then
        $pGUID = DllStructGetPtr($vGUID)
    ElseIf IsPtr($vGUID) Then
        $pGUID = $vGUID
    Else
        $pGUID = 0
    EndIf

    $iResult = DllCall($SETUPAPI_DllHandle, "ptr", "SetupDiGetClassDevsEx", "ptr", $pGUID, _
            $sType, $sEnumerator, "hWnd", 0, "dword", $iFlags, _
            "ptr", $hDevs, "str", $sMachine, "ptr", 0)
    If $iResult[0] = 0xFFFFFFFF Then Return SetError(_CM_Get_Last_Error(), 0, -1)
    Return $iResult[0]
EndFunc ;==>_SetupDiGetClassDevsEx

; #### FUNCTION ####
; ====================================================================================
; Name  : _CM_Connect_Machine
; Description   : The _CM_Connect_Machine function creates a connection to a remote machine.
; Parameter(s)  : $sUncSystem   - System name, in UNC format.
; Return values : Returns a machine handle if success, else returns INVALID_HANDLE_VALUE (0xFFFFFFFF).
; Author    : Pusofalse
; ====================================================================================
Func _CM_Connect_Machine($sUncSystem)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Connect_Machine", "str", $sUncSystem, "ptr*", 0)
    Return SetError($iResult[0], 0, $iResult[2])
EndFunc ;==>_CM_Connect_Machine

; #### FUNCTION ####
; ====================================================================================
; Name  : _CM_Disconnect_Machine
; Description   : The _CM_Disconnect_Machine function removes a connection to a remote machine.
; Parameter(s)  : $hMachine - A machine handle, returned by _CM_Connect_Machine.
; Return values : True indicates success, False otherwise.
; Author    : Pusofalse
; ====================================================================================
Func _CM_Disconnect_Machine($hMachine)
    Local $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Disconnect_Machine", "ptr", $hMachine)
    Return SetError($iResult[0], 0, $iResult[0] = $CR_SUCCESS)
EndFunc ;==>_CM_Disconnect_Machine

; #### FUNCTION ####
; ====================================================================================
; Name  : _CM_Get_Child_Ex
; Description   : The _CM_Get_Child_Ex function is used to retrieve a device instance handle to the first child node of a specified device node (devnode) in a local or a remote machine's device tree.
; Parameter(s)  : $hDevInst - A device instance handle under which the child node is retrieved.
;       : $hMachine - A machine handle.
; Return values : Returns the device node handle if succeeds, else returns zero and sets @error to a configuration manager error code.
; Author    : Pusofalse
; ====================================================================================
Func _CM_Get_Child_Ex($hDevInst, $hMachine)
    Local $iResult
    $iResult  = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Child_Ex", "dword*", 0, _
            "dword", $hDevInst, "ulong", 0, "ptr", $hMachine)
    Return SetError($iResult[0], 0, $iResult[1])
EndFunc ;==>_CM_Get_Child_Ex

; #### FUNCTION ####
; ====================================================================================
; Name  : _CM_Get_Depth_Ex
; Description   : The function is used to obtain the depth of a specified device node (devnode) within a local or a remote machine's device tree.
; Parameter(s)  : $hDevInst - A handle to a device instance.
;       : $hMachine - A handle to a machine.
; Return values : If success, returns the depth value, else @error is set to non-zero.
; Author    : Pusofalse
; ====================================================================================
Func _CM_Get_Depth_Ex($hDevInst, $hMachine)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Depth_Ex", "ulong*", 0, _
            "dword", $hDevInst, "ulong", 0, "ptr", $hMachine)
    Return SetError($iResult[0], 0, $iResult[1])
EndFunc ;==>_CM_Get_Depth_Ex

; #### FUNCTION ####
; ====================================================================================
; Name  : _CM_Get_Parent_Ex
; Description   : This function obtains a device instance handle to the parent node of a specified device node (devnode) in a local or a remote machine's device tree.
; Parameter(s)  : $hDevInst - A device instance handle.
;       : $hMachine - A machine handle.
; Return values : Retrieves the parent device node handle if success, otherwise returns zero and sets @error to a configuration manager error code.
; Author    : Pusofalse
; ====================================================================================
Func _CM_Get_Parent_Ex($hDevInst, $hMachine)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Parent_Ex", "dword*", 0, _
            "dword", $hDevInst, "ulong", 0, "ptr", $hMachine)
    Return SetError($iResult[0], 0, $iResult[1])
EndFunc ;==>_CM_Get_Parent_Ex

; #### FUNCTION ####
; ====================================================================================
; Name  : _CM_Get_Sibling_Ex
; Description   : This function obtains a device instance handle to the sibling node of a specified device node (devnode) in a local or a remote machine's device tree.
; Parameter(s)  : $hDevInst - A handle to a device instance.
;       : $hMachine - A handle to a machine.
; Return values : A device instance handle indicates success, else returns zero and sets @error to a CR_* value.
; Author    : Pusofalse
; ====================================================================================
Func _CM_Get_Sibling_Ex($hDevInst, $hMachine)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Sibling_Ex", "dword*", 0, _
            "dword", $hDevInst, "ulong", 0, "ptr", $hMachine)
    Return SetError($iResult[0], 0, $iResult[1])
EndFunc ;==>_CM_Get_Sibling_Ex

; #### FUNCTION ####
; ====================================================================================
; Name  : _CM_Get_Version_Ex
; Description   : The _CM_Get_Version_Ex function returns version 4.0 of the Plug and Play (PNP) Configuration Manager DLL (Cfgmgr32.dll) for a local or a remote machine.
; Parameter(s)  : $hMachine - Supplies a machine handle, returned by _CM_Connect_Machine.
; Return values : If the function succeeds, it returns the major revision number in the high-order byte and the minor revision number in the low-order byte. Version 4.0 is returned as 0x0400. Version 4.0 is supported by default by Microsoft Windows NT 4.0 and later versions of Windows. If an internal error occurs, the function returns 0x0000. Call GetLastError to obtain the error code for the failure.
; Author    : Pusofalse
; ====================================================================================
Func _CM_Get_Version_Ex($hMachine)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "short", "CM_Get_Version_Ex", "ptr", $hMachine)
    Return $iResult[0]
EndFunc ;==>_CM_Get_Version_Ex

; #### FUNCTION ####
; ====================================================================================
; Name  : _CM_Locate_DevNode_Ex
; Description   : Obtains a device instance handle to the device node that is associated with a specified device instance identifier, on a local machine or a remote machine.
; Parameter(s)  : $sDevInstID - A device instance ID string on which the device instance handle is returned, a value of NULL indicates the root of the device tree.
;       : $hMachine - A machine handle.
;       : $iFlags   - One of the following values:
;       :   - CM_LOCATE_DEVNODE_NORMAL: The function retrieves the device instance handle for the specified device only if the device is currently configured in the device tree.
;       :   - CM_LOCATE_DEVNODE_PHANTOM: The function retrieves a device instance handle for the specified device if the device is currently configured in the device tree or the device is a nonpresent device that is not currently configured in the device tree.
;       :   - CM_LOCATE_DEVNODE_CANCELREMOVE: The function retrieves a device instance handle for the specified device if the device is currently configured in the device tree or in the process of being removed for the device tree. If the device is in the process of being removed, the function cancels the removal of the device.
; Return values : If succeeds, returns the specified device instance handle, else returns zero.
; Author    : Pusofalse
; ====================================================================================
Func _CM_Locate_DevNode_Ex($sDevInstID, $hMachine, $iFlags = $CM_LOCATE_DEVNODE_NORMAL)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Locate_DevNode_Ex", "dword*", 0, _
            "str", $sDevInstID, "ulong", $iFlags, "ptr", $hMachine)
    Return SetError($iResult[0], 0, $iResult[1])
EndFunc ;==>_CM_Locate_DevNode_Ex

; #### FUNCTION ####
; ====================================================================================
; Name  : _CM_Reenumerate_DevNode_Ex
; Description   :  The _CM_Reenumerate_DevNode_Ex function enumerates the devices identified by a specified device node and all of its children.
; Parameter(s)  : $hDevInst - A device instance handle.
;       : $hMachine - A machine handle.
;       : $iFlags - Can be a combination of the following values:
;       :   - CM_REENUMERATE_ASYNCHRONOUS: Reenumeration should occur asynchronously. The call to this function returns immediately after the PnP manager receives the reenumeration request. If this flag is set, the CM_REENUMERATE_SYNCHRONOUS flag should not also be set.
;       :   - CM_REENUMERATE_NORMAL: Specifies default reenumeration behavior, in which reenumeration occurs synchronously. This flag is currently equivalent to CM_REENUMERATE_SYNCHRONOUS.
;       :   - CM_REENUMERATE_RETRY_INSTALLATION: Specifies that Plug and Play should make another attempt to install any devices in the specified subtree that have been detected but are not yet configured, or are marked as needing reinstallation, or for which installation must be completed. This flag can be set along with either the CM_REENUMERATE_SYNCHRONOUS flag or the CM_REENUMERATE_ASYNCHRONOUS flag. This flag must be used with extreme caution, because it can cause the PnP manager to prompt the user to perform installation of any such devices. Currently, only components such as Device Manager and Hardware Wizard use this flag, to allow the user to retry installation of devices that might already have been detected but are not currently installed.
; Return values : Returns True if success, else returns false, @error is set to the reason of the failure.
; Author    : Pusofalse
; ====================================================================================
Func _CM_Reenumerate_DevNode_Ex($hDevInst, $hMachine, $iFlags = $CM_REENUMERATE_NORMAL)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Reenumerate_DevNode_Ex", _
            "dword", $hDevInst, "ulong", $iFlags, "ptr", $hMachine)
    Return SetError($iResult[0], 0, $iResult[0] = 0)
EndFunc ;==>_CM_Reenumerate_DevNode_Ex

; #### FUNCTION ####
; ====================================================================================
; Name  : _CM_Is_Version_Available_Ex
; Description   : The function indicates whether a specified version of the Plug and Play (PNP) Configuration Manager DLL (Cfgmgr32.dll) is supported by a local or a remote machine.
; Parameter(s)  : $wVersion - Identifies a version of the configuration manager. The supported version of the configuration manager corresponds directly to the operating system version. The major version is specified by the high-order byte and the minor version is specified by the low-order byte. For example, 0x0400 specifies version 4.0, which is supported by default by Microsoft Windows NT 4.0 and later versions of Windows. Version 0x0501 specifies version 5.1, which is supported by Windows XP and later versions of Windows.
;       : $hMachine - A machine handle.
; Return values : The function returns TRUE if the function can connect to the specified machine and if the machine supports the specified version. Otherwise, the function returns FALSE.
; Author    : Pusofalse
; ====================================================================================
Func _CM_Is_Version_Available_Ex($wVersion, $hMachine)
    Local $iResult
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Is_Version_Available_Ex", _
            "short", $wVersion, "ptr", $hMachine)
    Return $iResult[0] <> 0
EndFunc ;==>_CM_Is_Version_Available_Ex

; #### FUNCTION ####
; ====================================================================================
; Name  : _CM_Get_Device_ID_Ex
; Description   : The function retrieves the device instance ID for a specified device instance, on a local or a remote machine.
; Parameter(s)  : $hDevInst - A handle to a device instance.
;       : $hMachine - A handle to a machine.
; Return values : A device instance ID string is returned if success, else returns NULL and sets @error to a CR_* error code.
; Author    : Pusofalse
; ====================================================================================
Func _CM_Get_Device_ID_Ex($hDevInst, $hMachine)
    Local $iResult, $tBuffer, $pBuffer, $iLength

    $iLength = _CM_Get_Device_ID_Size_Ex($hDevInst, $hMachine) + 1
    $iResult = DllCall($SETUPAPI_DllHandle, "long", "CM_Get_Device_ID_Ex", "dword", $hDevInst, _
            "str", "", "ulong", $iLength, "ulong", 0, "ptr", $hMachine)
    Return SetError($iResult[0], 0, $iResult[2])
EndFunc ;==>_CM_Get_Device_ID_Ex

; #### FUNCTION ####
; ================================================================================
; Name  : _CM_Get_Device_ID_By_Name_Ex
; Description   : Specifies a device friendly name (or device description), retrieves the device instance ID binds to this name.
; Parameter(s)  : $sFriendlyName    - Specifies a device friendly name, or description.
;       : $fMatchAll    - A value of TRUE indicates the full words is matched, default to TRUE.
;       : $sDeviceID    - Device identifier string of the device from which the match is started, can be NULL.
;       : $hMachine - Supplies a machine handle, on which the function to execute, default to local.
; Return values : If a device instance is matched, the return value is set to the device instance identifier, otherwise returns NULL.
; Author    : Pusofalse
; ================================================================================
Func _CM_Get_Device_ID_By_Name_Ex($sFriendlyName, $fMatchAll = True, $sDeviceID = "", $hMachine = 0)
    Local $aChild, $sDescr, $sName, $hDevInst, $sVal

    If IsString($sDeviceID) = 0 Then
        $hDevInst = $sDeviceID
    Else