Sign in to follow this  
Followers 0
DXRW4E

Save\Restore Registry Key\SubKey

5 posts in this topic

#1 ·  Posted (edited)

These registry function I made them years ago, but being very busy i left all in the middle, however not need to use the RegCreateKey but just the RegOpenKey ;), http://support.microsoft.com/kb/128731 that should be in autoit

 

#RequireAdmin

#Region ;**** Global vars for Registry Function ****

If Not IsDeclared("arDllCall") Then Global Static $arDllCall
Global Const $hKernel32DLL = DllOpen("Kernel32.dll")
Global Const $hAdvapi32Dll = DllOpen("AdvApi32.dll")
;;Global Static $iTokenPrivilegesState

;;
;; Reserved Key Handles.
;;
Global Const $HKEY_CLASSES_ROOT                = 0x80000000
Global Const $HKEY_CURRENT_USER                = 0x80000001
Global Const $HKEY_LOCAL_MACHINE               = 0x80000002
Global Const $HKEY_USERS                       = 0x80000003
Global Const $HKEY_PERFORMANCE_DATA            = 0x80000004
Global Const $HKEY_CURRENT_CONFIG              = 0x80000005
Global Const $HKEY_DYN_DATA                    = 0x80000006
Global Const $HKEY_CURRENT_USER_LOCAL_SETTINGS = 0x80000007
Global Const $HKEY_PERFORMANCE_TEXT            = 0x80000050
Global Const $HKEY_PERFORMANCE_NLSTEXT         = 0x80000060

Global Const $SE_REGISTRY_KEY                  = 4  ;; Indicates a registry key. A registry key object can be in the local registry, such as CLASSES_ROOT\SomePath or in a remote registry, such as \\ComputerName\CLASSES_ROOT\SomePath. The names of registry keys must use the following literal strings to identify the predefined registry keys: "CLASSES_ROOT", "CURRENT_USER", "MACHINE", and "USERS".
Global Const $SE_REGISTRY_WOW64_32KEY          = 12 ;; Indicates an object for a registry entry under WOW64.
Global Const $KEY_WOW64_64KEY                  = 0x0100 ;; Indicates that an application on 64-bit Windows should operate on the 64-bit registry view. This flag is ignored by 32-bit Windows. For more information, see Accessing an Alternate Registry View. This flag must be combined using the OR operator with the other flags in this table that either query or access registry values.
Global Const $KEY_WOW64_32KEY                  = 0x0200 ;; Indicates that an application on 64-bit Windows should operate on the 32-bit registry view. This flag is ignored by 32-bit Windows. For more information, see Accessing an Alternate Registry View. This flag must be combined using the OR operator with the other flags in this table that either query or access registry values.
Global Const $KEY_WOW64_RES                    = 0x0300
Global Const $HKEY_PREDEFINED[11][6]           = [[0x80000000,"HKCR","CLASSES_ROOT","\Registry\Machine\SOFTWARE\Classes","HKEY_CLASSES_ROOT","HKCR"],[0x80000001,"HKCU","CURRENT_USER","\Registry\User\CurrentUser","HKEY_CURRENT_USER","HKCU"],[0x80000002,"HKLM","MACHINE","\Registry\Machine","HKEY_LOCAL_MACHINE","HKLM"],[0x80000003,"HKU","USERS","\Registry\User","HKEY_USERS","HKU"],[0x80000005,"HKLM","MACHINE\SYSTEM\CurrentControlSet\Hardware Profiles\Current","\Registry\Machine\SYSTEM\CurrentControlSet\Hardware Profiles\Current","HKEY_CURRENT_CONFIG","HKCC"],[0x80000007,"HKCU","CURRENT_USER\Software\Classes\Local Settings","\Registry\User\CurrentUser\Software\Classes\Local Settings","HKEY_CURRENT_USER_LOCAL_SETTINGS","HKLS"],[0x80000004,"HKPD","PERFORMANCE_DATA\","","HKEY_PERFORMANCE_DATA","HKPD"],[0x80000006,"HKDD","DYN_DATA\","","HKEY_DYN_DATA","HKDD"],[0x80000050,"HKPT","PERFORMANCE_TEXT\","","HKEY_PERFORMANCE_TEXT","HKPT"],[0x80000060,"HKPN","PERFORMANCE_NLSTEXT\","","HKEY_PERFORMANCE_NLSTEXT","HKPN"],[0,";",0,""]]

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                                                    ;;
;;               NT Defined Privileges                                ;;
;;                                                                    ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Global Const $SE_DEBUG_NAME                  = "SeDebugPrivilege"
Global Const $SE_TAKE_OWNERSHIP_NAME         = "SeTakeOwnershipPrivilege"
Global Const $SE_SECURITY_NAME               = "SeSecurityPrivilege"
Global Const $SE_BACKUP_NAME                 = "SeBackupPrivilege"
Global Const $SE_RESTORE_NAME                = "SeRestorePrivilege"
Global Const $SE_CREATE_SYMBOLIC_LINK_NAME   = "SeCreateSymbolicLinkPrivilege"
Global Static $aTokenPrivilegesNewState[6][2] = [[$SE_RESTORE_NAME,2],[$SE_BACKUP_NAME,2],[$SE_SECURITY_NAME,2],[$SE_TAKE_OWNERSHIP_NAME,2],[$SE_DEBUG_NAME,2],[$SE_CREATE_SYMBOLIC_LINK_NAME,2]]
Global Static $aTokenPrivilegesPreviousState = _WinAPI_SetPrivilegeEx($aTokenPrivilegesNewState)

Global Const $REG_SPECIAL_ACCESS = (IsDeclared("iTokenPrivilegesState") ? 4 : 0)  ;; $REG_OPTION_BACKUP_RESTORE = 4 - open for backup or restore special access rules privilege required
Global Const $KEY_ALL_ACCESS                   = 0x000F003F ;; BitOr($STANDARD_RIGHTS_REQUIRED, $KEY_QUERY_VALUE, $KEY_SET_VALUE, $KEY_CREATE_SUB_KEY, $KEY_ENUMERATE_SUB_KEYS, $KEY_NOTIFY, $KEY_CREATE_LINK)

#EndRegion ;**** Global vars for Registry Function ****


; #FUNCTION# ====================================================================================================================================
; Name...........: _WinAPI_SetPrivilegeEx
; Description ...: Enables or disables special privileges as required by some DllCalls
; Syntax.........: _WinAPI_SetPrivilegeEx($avPrivilege)
; Parameters ....: $avPrivilege - An array of privileges and respective attributes
;                                 $SE_PRIVILEGE_ENABLED - The function enables the privilege
;                                 $SE_PRIVILEGE_REMOVED - The privilege is removed from the list of privileges in the token
;                                 0 - The function disables the privilege
; Requirement(s).: None
; Return values .: Success - An array of modified privileges and their respective previous attribute state
;                  Failure - An empty array
;                            Sets @Error
; Author ........: engine
; Modified.......: FredAI, DXRW4E
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......;
; ===============================================================================================================================================
Func _WinAPI_SetPrivilegeEx($avPrivilege)
    ;;$iTokenPrivilegesState = $iTokenPrivilegesState ? 0 : 1
    If Not UBound($avPrivilege) Then Return SetError(1, 0, 0)
    Local $tagTP = "DWORD", $iTokens = UBound($avPrivilege), $iError = 0, $iCount
    For $i = 1 To $iTokens
        $tagTP &= ";DWORD;LONG;DWORD"
    Next
    Local $tCurrState = DLLStructCreate($tagTP), $tPrevState = DllStructCreate($tagTP), $tLUID = DllStructCreate("DWORD;LONG")
    DLLStructSetData($tCurrState, 1, $iTokens)
    For $i = 0 To $iTokens - 1
        DllCall($hAdvapi32Dll, "BOOL", "LookupPrivilegeValueW", "WSTR", Null, "WSTR", $avPrivilege[$i][0], "STRUCT*", $tLUID)
        DLLStructSetData($tCurrState, 3 * $i + 2, DllStructGetData($tLUID, 1))
        DLLStructSetData($tCurrState, 3 * $i + 3, DllStructGetData($tLUID, 2))
        DLLStructSetData($tCurrState, 3 * $i + 4, $avPrivilege[$i][1])
    Next
    Local $hToken = DllCall($hAdvapi32Dll, "BOOL", "OpenProcessToken", "HANDLE", DllCall($hKernel32DLL, "HANDLE", "GetCurrentProcess")[0], "DWORD", 40, "HANDLE*", 0)[3] ;; TOKEN_ADJUST_PRIVILEGES + TOKEN_QUERY = 40
    DllCall($hAdvapi32Dll, "BOOL", "AdjustTokenPrivileges", "HANDLE", $hToken, "BOOL", False, "STRUCT*", $tCurrState, "DWORD", DllStructGetSize($tCurrState), "STRUCT*", $tPrevState, "DWORD*", 0)
    $iError = DllCall($hKernel32DLL, "DWORD", "GetLastError")[0]
    DllCall($hKernel32DLL, "BOOL", "CloseHandle", "HANDLE", $hToken)
    $iCount = DllStructGetData($tPrevState, 1)
    If $iCount < 1 Then Return SetError($iError, 0, 0)
    Local $pLUID, $tName, $avPrevState[$iCount][2], $pPrevState = DllStructGetPtr($tPrevState)
    For $i = 0 To $iCount - 1
        $pLUID = $pPrevState + 12 * $i + 4
        $tName = DllStructCreate("WCHAR[" & DllCall($hAdvapi32Dll, "BOOL", "LookupPrivilegeNameW", "WSTR", Null, "PTR", $pLUID, "PTR", 0, "DWORD*", 0)[4] & "]")
        DllCall($hAdvapi32Dll, "BOOL", "LookupPrivilegeNameW", "WSTR", Null, "PTR", $pLUID, "STRUCT*", $tName, "DWORD*", DllStructGetSize($tName))
        $avPrevState[$i][0] = DllStructGetData($tName, 1)
        $avPrevState[$i][1] = DllStructGetData($tPrevState, 3 * $i + 4)
    Next
    Return SetError($iError, 1, $avPrevState)
EndFunc ;==> _WinAPI_SetPrivilegeEx


; #FUNCTION# ========================================================================================================================
; Name...........: _WinAPI_RegOpenKey
; Description ...: Opens the specified registry key.
;                    If the calling thread has not the $SE_BACKUP_NAME and $SE_RESTORE_NAME privilege enabled, the function fails
; Syntax.........: _WinAPI_RegOpenKey($hKey[, $sSubKey[, $samDesired[, $ulOptions]])
; Parameters ....: $hKey       - A handle to an open registry key. This handle is returned by the _WinAPI_RegCreateKeyEx or _WinAPI_RegOpenKeyEx
;                                  or _WinAPI_RegCreateKey or _WinAPI_RegOpenKey function, or it can be one of the following predefined keys:
;                                    $HKEY_CLASSES_ROOT
;                                    $HKEY_CURRENT_CONFIG
;                                    $HKEY_CURRENT_USER
;                                    $HKEY_LOCAL_MACHINE
;                                    $HKEY_USERS
;                                This parameter can be NULL, use the NULL or 0 to set NULL this parameter, If $hKey is NULL,
;                                  $sSubKey must be contain Full String KeyName, for more see $sSubKey
;                  $sSubKey    - Optional, The name of the registry key to be opened. Key names are not case sensitive.
;                                  This key must be a subkey of the key identified by the $hKey parameter.
;                                  if $hKey is Null this key must be a Full String KeyName, example
;                                    "HKLM\SOFTWARE\Example" or "HKEY_USERS" or "HKEY_CURRENT_USER\Software"
;                                    "\Registry\Machine\SOFTWARE\Example" or "\Registry\User" or "\Registry\User\CurrentUser"
;                                    "MACHINE\Software\Example" or "USERS" or "CURRENT_USER\Software"
;                                    "CLASSES_ROOT\Example" or in a remote registry such as \\ComputerName\CLASSES_ROOT\Example.
;                                  If this parameter is NULL or an empty string, the function returns the same handle that was passed in.
;                  $samDesired - Optional, An access mask the specifies the platform-specific view of the registry.
;                  |  This parameter can be one of the following values, These flags are ignored by 32-bit Windows
;                  |$KEY_WOW64_64KEY (256) - operate on the 64-bit registry view
;                  |$KEY_WOW64_32KEY (512) - operate on the 32-bit registry view
;                  $ulOptions  - Optional, This parameter is reserved and must be zero.
;                  | however will have to support flags such as
;                  |$REG_OPTION_OPEN_LINK (8) - Open symbolic link, query L"SymbolicLinkValue" or set L"SymbolicLinkValue"
; Return values .: If the function succeeds, the return value is a handle to the opened key and set ERROR_SUCCESS error code
;                  If the function fails, the return value is a 0, and set nonzero error code, and set Extended error code defined in WinError.h
;                    @Extended: -1 = unable to use the DLL file,
;                               -2 = unknown "return type",
;                               -3 = "function" not found in the DLL file,
;                               -4 = bad number of parameters,
;                               -5 = bad parameter.
;                               0+ = error code defined in WinError.h
; Author ........: DXRW4E
; Modified.......:
; Remarks .......: The _WinAPI_RegOpenKey function ignores the security access mask and attempts to open the key (Not Volatile) with the
;                    access required to backup or restore the key. If the calling thread has the $SE_BACKUP_NAME privilege enabled,
;                    the key is opened with the ACCESS_SYSTEM_SECURITY and KEY_READ access rights. If the calling thread has
;                    the $SE_RESTORE_NAME privilege enabled, beginning with Windows Vista, the key is opened with the
;                    $ACCESS_SYSTEM_SECURITY, $DELETE and $KEY_WRITE access rights. If both privileges are enabled, the key has
;                    the combined access rights for both privileges. For more information, see Running with Special Privileges msdn.microsoft.com/en-us/library/windows/desktop/ms717802(v=vs.85).aspx
;                  If opening the key requires adifferent access right, An application should use the _WinAPI_RegOpenKeyEx function to
;                    specify an access mask in this situation, or to specify other options.
;                  _WinAPI_RegOpenKey does not create the specified key if the key does not exist in the database.
;                  If your service or application impersonates different users, do not use this function with $HKEY_CURRENT_USER.
;                    Instead, call the _WinAPI_RegOpenCurrentUser function.
;                  Note that operations that access certain registry keys are redirected. For more information,
;                    see Registry Virtualization http://msdn.microsoft.com/en-us/library/windows/desktop/aa965884(v=vs.85).aspx
;                    and 32-bit and 64-bit Application Data in the Registry http://msdn.microsoft.com/en-us/library/windows/desktop/ms724072(v=vs.85).aspx
;                  If the key is not one of the predefined registry keys you must call the _WinAPI_RegCloseKey()
;                    function after finished using the handle.
; Related .......:
; Link ..........:
; Example .......:
; Example .......: _WinAPI_RegOpenKey(0, "HKLM\Software\KeyName")
;                  _WinAPI_RegOpenKey($HKEY_LOCAL_MACHINE, "Software\KeyName")
; Note ..........:
; ===================================================================================================================================
Func _WinAPI_RegOpenKey(Const ByRef $hKey, $sSubKey = "", $samDesired = 0, $ulOptions = 0)
    ;; Static $REG_OPTION_BACKUP_RESTORE = 4
    $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegOpenKeyExW", "ULONG_PTR", ($hKey ? $hKey : _RegGetPredefinedKeyEx($sSubKey, $samDesired)), "WSTR", $sSubKey, "DWORD", BitOR($ulOptions, 4), "DWORD", $samDesired, "ULONG_PTR*", 0)
    If @Error Then Return SetError(1, -@Error, 0)
    If $arDllCall[0] = 206 Then ;; ERROR_FILENAME_EXCED_RANGE - 206 (0xCE) - The filename or extension is too long.
        $sSubKey = StringRegExp($sSubKey, "(?>[^\\]+\\+){1,29}(?>[^\\]*)", 3)
        If @Error Or UBound($sSubKey) > 17 Then Return SetError(2, 206, 0)
        $arDllCall[5] = $arDllCall[1]
        For $i = 0 To UBound($sSubKey) - 1
            $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegOpenKeyExW", "ULONG_PTR", $arDllCall[5], "WSTR", $sSubKey[$i], "DWORD", $arDllCall[3], "DWORD", $samDesired, "ULONG_PTR*", 0)
            If $i Then DllCall($hAdvapi32Dll, "LONG", "RegCloseKey", "ULONG_PTR", $arDllCall[1])
            If $arDllCall[0] Then Return SetError(3, $arDllCall[0], 0)
        Next
    EndIf
    Return SetError($arDllCall[0], $arDllCall[0], $arDllCall[5])
EndFunc


; #FUNCTION# ========================================================================================================================
; Name...........: _WinAPI_RegCreateKey
; Description ...: Creates the specified registry key. If the key already exists in the registry, the function opens it.
;                    If the calling thread has not the $SE_BACKUP_NAME and $SE_RESTORE_NAME privilege enabled, the function fails
; Syntax.........: _WinAPI_RegCreateKey($hKey[, $sSubKey[, $samDesired[, $dwOptions]]])
; Parameters ....: $hKey       - A handle to an open registry key. This handle is returned by the _WinAPI_RegCreateKeyEx or _WinAPI_RegOpenKeyEx
;                                  or _WinAPI_RegCreateKey or _WinAPI_RegOpenKey function, or it can be one of the following predefined keys:
;                                    $HKEY_CLASSES_ROOT
;                                    $HKEY_CURRENT_CONFIG
;                                    $HKEY_CURRENT_USER
;                                    $HKEY_LOCAL_MACHINE
;                                    $HKEY_USERS
;                                This parameter can be NULL, use the NULL or 0 to set NULL this parameter, If $hKey is NULL,
;                                  $sSubKey must be contain Full String KeyName, for more see $sSubKey
;                  $sSubKey    - Optional, The name of a key that this function opens or creates. Key names are not case sensitive.
;                                  This key must be a subkey of the key identified by the $hKey parameter.
;                                  This parameter cannot be NULL.
;                                  if $hKey is Null this key must be a Full String KeyName, example
;                                    "HKLM\SOFTWARE\Example" or "HKEY_USERS" or "HKEY_CURRENT_USER\Software"
;                                    "\Registry\Machine\SOFTWARE\Example" or "\Registry\User" or "\Registry\User\CurrentUser"
;                                    "MACHINE\Software\Example" or "USERS" or "CURRENT_USER\Software"
;                                    "CLASSES_ROOT\Example" or in a remote registry such as \\ComputerName\CLASSES_ROOT\Example.
;                                  If $hKey is one of the predefined keys, $sSubKey may be NULL. In that case, return the same $hKey handle passed in to the function.
;                  $samDesired - Optional, An access mask the specifies the platform-specific view of the registry.
;                  |  This parameter can be one of the following values, These flags are ignored by 32-bit Windows
;                  |$KEY_WOW64_64KEY (256) - operate on the 64-bit registry view
;                  |$KEY_WOW64_32KEY (512) - operate on the 32-bit registry view
;                  $dwOptions  - Optional, This parameter can be one of the following values.
;                  |  (add the flags together for multiple operations):
;                  |$REG_OPTION_NON_VOLATILE (0) - (Default) This key is not volatile; this is the default. The information is stored in a file and is
;                  |                                 preserved when the system is restarted. The RegSaveKey function saves keys that are not volatile.
;                  |$REG_OPTION_VOLATILE (1)     - All keys created by the function are volatile. The information is stored in memory and is not preserved
;                  |                                when the corresponding registry hive is unloaded. For HKEY_LOCAL_MACHINE, this occurs only when the system
;                  |                                initiates a full shutdown. For registry keys loaded by the RegLoadKey function, this occurs when the
;                  |                                corresponding RegUnLoadKey is performed. The RegSaveKey function does not save volatile keys. This flag
;                  |                                is ignored for keys that already exist.
;                  |                               Note  On a user selected shutdown, a fast startup shutdown is the default behavior for the system.
;                  |$REG_OPTION_CREATE_LINK (2)  - Note Registry symbolic links should only be used for for application compatibility when absolutely necessary.
;                  |                                This key is a symbolic link. The target path is assigned to the L"SymbolicLinkValue" value of the key.
;                  |                                The target path must be an absolute registry path.
; Return values .: If the function succeeds, the return value is a handle to the opened or created key and set ERROR_SUCCESS error code, and set Extended
;                    @Extended: $REG_CREATED_NEW_KEY (1)     = The key did not exist and was created.
;                               $REG_OPENED_EXISTING_KEY (2) = The key existed and was simply opened without being changed.
;                  If the function fails, the return value is a 0, and set nonzero error code, and set Extended error code defined in WinError.h
;                    @Extended: -1 = unable to use the DLL file,
;                               -2 = unknown "return type",
;                               -3 = "function" not found in the DLL file,
;                               -4 = bad number of parameters,
;                               -5 = bad parameter.
;                               0+ = error code defined in WinError.h
; Author ........: DXRW4E
; Modified.......:
; Remarks .......: The _WinAPI_RegCreateKey function ignores the security access mask and attempts to open\create the key (Not Volatile) with the
;                    access required to backup or restore the key. If the calling thread has the $SE_BACKUP_NAME privilege enabled,
;                    the key is opened with the ACCESS_SYSTEM_SECURITY and KEY_READ access rights. If the calling thread has
;                    the $SE_RESTORE_NAME privilege enabled, beginning with Windows Vista, the key is opened with the
;                    ACCESS_SYSTEM_SECURITY, DELETE and KEY_WRITE access rights. If both privileges are enabled, the key has
;                    the combined access rights for both privileges. For more information, see Running with Special Privileges msdn.microsoft.com/en-us/library/windows/desktop/ms717802(v=vs.85).aspx
;                  If opening\creates the key requires adifferent access right, An application should use the _WinAPI_RegCreateKeyEx function to
;                    specify an access mask in this situation, or to specify other options.
;                  The key that the _WinAPI_RegCreateKey function creates has no values. An application can use the
;                    _WinAPI_RegSetValueEx function to set key values.
;                  The _WinAPI_RegCreateKey function creates all missing keys in the specified path. An application can take advantage
;                    of this behavior to create several keys at once. For example, an application can create a subkey four levels deep
;                    at the same time as the three preceding subkeys by specifying a string of the following form for the $sSubKey parameter:
;                      "subkey1\subkey2\subkey3\subkey4"
;                  Note that this behavior will result in creation of unwanted keys if an existing key in the path is spelled incorrectly.
;                  An application cannot create a key that is a direct child of $HKEY_USERS or $HKEY_LOCAL_MACHINE. An application can create
;                    subkeys in lower levels of the $HKEY_USERS or $HKEY_LOCAL_MACHINE trees.
;                  If your service or application impersonates different users, do not use this function with $HKEY_CURRENT_USER. Instead,
;                    call the _WinAPI_RegOpenCurrentUser function.
;                  Note that operations that access certain registry keys are redirected. For more information,
;                    see Registry Virtualization http://msdn.microsoft.com/en-us/library/windows/desktop/aa965884(v=vs.85).aspx
;                    and 32-bit and 64-bit Application Data in the Registry http://msdn.microsoft.com/en-us/library/windows/desktop/ms724072(v=vs.85).aspx
;                  If the key is not one of the predefined registry keys you must call the _WinAPI_RegCloseKey()
;                    function after finished using the handle.
; Related .......:
; Link ..........:
; Example .......:
; Example .......: _WinAPI_RegCreateKey(0, "HKLM\Software\KeyName")
;                  _WinAPI_RegCreateKey($HKEY_LOCAL_MACHINE, "Software\KeyName")
; Note ..........:
; ===================================================================================================================================
Func _WinAPI_RegCreateKey(Const ByRef $hKey, $sSubKey = "", $samDesired = 0, $dwOptions = 0)
    ;; Static $REG_OPTION_RESERVED = 0, $REG_OPTION_BACKUP_RESTORE = 4
    $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegCreateKeyExW", "ULONG_PTR", ($hKey ? $hKey : _RegGetPredefinedKeyEx($sSubKey, $samDesired)), "WSTR", ($sSubKey ? $sSubKey : ""), "DWORD", 0, "WSTR", Null, "DWORD", BitOR($dwOptions, 4), "DWORD", $samDesired, "PTR", Null, "ULONG_PTR*", 0, "DWORD*", 0)
    If @Error Then Return SetError(1, -@Error, 0)
    If $arDllCall[0] = 206 Then ;; ERROR_FILENAME_EXCED_RANGE - 206 (0xCE) - The filename or extension is too long.
        $sSubKey = StringRegExp($arDllCall[2], "(?>[^\\]+\\+){1,29}(?>[^\\]*)", 3)
        If @Error Or UBound($sSubKey) > 17 Then Return SetError(2, $arDllCall[0], 0)
        $arDllCall[8] = $arDllCall[1]
        For $i = 0 To UBound($sSubKey) - 1
            $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegCreateKeyExW", "ULONG_PTR", $arDllCall[8], "WSTR", $sSubKey[$i], "DWORD", 0, "WSTR", Null, "DWORD", $arDllCall[5], "DWORD", $samDesired, "PTR", Null, "ULONG_PTR*", 0, "DWORD*", 0)
            If $i Then DllCall($hAdvapi32Dll, "LONG", "RegCloseKey", "ULONG_PTR", $arDllCall[1])
            If $arDllCall[0] Then Return SetError(3, $arDllCall[0], 0)
        Next
    EndIf
    Return SetError($arDllCall[0], ($arDllCall[0] ? $arDllCall[0] : $arDllCall[9]), $arDllCall[8])
EndFunc


; #FUNCTION# ========================================================================================================================
; Name...........: _WinAPI_RegEnumKey
; Description ...: Enumerates the subkeys of the specified open registry key. The function retrieves information about one subkey each time it is called.
; Syntax.........: _WinAPI_RegEnumKey($hKey, $dwIndex)
; Parameters ....: $hKey    - A handle to an open registry key. The key must have been opened with the KEY_ENUMERATE_SUB_KEYS access right.
;                               For more information, see Registry Key Security and Access Rights.
;                               This handle is returned by the _WinAPI_RegCreateKeyEx or _WinAPI_RegOpenKeyEx or _WinAPI_RegCreateKey or _WinAPI_RegOpenKey
;                                 function, or it can be one of the following predefined keys:
;                                     $HKEY_CLASSES_ROOT
;                                     $HKEY_CURRENT_CONFIG
;                                     $HKEY_CURRENT_USER
;                                     $HKEY_LOCAL_MACHINE
;                                     $HKEY_PERFORMANCE_DATA
;                                     $HKEY_USERS
;                  $dwIndex -  The index of the subkey to retrieve. This parameter should be zero for the first call to the _WinAPI_RegEnumKey
;                                function and then incremented for subsequent calls.
;                              Because subkeys are not ordered, any new subkey will have an arbitrary index. This means that the function
;                                may return subkeys in any order.
; Return values .: If the function succeeds, the return value is name of the subkey and set ERROR_SUCCESS error code
;                  If the function fails, the return value is a None '', and set nonzero error code, and set Extended error code defined in WinError.h
;                    @Extended: -1 = unable to use the DLL file,
;                               -2 = unknown "return type",
;                               -3 = "function" not found in the DLL file,
;                               -4 = bad number of parameters,
;                               -5 = bad parameter.
;                               0+ = error code defined in WinError.h
; Author ........: DXRW4E
; Modified.......:
; Remarks .......: To enumerate subkeys, an application should initially call the _WinAPI_RegEnumKey function with the dwIndex
;                    parameter set to zero. The application should then increment the dwIndex parameter and call _WinAPI_RegEnumKey
;                    until there are no more subkeys (meaning the function returns ERROR_NO_MORE_ITEMS).
;                  The application can also set dwIndex to the index of the last subkey on the first call to the function and decrement the index
;                    until the subkey with the index 0 is enumerated. To retrieve the index of the last subkey, use the RegQueryInfoKey function.
;                  While an application is using the _WinAPI_RegEnumKey function, it should not make calls to any registration
;                    functions that might change the key being enumerated.
; Related .......:
; Link ..........:
; Example .......:
; Example .......:  _WinAPI_RegEnumKey($hKey, $dwIndex)
; Note ..........:
; ===================================================================================================================================
Func _WinAPI_RegEnumKey(Const ByRef $hKey, Const ByRef $dwIndex)
    $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegEnumKeyExW", "ULONG_PTR", $hKey, "DWORD", $dwIndex, "WSTR", "", "DWORD*", 256, "DWORD", Null, "WSTR", Null, "DWORD*", Null, "PTR", Null)
    If @Error Or $arDllCall[0] Then Return SetError(1, (@Error ? -@Error : $arDllCall[0]), "")
    Return $arDllCall[3]
EndFunc   ;==>_WinAPI_RegEnumKey


; #FUNCTION# ========================================================================================================================
; Name...........: _WinAPI_RegEnumKeyEx
; Description ...: Enumerates the subkeys of the specified open registry key. The function retrieves information about one subkey each time it is called.
; Syntax.........: _WinAPI_RegEnumKeyEx($hKey[, $sSubKey[, $iFlags[, $sFilter]]])
; Parameters ....: $hKey   - A handle to an open registry key. The key must have been opened with the KEY_ENUMERATE_SUB_KEYS access right.
;                              For more information, see Registry Key Security and Access Rights.
;                            This handle is returned by the _WinAPI_RegCreateKeyEx or _WinAPI_RegOpenKeyEx or _WinAPI_RegCreateKey or _WinAPI_RegOpenKey
;                              function, or it can be one of the following predefined keys:
;                                $HKEY_CLASSES_ROOT
;                                $HKEY_CURRENT_CONFIG
;                                $HKEY_CURRENT_USER
;                                $HKEY_LOCAL_MACHINE
;                                $HKEY_PERFORMANCE_DATA
;                                $HKEY_USERS
;                            This parameter can be NULL, use the NULL or 0 to set NULL this parameter, If $hKey is NULL,
;                              $sSubKey must be contain Full String KeyName, for more see $sSubKey
;                  $sSubKey - Optional, The name of the registry key to Enumerate. Key names are not case sensitive.
;                               This key must be a subkey of the key identified by the $hKey parameter.
;                               if $hKey is Null this parameter must be a Full String KeyName, example
;                                 "HKLM\SOFTWARE\Example" or "HKEY_USERS" or "HKEY_CURRENT_USER\Software"
;                                 "\Registry\Machine\SOFTWARE\Example" or "\Registry\User" or "\Registry\User\CurrentUser"
;                                 "MACHINE\Software\Example" or "USERS" or "CURRENT_USER\Software"
;                                 "CLASSES_ROOT\Example" or in a remote registry such as \\ComputerName\CLASSES_ROOT\Example.
;                               If $hKey is one of the predefined keys, $sSubKey may be NULL. In that case, return the same $hKey handle passed in to the function.
;                  $iFlags  - Optional specifies Recursion (add the flags together for multiple operations):
;                  |$iFlags = 0 (Default) All Key-SubKeys Recursive Mod
;                  |$iFlags = 1 All SubKeys Not Recursive Mod
;                  |$iFlags = 2 Disable the return the count in the first element - effectively makes the array 0-based (must use UBound()
;                  |              to get the size in this case). By Default the first element ($array[0]) contains the number of
;                  |              keys\subkeys\values returned, the remaining elements ($array[1], $array[2], etc.)
;                  |  These flags are ignored by 32-bit Windows
;                  |$iFlags = 256 operate on the 64-bit registry view, $KEY_WOW64_64KEY (256)
;                  |$iFlags = 512 operate on the 32-bit registry view, $KEY_WOW64_32KEY (512)
;                  $sFilter - Optional the filter to use, default is ".*", $sFilter is REGEXP Mod, See Pattern Parameters in StringRegExp
; Return values .: return value is Array, If the function succeeds set ERROR_SUCCESS error code
;                  If the function fails set nonzero error code, and set Extended error code defined in WinError.h
;                    @Extended: -1 = unable to use the DLL file,
;                               -2 = unknown "return type",
;                               -3 = "function" not found in the DLL file,
;                               -4 = bad number of parameters,
;                               -5 = bad parameter.
;                               0+ = error code defined in WinError.h
; Author ........: DXRW4E
; Modified.......:
; Remarks .......: While an application is using the _WinAPI_RegEnumKeyEx function, it should not make calls to any registration
;                    functions that might change the key being enumerated.
; Related .......:
; Link ..........:
; Example .......:
; Example .......:  _WinAPI_RegEnumKeyEx($HKEY_LOCAL_MACHINE, "SOFTWARE\KeyName")
;                   _WinAPI_RegEnumKeyEx(Null, "HKEY_LOCAL_MACHINE\SOFTWARE\KeyName")
; Note ..........:
; ===================================================================================================================================
Func _WinAPI_RegEnumKeyEx(Const ByRef $hKey, $sSubKey = "", $iFlags = 0, $sFilter = ".*")
    Static $aIndexSubKey[515][3] = [[512],[0,0]], $I, $aArray[1] = [Null]
    Local $sKeyList, $iNoRecursive = BitAND($iFlags, 1), $iFilter = ($sFilter == ".*" ? 0 : 1), $samDesired = 8 + BitAND($iFlags, 768) ;; $KEY_WOW64_* + $KEY_ENUMERATE_SUB_KEYS = 0x0008
    $aIndexSubKey[1][1] = _WinAPI_RegOpenKey($hKey, $sSubKey, $samDesired)
    If @Error Then Return SetError(1, @Extended, $aArray)
    ;; just to check DllCall @Error, to not check it more during the While\WEnd
    $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegEnumKeyExW", "ULONG_PTR", $aIndexSubKey[1][1], "DWORD", 0, "WSTR", "", "DWORD*", 256, "DWORD", Null, "WSTR", Null, "DWORD*", Null, "PTR", Null)
    $I = (@Error Or $arDllCall[0]) ? 0 : 1
    While $I
        $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegEnumKeyExW", "ULONG_PTR", $aIndexSubKey[$I][1], "DWORD", $aIndexSubKey[$I][0], "WSTR", "", "DWORD*", 256, "DWORD", Null, "WSTR", Null, "DWORD*", Null, "PTR", Null)
        If $arDllCall[0] Then
            DllCall($hAdvapi32Dll, "LONG", "RegCloseKey", "ULONG_PTR", $arDllCall[1])
            $aIndexSubKey[$I][0] = 0
            $aIndexSubKey[$I][1] = 0
            $aIndexSubKey[$I][2] = ""
            $I -= 1
            ContinueLoop
        EndIf
        $aIndexSubKey[$I][0] += 1
        $aIndexSubKey[$I+1][2] = $aIndexSubKey[$I][2] & "\" & $arDllCall[3]
        $sKeyList &= Not $iFilter ? @LF & $aIndexSubKey[$I+1][2] : (StringRegExp($arDllCall[3], $sFilter) ? @LF & $aIndexSubKey[$I+1][2] : "")
        If $iNoRecursive Then ContinueLoop
        $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegOpenKeyExW", "ULONG_PTR", $aIndexSubKey[$I][1], "WSTR", $arDllCall[3], "DWORD", $REG_SPECIAL_ACCESS, "DWORD", $samDesired, "ULONG_PTR*", 0)
        If $arDllCall[0] Then ContinueLoop
        $I += 1
        ;;If $I > $aIndexSubKey[0][0] Then ;; (will not have to ever happen) Error Registry Element Size Limits (A registry tree can be 512 levels deep) - http://msdn.microsoft.com/en-us/library/windows/desktop/ms724872(v=vs.85).aspx
        ;;  $aIndexSubKey[0][0] *= 2
        ;;  ReDim $aIndexSubKey[$aIndexSubKey[0][0] + 1][3]
        ;;EndIf
        $aIndexSubKey[$I][1] = $arDllCall[5]
    WEnd
    If $aIndexSubKey[1][1] Then SetError(@Error + DllCall($hAdvapi32Dll, "LONG", "RegCloseKey", "ULONG_PTR", $aIndexSubKey[1][1]))
    If Not $sKeyList Then Return SetError(3, (@Error ? -@Error : $arDllCall[0]), $aArray)
    Return StringSplit(StringTrimLeft($sKeyList, 2), @LF & "\", 1 + BitAND($iFlags, 2))
EndFunc   ;==>_WinAPI_RegEnumKeyEx


; #FUNCTION# ========================================================================================================================
; Name...........: _WinAPI_RegEnumValue
; Description ...: Enumerates the values for the specified open registry key. The function copies one indexed value name and data block
;                    for the key each time it is called.
; Syntax.........: _WinAPI_RegEnumValue($hKey, $dwIndex)
; Parameters ....: $hKey    - A handle to an open registry key. The key must have been opened with the KEY_QUERY_VALUE access right.
;                               For more information, see Registry Key Security and Access Rights.
;                               This handle is returned by the _WinAPI_RegCreateKeyEx or _WinAPI_RegOpenKeyEx or _WinAPI_RegCreateKey or _WinAPI_RegOpenKey
;                                 function, or it can be one of the following predefined keys:
;                                     $HKEY_CLASSES_ROOT
;                                     $HKEY_CURRENT_CONFIG
;                                     $HKEY_CURRENT_USER
;                                     $HKEY_LOCAL_MACHINE
;                                     $HKEY_PERFORMANCE_DATA
;                                     $HKEY_USERS
;                  $dwIndex -  The index of the subkey to retrieve. This parameter should be zero for the first call to the _WinAPI_RegEnumValue
;                                function and then incremented for subsequent calls.
;                              Because values are not ordered, any new value will have an arbitrary index. This means that the function
;                                may return values in any order.
; Return values .: If the function succeeds, the return value is name of the subkey and set ERROR_SUCCESS error code
;                  If the function fails, the return value is a None '', and set nonzero error code, and set Extended error code defined in WinError.h
;                    @Extended: -1 = unable to use the DLL file,
;                               -2 = unknown "return type",
;                               -3 = "function" not found in the DLL file,
;                               -4 = bad number of parameters,
;                               -5 = bad parameter.
;                               0+ = error code defined in WinError.h
; Author ........: DXRW4E
; Modified.......:
; Remarks .......: To enumerate values, an application should initially call the _WinAPI_RegEnumValue function with the dwIndex
;                    parameter set to zero. The application should then increment dwIndex and call the _WinAPI_RegEnumValue function
;                    until there are no more values (until the function returns ERROR_NO_MORE_ITEMS).
;                  The application can also set dwIndex to the index of the last value on the first call to the function
;                    and decrement the index until the value with index 0 is enumerated. To retrieve the index of the last value,
;                    use the RegQueryInfoKey function.
;                  While using _WinAPI_RegEnumValue, an application should not call any registry functions that might change the key being queried.
;                  If the data has the REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ type, the string may not have been stored with
;                    the proper null-terminating characters. Therefore, even if the function returns ERROR_SUCCESS, the
;                    application should ensure that the string is properly terminated before using it; otherwise, it may
;                    overwrite a buffer. (Note that REG_MULTI_SZ strings should have two null-terminating characters.)
;                  To determine the maximum size of the name and data buffers, use the RegQueryInfoKey function.
; Related .......:
; Link ..........:
; Example .......:
; Example .......:  _WinAPI_RegEnumValue($hKey, $dwIndex)
; Note ..........:
; ===================================================================================================================================
Func _WinAPI_RegEnumValue(Const ByRef $hKey, Const ByRef $dwIndex)
    $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegEnumValueW", "ULONG_PTR", $hKey, "DWORD", $dwIndex, "WSTR", "", "DWORD*", 16384, "DWORD", Null, "DWORD*", 0, "PTR", Null, "PTR", Null)
    If @Error Or $arDllCall[0] Then Return SetError(1, (@Error ? -@Error : $arDllCall[0]), "")
    Return SetExtended($arDllCall[6], $arDllCall[3])
EndFunc   ;==>_WinAPI_RegEnumValue


; #FUNCTION# ========================================================================================================================
; Name...........: _WinAPI_RegEnumValueEx
; Description ...: Enumerates the values for the specified open registry key. The function copies one indexed value name and data block
;                    for the key each time it is called.
; Syntax.........: _WinAPI_RegEnumValueEx($hKey[, $sSubKey[, $samDesired, $sFilter]]])
; Parameters ....: $hKey       - A handle to an open registry key. The key must have been opened with the KEY_QUERY_VALUE access right.
;                                  For more information, see Registry Key Security and Access Rights.
;                                  This handle is returned by the _WinAPI_RegCreateKeyEx or _WinAPI_RegOpenKeyEx or _WinAPI_RegCreateKey or _WinAPI_RegOpenKey
;                                    function, or it can be one of the following predefined keys:
;                                        $HKEY_CLASSES_ROOT
;                                        $HKEY_CURRENT_CONFIG
;                                        $HKEY_CURRENT_USER
;                                        $HKEY_LOCAL_MACHINE
;                                        $HKEY_PERFORMANCE_DATA
;                                        $HKEY_USERS
;                  $sSubKey    - Optional, The name of the registry key to enumerate value. Key names are not case sensitive.
;                                   This key must be a subkey of the key identified by the $hKey parameter.
;                                   if $hKey is Null this key must be a Full String KeyName, example
;                                     "HKLM\SOFTWARE\Example" or "HKEY_USERS" or "HKEY_CURRENT_USER\Software"
;                                     "\Registry\Machine\SOFTWARE\Example" or "\Registry\User" or "\Registry\User\CurrentUser"
;                                     "MACHINE\Software\Example" or "USERS" or "CURRENT_USER\Software"
;                                     "CLASSES_ROOT\Example" or in a remote registry such as \\ComputerName\CLASSES_ROOT\Example.
;                  $samDesired - Optional, An access mask the specifies the platform-specific view of the registry.
;                  |$KEY_SYMBOLIC_LINK (64) - Key is Symbolic Link, query\check "SymbolicLinkValue"
;                  |  These flags are ignored by 32-bit Windows
;                  |$KEY_WOW64_64KEY (256)  - operate on the 64-bit registry view
;                  |$KEY_WOW64_32KEY (512)  - operate on the 32-bit registry view
;                  $sFilter    - Optional the filter to use, default is ".*", $sFilter is REGEXP Mod, See Pattern Parameters in StringRegExp
; Return values .: return value is 2D Array, If the function succeeds set ERROR_SUCCESS error code
;                  If the function fails set nonzero error code, and set Extended error code defined in WinError.h
;                    @Extended: -1 = unable to use the DLL file,
;                               -2 = unknown "return type",
;                               -3 = "function" not found in the DLL file,
;                               -4 = bad number of parameters,
;                               -5 = bad parameter.
;                               0+ = error code defined in WinError.h
; Author ........: DXRW4E
; Modified.......:
; Remarks .......: To enumerate values, an application should initially call the _WinAPI_RegEnumValueEx function with the dwIndex
;                    parameter set to zero. The application should then increment dwIndex and call the _WinAPI_RegEnumValueEx function
;                    until there are no more values (until the function returns ERROR_NO_MORE_ITEMS).
;                  The application can also set dwIndex to the index of the last value on the first call to the function
;                    and decrement the index until the value with index 0 is enumerated. To retrieve the index of the last value,
;                    use the RegQueryInfoKey function.
;                  While using _WinAPI_RegEnumValueEx, an application should not call any registry functions that might change the key being queried.
;                  If the data has the REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ type, the string may not have been stored with
;                    the proper null-terminating characters. Therefore, even if the function returns ERROR_SUCCESS, the
;                    application should ensure that the string is properly terminated before using it; otherwise, it may
;                    overwrite a buffer. (Note that REG_MULTI_SZ strings should have two null-terminating characters.)
;                  To determine the maximum size of the name and data buffers, use the RegQueryInfoKey function.
; Related .......:
; Link ..........:
; Example .......:
; Example .......:  _WinAPI_RegEnumValueEx($hKey)
;                   _WinAPI_RegEnumValueEx(Null, "HKLM\Software\KeyName")
;                   _WinAPI_RegEnumValueEx(Null, "HKLM\Software\KeyName", $KEY_WOW64_64KEY)
;                   _WinAPI_RegEnumValueEx(Null, "HKLM\Software\KeyName", 0, ".*ValueName.*")
; Note ..........:
; ===================================================================================================================================
Func _WinAPI_RegEnumValueEx($hKey, $sSubKey = "", $samDesired = 0, $sFilter = ".*")
    If Not $hKey Then $hKey = _RegGetPredefinedKeyEx($sSubKey, $samDesired)
    ;;Static $dwIndex = 0
    ;;$arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegEnumValueW", "ULONG_PTR", $hKey, "DWORD", $dwIndex, "WSTR", "", "DWORD*", 16384, "DWORD", Null, "DWORD*", 0, "PTR", Null, "PTR", Null)
    ;;If @Error Or $arDllCall[0] Then
    ;;  $dwIndex = 0
    ;;  Return SetError(1, (@Error ? -@Error : $arDllCall[0]), "")
    ;;EndIf
    ;;$dwIndex += 1
    ;;Return SetExtended($arDllCall[6], $arDllCall[3])
    Local $dwIndex = 0, $tData = DllStructCreate("BYTE[4096]"), $aRegEnumValue[11][3] = [[0,10,0]], $iFilter = $sFilter == ".*" ? 0 : 1
    If $sSubKey Or $samDesired Then
        $hKey = _WinAPI_RegOpenKey($hKey, $sSubKey, 1 + BitAND($samDesired, 768), (BitAND($samDesired, 64) ? 8 : 0)) ;; $KEY_QUERY_VALUE = 0x0001
        If @Error Then Return SetError(1, @Extended, $aRegEnumValue)
    EndIf
    While 1
        $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegEnumValueW", "ULONG_PTR", $hKey, "DWORD", $dwIndex, "WSTR", "", "DWORD*", 16384, "DWORD", Null, "DWORD*", 0, "STRUCT*", $tData, "DWORD*", 4096)
        If @Error Then ExitLoop
        If $arDllCall[8] > 4096 Then
            $tData = DllStructCreate("BYTE[" & $arDllCall[8] & "]")
            $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegEnumValueW", "ULONG_PTR", $hKey, "DWORD", $dwIndex, "WSTR", "", "DWORD*", 16384, "DWORD", Null, "DWORD*", 0, "STRUCT*", $tData, "DWORD*", $arDllCall[8])
        EndIf
        If $arDllCall[0] Then ExitLoop
        If $iFilter And StringRegExp($arDllCall[3], $sFilter) = 0 Then ContinueLoop
        $dwIndex += 1
        If $dwIndex > $aRegEnumValue[0][1] Then
            $aRegEnumValue[0][1] *= 2
            ReDim $aRegEnumValue[$aRegEnumValue[0][1] + 1][3]
        EndIf
        $aRegEnumValue[$dwIndex][0] = $arDllCall[3]
        $aRegEnumValue[$dwIndex][1] = $arDllCall[6]
        Switch $arDllCall[6]
            Case 1, 2, 6  ;; $REG_SZ, $REG_EXPAND_SZ, $REG_LINK
                $aRegEnumValue[$dwIndex][2] = BinaryToString(BinaryMid(DllStructGetData($tData, 1), 1, $arDllCall[8]), 2)
            Case 7  ;; $REG_MULTI_SZ
                $aRegEnumValue[$dwIndex][2] = StringRegExpReplace(BinaryToString(BinaryMid(DllStructGetData($tData, 1), 1, $arDllCall[8]), 2), "\x00+", @LF)
            Case 4  ;; $REG_DWORD, $REG_DWORD_LITTLE_ENDIAN
                $aRegEnumValue[$dwIndex][2] = DllStructGetData(DllStructCreate("DWORD", DllStructGetPtr($tData, 1)), 1) ;; Or Dec(StringRegExpReplace(BinaryMid(DllStructGetData($tData, 1), 1, 4), "^..(..)(..)(..)(..)","$4$3$2$1"), 1)
            Case 5  ;; $REG_DWORD_BIG_ENDIAN
                $aRegEnumValue[$dwIndex][2] = Dec(StringMid(BinaryMid(DllStructGetData($tData, 1), 1, $arDllCall[8]), 3, 8), 1) ;; Or Number(StringLeft(DllStructGetData($tData, 1), 10), 3)
            Case 11  ;; $REG_QWORD, $REG_QWORD_LITTLE_ENDIAN
                $aRegEnumValue[$dwIndex][2] = DllStructGetData(DllStructCreate("UINT64", DllStructGetPtr($tData, 1)), 1) ;; Or Dec(StringRegExpReplace(BinaryMid(DllStructGetData($tData, 1), 1, 8), "^..(..)(..)(..)(..)(..)(..)(..)(..)","0x$8$7$6$5$4$3$2$1"), 2)
            Case Else ;; 0 To 11 ;; 0, 3, 8, 9, 10 ;; $REG_NONE, $REG_BINARY, $REG_RESOURCE_LIST, $REG_FULL_RESOURCE_DESCRIPTOR, $REG_RESOURCE_REQUIREMENTS_LIST
                $aRegEnumValue[$dwIndex][2] = BinaryMid(DllStructGetData($tData, 1), 1, $arDllCall[8])
        EndSwitch
    WEnd
    If $sSubKey Then SetError(@Error + DllCall($hAdvapi32Dll, "LONG", "RegCloseKey", "ULONG_PTR", $hKey))
    If Not $dwIndex Then Return SetError(2, (@Error ? -@Error : $arDllCall[0]), $aRegEnumValue)
    $aRegEnumValue[0][0] = $dwIndex + 1
    Return $aRegEnumValue
EndFunc   ;==>_WinAPI_RegEnumValueEx


; #FUNCTION# ========================================================================================================================
; Name...........: _WinAPI_RegKeyExistEx
; Description ...: Check is the specified registry key exist. Note that key names are not case sensitive.
; Syntax.........: _WinAPI_RegKeyExistEx($hKey[, $sSubKey[, $samDesired[, $ulOptions]]])
; Parameters ....: $hKey       - A handle to an open registry key. This handle is returned by the _WinAPI_RegCreateKeyEx or _WinAPI_RegOpenKeyEx
;                                  or _WinAPI_RegCreateKey or _WinAPI_RegOpenKey function, or it can be one of the following predefined keys:
;                                    $HKEY_CLASSES_ROOT
;                                    $HKEY_CURRENT_CONFIG
;                                    $HKEY_CURRENT_USER
;                                    $HKEY_LOCAL_MACHINE
;                                    $HKEY_USERS
;                                This parameter can be NULL, use the NULL or 0 to set NULL this parameter, If $hKey is NULL,
;                                  $sSubKey must be contain Full String KeyName, for more see $sSubKey
;                  $sSubKey    - Optional, The name of the registry subkey to be opened. Key names are not case sensitive.
;                                  This key must be a subkey of the key identified by the $hKey parameter.
;                                  if $hKey is Null this parameter must be a Full String KeyName, example
;                                    "HKLM\SOFTWARE\Example" or "HKEY_USERS" or "HKEY_CURRENT_USER\Software"
;                                    "\Registry\Machine\SOFTWARE\Example" or "\Registry\User" or "\Registry\User\CurrentUser"
;                                    "MACHINE\Software\Example" or "USERS" or "CURRENT_USER\Software"
;                                    "CLASSES_ROOT\Example" or in a remote registry such as \\ComputerName\CLASSES_ROOT\Example.
;                                  The $sSubKey parameter can be an empty string. If $sSubKey is an empty string and $hKey is $HKEY_CLASSES_ROOT,
;                                    function return the same $hKey handle passed into the function. Otherwise, return a new handle to the key specified by $hKey.
;                                  The $sSubKey parameter can be NULL only if $hKey is one of the predefined keys. If $sSubKey is NULL and $hKey is
;                                    $HKEY_CLASSES_ROOT, function return a new handle to the key specified by $hKey. Otherwise, retun the same
;                                    $hKey handle passed in to the function.
;                  $samDesired - Optional, An access mask the specifies the platform-specific view of the registry.
;                  |$KEY_SYMBOLIC_LINK (64) - Key is Symbolic Link, Check for Symbolic Link
;                  |  This parameter can be one of the following values, These flags are ignored by 32-bit Windows
;                  |$KEY_WOW64_64KEY (256) - operate on the 64-bit registry view
;                  |$KEY_WOW64_32KEY (512) - operate on the 32-bit registry view
;                  $ulOptions  - Optional, This parameter is reserved and must be zero.
;                  | however will have to support flags such as
;                  $ulOptions  - Optional, This parameter is reserved and must be zero.
;                  | however will have to support flags such as
;                  |$REG_OPTION_OPEN_LINK (8)      - Open symbolic link, query L"SymbolicLinkValue" or set L"SymbolicLinkValue"
; Return values .: If the function succeeds, the return value is True, and set ERROR_SUCCESS error code, If the function fails,
;                    the return value is a False, and set error code defined in WinError.h
;                    And set Extended
;                    @Extended: 1 = Key is Normal Registry Key (Normale Key Exist)
;                               2 = Key is Symbolic Link (Symbolic Link Key Exist)
;                               4 = Key is Empty (5 = Normal Key & Empty Key - 6 = Symbolic Link & Key that the symbolic link refers to is Empty)
; Author ........: DXRW4E
; Modified.......:
; Remarks .......: For safety is always best to check the @Extended, for example
;                    _WinAPI_RegKeyExistEx(0, "HKLM\Software\NormalKeyName", $KEY_SYMBOLIC_LINK) - Return False and set Extended 1 or 5
;                    _WinAPI_RegKeyExistEx(0, "HKLM\Software\SymbolicLinkKeyName") - Return False and set Extended 2 or 6
; Related .......:
; Link ..........:
; Example .......:
; Example .......: _WinAPI_RegKeyExistEx(0, "HKLM\Software\KeyName")
;                  _WinAPI_RegKeyExistEx($HKEY_LOCAL_MACHINE, "Software\KeyName", $KEY_WOW64_64KEY)
; Note ..........:
; ===================================================================================================================================
Func _WinAPI_RegKeyExistEx(Const ByRef $hKey, $sSubKey = "", $samDesired = 0)
    Static $hKeyEx = 0, $hLinkKey = 0, $iEmptyKey = 0, $bLinkKey ;; $KEY_QUERY_VALUE = 0x1 ;; $KEY_ENUMERATE_SUB_KEYS = 0x8 ;; $KEY_ALL_ACCESS = 0xF003F ;; $_KEY_ALL_ACCESS = 0x3F
    If Not $sSubKey Then
        If Not _NTAPI_GetRegKeyNameByHandle($hKey) Then Return SetError(6, 0, False) ;; ERROR_INVALID_HANDLE - 6 (0x6) - The handle is invalid.
        $iEmptyKey = ((Not _WinAPI_RegEnumValue($hKeyEx, 0) And @Error) And (Not _WinAPI_RegEnumKey($hKeyEx, 0) And @Error)) ? 5 : 1
        If Not BitAND($samDesired, 64) Then Return SetExtended($iEmptyKey, True)
        $bLinkKey = ((_WinAPI_RegEnumValue($hKey, 0) = "SymbolicLinkValue" And @Extended = 6) And (Not _WinAPI_RegEnumValue($hKey, 1) And @Error) And (Not _WinAPI_RegEnumKey($hKey, 0) And @Error))
        Return SetExtended(Int($bLinkKey) + $iEmptyKey, $bLinkKey)
    EndIf
    $hKeyEx = _WinAPI_RegOpenKey($hKey, $sSubKey, BitOR($samDesired, 9))
    If @Extended = 5 Then Return SetError(5, 1, True)
    If @Error Then
        $hLinkKey = _WinAPI_RegOpenKey($hKey, $sSubKey, BitOR($samDesired, 1), 8) ;; $REG_OPTION_OPEN_LINK = 8
        If @Error Then Return SetError(@Extended, 0, False)
        Return SetExtended(2 + DllCall($hAdvapi32Dll, "LONG", "RegCloseKey", "ULONG_PTR", $hLinkKey), (BitAND($samDesired, 64) ? True : False))
    EndIf
    $iEmptyKey = ((Not _WinAPI_RegEnumValue($hKeyEx, 0) And @Error) And (Not _WinAPI_RegEnumKey($hKeyEx, 0) And @Error)) ? 5 : 1
    If Not BitAND($samDesired, 64) Then Return SetExtended($iEmptyKey + DllCall($hAdvapi32Dll, "LONG", "RegCloseKey", "ULONG_PTR", $hKeyEx), True)
    $hLinkKey = _WinAPI_RegOpenKey($hKey, $sSubKey, 1, 8) ;; $REG_OPTION_OPEN_LINK = 8
    $bLinkKey = $sSubKey ? (_NTAPI_GetRegKeyNameByHandle($hKeyEx) <> _NTAPI_GetRegKeyNameByHandle($hLinkKey)) : ((_WinAPI_RegEnumValue($hKey, 0) = "SymbolicLinkValue" And @Extended = 6) And (Not _WinAPI_RegEnumValue($hLinkKey, 1) And @Error) And (Not _WinAPI_RegEnumKey($hLinkKey, 0) And @Error))
    DllCall($hAdvapi32Dll, "LONG", "RegCloseKey", "ULONG_PTR", $hKeyEx)
    DllCall($hAdvapi32Dll, "LONG", "RegCloseKey", "ULONG_PTR", $hLinkKey)
    Return SetExtended(Int($bLinkKey) + $iEmptyKey, $bLinkKey)
EndFunc


; #FUNCTION# ========================================================================================================================
; Name...........: _WinAPI_RegSetValue
; Description ...: Sets the data and type of a specified value under a registry key.
; Syntax.........: _WinAPI_RegSetValue($hKey[, $sValueName[, $vData[, $dwType]]])
; Parameters ....: $hKey       - A handle to an open registry key. The key must have been opened with the $KEY_SET_VALUE access right.
;                                  For more information, see Registry Key Security and Access Rights.
;                                This handle is returned by the _WinAPI_RegCreateKey, _WinAPI_RegCreateKeyEx, _WinAPI_RegOpenKey, _WinAPI_RegOpenKeyEx,
;                                  or RegOpenKeyTransacted function. It can also be one of the following predefined keys:
;                                    $HKEY_CLASSES_ROOT
;                                    $HKEY_CURRENT_CONFIG
;                                    $HKEY_CURRENT_USER
;                                    $HKEY_LOCAL_MACHINE
;                                    $HKEY_USERS
;                                The Unicode version of this function supports the following additional predefined keys:
;                                    $HKEY_PERFORMANCE_TEXT
;                                    $HKEY_PERFORMANCE_NLSTEXT
;                  $sValueName - Optional, The name of the value to be set. If a value with this name is not already present in the key, the function adds it to the key.
;                                If $sValueName is NULL or an empty string, "", the function sets the type and data for the key's unnamed or default value.
;                                For more information, see Registry Element Size Limits.
;                                Registry keys do not have default values, but they can have one unnamed value, which can be of any type.
;                  $dwType     - Optional, The type of data pointed to by the lpData parameter. For a list of the possible types, see Registry Value Types.
;                  |$REG_NONE (0)                - No defined value type.
;                  |$REG_SZ (1)                  - (Default) A null-terminated string. This will be either a Unicode or an ANSI string, depending on whether
;                  |                                you use the Unicode or ANSI functions.
;                  |$REG_EXPAND_SZ (2)           - A null-terminated string that contains unexpanded references to environment variables (for example,
;                  |                                "%PATH%"). It will be a Unicode or ANSI string depending on whether you use the Unicode or ANSI functions.
;                  |                                To expand the environment variable references, use the ExpandEnvironmentStrings function.
;                  |$REG_BINARY (3)              - Binary data in any form.
;                  |$REG_DWORD (4)               - A 32-bit number.
;                  |$REG_DWORD_LITTLE_ENDIAN (4) - A 32-bit number in little-endian format.
;                  |                               Windows is designed to run on little-endian computer architectures. Therefore, this value is defined
;                  |                                as REG_DWORD in the Windows header files.
;                  |$REG_DWORD_BIG_ENDIAN (5)    - A 32-bit number in big-endian format. Some UNIX systems support big-endian architectures.
;                  |$REG_LINK (6)                - A null-terminated Unicode string that contains the target path of a symbolic link that was
;                  |                                created by calling the RegCreateKeyEx function with REG_OPTION_CREATE_LINK.
;                  |$REG_MULTI_SZ (7)            - A sequence of null-terminated strings, terminated by an empty string (\0).
;                  |                               The following is an example:
;                  |                                 String1\0String2\0String3\0LastString\0\0
;                  |                                 The first \0 terminates the first string, the second to the last \0 terminates the last string, and the
;                  |                                  final \0 terminates the sequence. Note that the final terminator must be factored into the length of the string.
;                  |$REG_RESOURCE_LIST (8)               - Resource list in the resource map
;                  |$REG_FULL_RESOURCE_DESCRIPTOR (9)    - Resource list in the hardware description
;                  |$REG_RESOURCE_REQUIREMENTS_LIST (10) - Resource list in the hardware description
;                  |$REG_QWORD (11)               - A 64-bit number.
;                  |$REG_QWORD_LITTLE_ENDIAN (11) - A 64-bit number in little-endian format.
;                  |                                Windows is designed to run on little-endian computer architectures. Therefore, this value is defined
;                  |                                 as REG_QWORD in the Windows header files.
; Return values .: If the function succeeds, the return value is ERROR_SUCCESS. and set ERROR_SUCCESS error code
;                  If the function fails, the return value is nonzero, and set nonzero error code, and set Extended error code defined in WinError.h
;                    @Extended: -1 = unable to use the DLL file,
;                               -2 = unknown "return type",
;                               -3 = "function" not found in the DLL file,
;                               -4 = bad number of parameters,
;                               -5 = bad parameter.
;                               0+ = error code defined in WinError.h
; Author ........: DXRW4E
; Modified.......:
; Remarks .......: Calling _WinAPI_RegSetValue is an expensive operation that significantly affects system-wide performance as
;                    it consumes disk bandwidth and blocks modifications to all keys by all processes in the registry hive that
;                    is being flushed until the flush operation completes. _WinAPI_RegSetValue should only be called xplicitly
;                    ewhen an application must guarantee that registry changes are persisted to disk immediately after modification.
;                    All modifications made to keys are visible to other processes without the need to flush them to disk.
;                  Alternatively, the registry has a 'lazy flush' mechanism that flushes registry modifications to disk at regular
;                    intervals of time. In addition to this regular flush operation, registry changes are also flushed to disk at
;                    system shutdown. Allowing the 'lazy flush' to flush registry changes is the most efficient way to manage registry
;                    writes to the registry store on disk.
;                  The _WinAPI_RegSetValue function returns only when all the data for the hive that contains the specified key
;                    has been written to the registry store on disk.
;                  The _WinAPI_RegSetValue function writes out the data for other keys in the hive that have been modified since
;                    the last lazy flush or system start.
;                  After _WinAPI_RegSetValue returns, use _WinAPI_RegCloseKey to close the handle to the registry key.
; Related .......:
; Link ..........:
; Example .......:
; Example .......: _WinAPI_RegSetValue($hKey, "Test", "This is Test", $REG_SZ)
; Note ..........:
; ===================================================================================================================================
Func _WinAPI_RegSetValue(Const ByRef $hKey, $sValueName = "", $vData = "", $dwType = 1) ;; $REG_SZ = 1
    Static $tData = DllStructCreate("BYTE[4096]"), $cbData, $lpData = $tData
    Switch $dwType
        Case 1, 2  ;; $REG_SZ, $REG_EXPAND_SZ
            If Not IsBinary($vData) Then $vData = StringToBinary(StringRegExpReplace(StringRegExpReplace($vData, "\\", "\\\\"), "\x00*+$", "") & Chr(0), 2)
            ;$tData = DllStructCreate("BYTE[" & BinaryLen($vData) & "]")
        Case 5  ;; $REG_DWORD_BIG_ENDIAN
            If Not IsBinary($vData) Then $vData = Binary("0x" & Hex($vData, 8))
        Case 6  ;; $REG_LINK
            ;;If (_WinAPI_RegEnumValue($hKey, 0) = "SymbolicLinkValue" And @Extended = 6) And (Not _WinAPI_RegEnumValue($hKey, 1) And @Error) And (Not _WinAPI_RegEnumKey($hKey, 0) And @Error) Then Return SetError(2, 87, 87)
            If Not IsBinary($vData) Then $vData = StringToBinary((StringRegExp($vData, "(?i)^\\Registry\\") ? $vData : _RegGetObjectNameKey($vData)), 2)
        Case 7  ;; $REG_MULTI_SZ
            If Not IsBinary($vData) Then $vData = StringToBinary(StringRegExpReplace(StringRegExpReplace(StringRegExpReplace($vData, "\n", Chr(0)), "\\", "\\\\"), "\x00*+$", "") & Chr(0) & Chr(0), 2)
            ;$tData = DllStructCreate("BYTE[" & BinaryLen($vData) & "]")
        Case 0 To 11  ;; 0, 3, 4, 8, 9, 10, 11  ;; $REG_NONE, $REG_BINARY, $REG_DWORD, $REG_RESOURCE_LIST, $REG_FULL_RESOURCE_DESCRIPTOR, $REG_RESOURCE_REQUIREMENTS_LIST, $REG_QWORD
        ;;Case 4  ;; $REG_DWORD, $REG_DWORD_LITTLE_ENDIAN
        ;;  $tData = DllStructCreate("DWORD")
        ;; or
        ;;  DllStructCreate("BYTE[4]")
        ;;  If Not IsBinary($vData) Then $vData = Binary(StringRegExpReplace(Hex($vData, 8), "^(..)(..)(..)(..)","0x$4$3$2$1"))
        ;;Case 11  ;; $REG_QWORD, $REG_QWORD_LITTLE_ENDIAN
        ;;  $tData = DllStructCreate("UINT64")
        ;; or
        ;;  DllStructCreate("BYTE[8]")
        ;;  If Not IsBinary($vData) Then $vData = Binary(StringRegExpReplace(Hex($vData, 16), "^(..)(..)(..)(..)(..)(..)(..)(..)","0x$8$7$6$5$4$3$2$1"))
        ;;Case 0, 3, 8, 9, 10  ;; $REG_NONE, $REG_BINARY, $REG_RESOURCE_LIST, $REG_FULL_RESOURCE_DESCRIPTOR, $REG_RESOURCE_REQUIREMENTS_LIST
        ;;  $tData = DllStructCreate("BYTE[" & BinaryLen($vData) & "]")
        Case Else
            Return SetError(2, 87, 87)
    EndSwitch
    $cbData = $dwType = 11 ? 8 : BinaryLen($vData)
    If $cbData > 4096 Then $tData = DllStructCreate("BYTE[" & $cbData & "]")
    DllStructSetData($tData, 1, $vData)
    $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegSetValueExW", "ULONG_PTR", $hKey, "WSTR", $sValueName, "DWORD", 0, "DWORD", $dwType, "STRUCT*", $tData, "DWORD", $cbData)
    If $cbData > 4096 Then $tData = $lpData
    If @Error Then Return SetError(1, -@Error, -@Error)
    Return SetError($arDllCall[0], $arDllCall[0], $arDllCall[0])
EndFunc


; #FUNCTION# ========================================================================================================================
; Name...........: _WinAPI_RegSetValueEx
; Description ...: Sets the data and type of a specified value under a registry key.
; Syntax.........: _WinAPI_RegSetValueEx($hKey[, $sSubKey[, $sValueName[, $vData[, $dwType[, $samDesired]]]]])
; Parameters ....: $hKey       - A handle to an open registry key. The key must have been opened with the $KEY_SET_VALUE access right.
;                                  For more information, see Registry Key Security and Access Rights.
;                                This handle is returned by the _WinAPI_RegCreateKey, _WinAPI_RegCreateKeyEx, _WinAPI_RegOpenKey, _WinAPI_RegOpenKeyEx,
;                                  or RegOpenKeyTransacted function. It can also be one of the following predefined keys:
;                                    $HKEY_CLASSES_ROOT
;                                    $HKEY_CURRENT_CONFIG
;                                    $HKEY_CURRENT_USER
;                                    $HKEY_LOCAL_MACHINE
;                                    $HKEY_USERS
;                                The Unicode version of this function supports the following additional predefined keys:
;                                    $HKEY_PERFORMANCE_TEXT
;                                    $HKEY_PERFORMANCE_NLSTEXT
;                                This parameter can be NULL, use the NULL or 0 to set NULL this parameter, If $hKey is NULL,
;                                  $sSubKey must be contain Full String KeyName, for more see $sSubKey
;                  $sSubKey    - Optional, The name of the registry key to set the value. Key names are not case sensitive.
;                                  This key must be a subkey of the key identified by the $hKey parameter.
;                                  if $hKey is Null this key must be a Full String KeyName, example
;                                    "HKLM\SOFTWARE\Example" or "HKEY_USERS" or "HKEY_CURRENT_USER\Software"
;                                    "\Registry\Machine\SOFTWARE\Example" or "\Registry\User" or "\Registry\User\CurrentUser"
;                                    "MACHINE\Software\Example" or "USERS" or "CURRENT_USER\Software"
;                                    "CLASSES_ROOT\Example" or in a remote registry such as \\ComputerName\CLASSES_ROOT\Example.
;                                  If this parameter is NULL or an empty string, the function returns the same handle that was passed in.
;                  $sValueName - Optional, The name of the value to be set. If a value with this name is not already present in the key, the function adds it to the key.
;                                If $sValueName is NULL or an empty string, "", the function sets the type and data for the key's unnamed or default value.
;                                For more information, see Registry Element Size Limits.
;                                Registry keys do not have default values, but they can have one unnamed value, which can be of any type.
;                  $dwType     - Optional, The type of data pointed to by the lpData parameter. For a list of the possible types, see Registry Value Types.
;                  |$REG_NONE (0)                - No defined value type.
;                  |$REG_SZ (1)                  - (Default) A null-terminated string. This will be either a Unicode or an ANSI string, depending on whether
;                  |                                you use the Unicode or ANSI functions.
;                  |$REG_EXPAND_SZ (2)           - A null-terminated string that contains unexpanded references to environment variables (for example,
;                  |                                "%PATH%"). It will be a Unicode or ANSI string depending on whether you use the Unicode or ANSI functions.
;                  |                                To expand the environment variable references, use the ExpandEnvironmentStrings function.
;                  |$REG_BINARY (3)              - Binary data in any form.
;                  |$REG_DWORD (4)               - A 32-bit number.
;                  |$REG_DWORD_LITTLE_ENDIAN (4) - A 32-bit number in little-endian format.
;                  |                               Windows is designed to run on little-endian computer architectures. Therefore, this value is defined
;                  |                                as REG_DWORD in the Windows header files.
;                  |$REG_DWORD_BIG_ENDIAN (5)    - A 32-bit number in big-endian format. Some UNIX systems support big-endian architectures.
;                  |$REG_LINK (6)                - A null-terminated Unicode string that contains the target path of a symbolic link that was
;                  |                                created by calling the RegCreateKeyEx function with REG_OPTION_CREATE_LINK.
;                  |$REG_MULTI_SZ (7)            - A sequence of null-terminated strings, terminated by an empty string (\0).
;                  |                               The following is an example:
;                  |                                 String1\0String2\0String3\0LastString\0\0
;                  |                                 The first \0 terminates the first string, the second to the last \0 terminates the last string, and the
;                  |                                  final \0 terminates the sequence. Note that the final terminator must be factored into the length of the string.
;                  |$REG_RESOURCE_LIST (8)               - Resource list in the resource map
;                  |$REG_FULL_RESOURCE_DESCRIPTOR (9)    - Resource list in the hardware description
;                  |$REG_RESOURCE_REQUIREMENTS_LIST (10) - Resource list in the hardware description
;                  |$REG_QWORD (11)               - A 64-bit number.
;                  |$REG_QWORD_LITTLE_ENDIAN (11) - A 64-bit number in little-endian format.
;                  |                                Windows is designed to run on little-endian computer architectures. Therefore, this value is defined
;                  |                                 as REG_QWORD in the Windows header files.
;                  $samDesired - Optional, An access mask the specifies the platform-specific view of the registry.
;                  |  This parameter can be one of the following values, These flags are ignored by 32-bit Windows
;                  |$KEY_WOW64_64KEY (256) - operate on the 64-bit registry view
;                  |$KEY_WOW64_32KEY (512) - operate on the 32-bit registry view
; Return values .: If the function succeeds, the return value is ERROR_SUCCESS. and set ERROR_SUCCESS error code
;                  If the function fails, the return value is nonzero, and set nonzero error code, and set Extended error code defined in WinError.h
;                    @Extended: -1 = unable to use the DLL file,
;                               -2 = unknown "return type",
;                               -3 = "function" not found in the DLL file,
;                               -4 = bad number of parameters,
;                               -5 = bad parameter.
;                               0+ = error code defined in WinError.h
; Author ........: DXRW4E
; Modified.......:
; Remarks .......: Calling _WinAPI_RegSetValueEx is an expensive operation that significantly affects system-wide performance as
;                    it consumes disk bandwidth and blocks modifications to all keys by all processes in the registry hive that
;                    is being flushed until the flush operation completes. _WinAPI_RegSetValueEx should only be called xplicitly
;                    ewhen an application must guarantee that registry changes are persisted to disk immediately after modification.
;                    All modifications made to keys are visible to other processes without the need to flush them to disk.
;                  Alternatively, the registry has a 'lazy flush' mechanism that flushes registry modifications to disk at regular
;                    intervals of time. In addition to this regular flush operation, registry changes are also flushed to disk at
;                    system shutdown. Allowing the 'lazy flush' to flush registry changes is the most efficient way to manage registry
;                    writes to the registry store on disk.
;                  The _WinAPI_RegSetValueEx function returns only when all the data for the hive that contains the specified key
;                    has been written to the registry store on disk.
;                  The _WinAPI_RegSetValueEx function writes out the data for other keys in the hive that have been modified since
;                    the last lazy flush or system start.
;                  After _WinAPI_RegSetValueEx returns, use _WinAPI_RegCloseKey to close the handle to the registry key.
; Related .......:
; Link ..........:
; Example .......:
; Example .......: _WinAPI_RegSetValueEx($hKey, Null, "Test", "This is Test", $REG_SZ)
;                  _WinAPI_RegSetValueEx($HKEY_LOCAL_MACHINE, "SOFTWARE\KeyName", "Test", "This is Test", $REG_SZ)
; Note ..........:
; ===================================================================================================================================
Func _WinAPI_RegSetValueEx($hKey, $sSubKey = "", $sValueName = "", $vData = "", $dwType = 1, $samDesired = 0)
    ;Static $_WIN32_WINNT5 = StringRegExp(@OSVersion, "(?i)WIN_(?:XP|XPe|2000|2003)")
    Switch $dwType
        Case 1, 2  ;; $REG_SZ, $REG_EXPAND_SZ
            If Not IsBinary($vData) Then $vData = StringToBinary(StringRegExpReplace(StringRegExpReplace($vData, "\\", "\\\\"), "\x00*+$", "") & Chr(0), 2)
        Case 5  ;; $REG_DWORD_BIG_ENDIAN
            If Not IsBinary($vData) Then $vData = Binary("0x" & Hex($vData, 8))
        Case 6  ;; $REG_LINK
            If Not _WinAPI_RegKeyExistEx($hKey, $sSubKey, BitOR($samDesired, 64)) And @Extended Then Return SetError(4, 2, 2)
            If Not IsBinary($vData) Then $vData = StringToBinary((StringRegExp($vData, "(?i)^\\Registry\\") ? $vData : _RegGetObjectNameKey($vData)), 2)
        Case 7  ;; $REG_MULTI_SZ
            If Not IsBinary($vData) Then $vData = StringToBinary(StringRegExpReplace(StringRegExpReplace(StringRegExpReplace($vData, "\n", Chr(0)), "\\", "\\\\"), "\x00*+$", "") & Chr(0) & Chr(0), 2)
        Case 0 To 11  ;; 0, 3, 4, 8, 9, 10, 11  ;; $REG_NONE, $REG_BINARY, $REG_DWORD, $REG_RESOURCE_LIST, $REG_FULL_RESOURCE_DESCRIPTOR, $REG_RESOURCE_REQUIREMENTS_LIST, $REG_QWORD
            ;;
        Case Else
            Return SetError(2, 87, 87)
    EndSwitch
    Local $cbData = ($dwType = 11 ? 8 : BinaryLen($vData)), $tData = DllStructCreate("BYTE[" & $cbData & "]")
    DllStructSetData($tData, 1, $vData)
    If Not $hKey Then $hKey = _RegGetPredefinedKeyEx($sSubKey, $samDesired)
    If $sSubKey Or $samDesired Then
        Local $hKeyEx = _WinAPI_RegCreateKey($hKey, $sSubKey, 2 + BitAND($samDesired, 768), ($dwType = 6 ? 2 : 0))
        If @Error And $dwType = 6 Then $hKeyEx = _WinAPI_RegOpenKey($hKey, $sSubKey, 2 + BitAND($samDesired, 768), 8)
        If @Error Then Return SetError(3, @Extended, @Extended)
        $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegSetValueExW", "ULONG_PTR", $hKeyEx, "WSTR", $sValueName, "DWORD", 0, "DWORD", $dwType, "STRUCT*", $tData, "DWORD", $cbData)
        SetError(@Error + DllCall($hAdvapi32Dll, "LONG", "RegCloseKey", "ULONG_PTR", $hKeyEx))
    Else
        $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegSetValueExW", "ULONG_PTR", $hKey, "WSTR", $sValueName, "DWORD", 0, "DWORD", $dwType, "STRUCT*", $tData, "DWORD", $cbData)
    EndIf
    If @Error Then Return SetError(1, -@Error, -@Error)
    Return SetError($arDllCall[0], $arDllCall[0], $arDllCall[0])
EndFunc


; #FUNCTION# ========================================================================================================================
; Name...........: _WinAPI_RegSetKeyValue
; Description ...: Sets the data for the specified value in the specified registry key and subkey, Minimum supported client Windows Vista
; Syntax.........: _WinAPI_RegSetKeyValue($hKey[, $sSubKey[, $sValueName[, $vData[, $dwType[, $samDesired]]]]])
; Parameters ....: $hKey       - A handle to an open registry key. The key must have been opened with the $KEY_SET_VALUE access right.
;                                  For more information, see Registry Key Security and Access Rights.
;                                This handle is returned by the _WinAPI_RegCreateKey, _WinAPI_RegCreateKeyEx, _WinAPI_RegOpenKey, _WinAPI_RegOpenKeyEx,
;                                  or RegOpenKeyTransacted function. It can also be one of the following predefined keys:
;                                    $HKEY_CLASSES_ROOT
;                                    $HKEY_CURRENT_CONFIG
;                                    $HKEY_CURRENT_USER
;                                    $HKEY_LOCAL_MACHINE
;                                    $HKEY_USERS
;                                The Unicode version of this function supports the following additional predefined keys:
;                                    $HKEY_PERFORMANCE_TEXT
;                                    $HKEY_PERFORMANCE_NLSTEXT
;                                This parameter can be NULL, use the NULL or 0 to set NULL this parameter, If $hKey is NULL,
;                                  $sSubKey must be contain Full String KeyName, for more see $sSubKey
;                  $sSubKey    - Optional, The name of the registry key to set the value. Key names are not case sensitive.
;                                  This key must be a subkey of the key identified by the $hKey parameter.
;                                  if $hKey is Null this key must be a Full String KeyName, example
;                                    "HKLM\SOFTWARE\Example" or "HKEY_USERS" or "HKEY_CURRENT_USER\Software"
;                                    "\Registry\Machine\SOFTWARE\Example" or "\Registry\User" or "\Registry\User\CurrentUser"
;                                    "MACHINE\Software\Example" or "USERS" or "CURRENT_USER\Software"
;                                    "CLASSES_ROOT\Example" or in a remote registry such as \\ComputerName\CLASSES_ROOT\Example.
;                                  If this parameter is NULL or an empty string, the function returns the same handle that was passed in.
;                  $sValueName - Optional, The name of the value to be set. If a value with this name is not already present in the key, the function adds it to the key.
;                                If $sValueName is NULL or an empty string, "", the function sets the type and data for the key's unnamed or default value.
;                                For more information, see Registry Element Size Limits.
;                                Registry keys do not have default values, but they can have one unnamed value, which can be of any type.
;                  $dwType     - Optional, The type of data pointed to by the lpData parameter. For a list of the possible types, see Registry Value Types.
;                  |$REG_NONE (0)                - No defined value type.
;                  |$REG_SZ (1)                  - (Default) A null-terminated string. This will be either a Unicode or an ANSI string, depending on whether
;                  |                                you use the Unicode or ANSI functions.
;                  |$REG_EXPAND_SZ (2)           - A null-terminated string that contains unexpanded references to environment variables (for example,
;                  |                                "%PATH%"). It will be a Unicode or ANSI string depending on whether you use the Unicode or ANSI functions.
;                  |                                To expand the environment variable references, use the ExpandEnvironmentStrings function.
;                  |$REG_BINARY (3)              - Binary data in any form.
;                  |$REG_DWORD (4)               - A 32-bit number.
;                  |$REG_DWORD_LITTLE_ENDIAN (4) - A 32-bit number in little-endian format.
;                  |                               Windows is designed to run on little-endian computer architectures. Therefore, this value is defined
;                  |                                as REG_DWORD in the Windows header files.
;                  |$REG_DWORD_BIG_ENDIAN (5)    - A 32-bit number in big-endian format. Some UNIX systems support big-endian architectures.
;                  |$REG_LINK (6)                - A null-terminated Unicode string that contains the target path of a symbolic link that was
;                  |                                created by calling the RegCreateKeyEx function with REG_OPTION_CREATE_LINK.
;                  |$REG_MULTI_SZ (7)            - A sequence of null-terminated strings, terminated by an empty string (\0).
;                  |                               The following is an example:
;                  |                                 String1\0String2\0String3\0LastString\0\0
;                  |                                 The first \0 terminates the first string, the second to the last \0 terminates the last string, and the
;                  |                                  final \0 terminates the sequence. Note that the final terminator must be factored into the length of the string.
;                  |$REG_RESOURCE_LIST (8)               - Resource list in the resource map
;                  |$REG_FULL_RESOURCE_DESCRIPTOR (9)    - Resource list in the hardware description
;                  |$REG_RESOURCE_REQUIREMENTS_LIST (10) - Resource list in the hardware description
;                  |$REG_QWORD (11)               - A 64-bit number.
;                  |$REG_QWORD_LITTLE_ENDIAN (11) - A 64-bit number in little-endian format.
;                  |                                Windows is designed to run on little-endian computer architectures. Therefore, this value is defined
;                  |                                 as REG_QWORD in the Windows header files.
;                  $samDesired - Optional, An access mask the specifies the platform-specific view of the registry.
;                  |  This parameter can be one of the following values, These flags are ignored by 32-bit Windows
;                  |$KEY_WOW64_64KEY (256) - operate on the 64-bit registry view
;                  |$KEY_WOW64_32KEY (512) - operate on the 32-bit registry view
; Return values .: If the function succeeds, the return value is ERROR_SUCCESS. and set ERROR_SUCCESS error code
;                  If the function fails, the return value is nonzero, and set nonzero error code, and set Extended error code defined in WinError.h
;                    @Extended: -1 = unable to use the DLL file,
;                               -2 = unknown "return type",
;                               -3 = "function" not found in the DLL file,
;                               -4 = bad number of parameters,
;                               -5 = bad parameter.
;                               0+ = error code defined in WinError.h
; Author ........: DXRW4E
; Modified.......:
; Remarks .......: Calling _WinAPI_RegSetKeyValue is an expensive operation that significantly affects system-wide performance as
;                    it consumes disk bandwidth and blocks modifications to all keys by all processes in the registry hive that
;                    is being flushed until the flush operation completes. _WinAPI_RegSetKeyValue should only be called xplicitly
;                    ewhen an application must guarantee that registry changes are persisted to disk immediately after modification.
;                    All modifications made to keys are visible to other processes without the need to flush them to disk.
;                  Alternatively, the registry has a 'lazy flush' mechanism that flushes registry modifications to disk at regular
;                    intervals of time. In addition to this regular flush operation, registry changes are also flushed to disk at
;                    system shutdown. Allowing the 'lazy flush' to flush registry changes is the most efficient way to manage registry
;                    writes to the registry store on disk.
;                  The _WinAPI_RegSetKeyValue function returns only when all the data for the hive that contains the specified key
;                    has been written to the registry store on disk.
;                  The _WinAPI_RegSetKeyValue function writes out the data for other keys in the hive that have been modified since
;                    the last lazy flush or system start.
;                  After _WinAPI_RegSetKeyValue returns, use _WinAPI_RegCloseKey to close the handle to the registry key.
; Related .......:
; Link ..........:
; Example .......:
; Example .......: _WinAPI_RegSetKeyValue($hKey, Null, "Test", "This is Test", $REG_SZ)
;                  _WinAPI_RegSetKeyValue($HKEY_LOCAL_MACHINE, "SOFTWARE\KeyName", "Test", "This is Test", $REG_SZ)
; Note ..........:
; ===================================================================================================================================
Func _WinAPI_RegSetKeyValue($hKey, $sSubKey = "", $sValueName = "", $vData = "", $dwType = 1, $samDesired = 0)
    ;;If $_WIN32_WINNT5 Then Return SetError(_WinAPI_RegSetValueEx($hKey, $sSubKey, $sValueName, $vData, $dwType) + @Error, @Extended, @Error)
    Switch $dwType
        Case 1, 2  ;; $REG_SZ, $REG_EXPAND_SZ
            If Not IsBinary($vData) Then $vData = StringToBinary(StringRegExpReplace(StringRegExpReplace($vData, "\\", "\\\\"), "\x00*+$", "") & Chr(0), 2)
        Case 5  ;; $REG_DWORD_BIG_ENDIAN
            If Not IsBinary($vData) Then $vData = Binary("0x" & Hex($vData, 8))
        Case 6  ;; $REG_LINK
            $samDesired = BitOR($samDesired, 64)
            If Not _WinAPI_RegKeyExistEx($hKey, $sSubKey, $samDesired) And @Extended Then Return SetError(4, 2, 2)
            If Not IsBinary($vData) Then $vData = StringToBinary((StringRegExp($vData, "(?i)^\\Registry\\") ? $vData : _RegGetObjectNameKey($vData)), 2)
        Case 7  ;; $REG_MULTI_SZ
            If Not IsBinary($vData) Then $vData = StringToBinary(StringRegExpReplace(StringRegExpReplace(StringRegExpReplace($vData, "\n", Chr(0)), "\\", "\\\\"), "\x00*+$", "") & Chr(0) & Chr(0), 2)
        Case 0 To 11  ;; 0, 3, 4, 8, 9, 10, 11  ;; $REG_NONE, $REG_BINARY, $REG_DWORD, $REG_RESOURCE_LIST, $REG_FULL_RESOURCE_DESCRIPTOR, $REG_RESOURCE_REQUIREMENTS_LIST, $REG_QWORD
            ;;
        Case Else
            Return SetError(2, 87, 87)
    EndSwitch
    Local $cbData = ($dwType = 11 ? 8 : BinaryLen($vData)), $tData = DllStructCreate("BYTE[" & $cbData & "]")
    DllStructSetData($tData, 1, $vData)
    If Not $hKey Then $hKey = _RegGetPredefinedKeyEx($sSubKey, $samDesired)
    If $samDesired Then
        Local $hKeyEx = _WinAPI_RegCreateKey($hKey, $sSubKey, 2 + BitAND($samDesired, 768), ($dwType = 6 ? 2 : 0))
        If @Error And $dwType = 6 Then $hKeyEx = _WinAPI_RegOpenKey($hKey, $sSubKey, 2 + BitAND($samDesired, 768), 8)
        If @Error Then Return SetError(3, @Extended, @Extended)
        $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegSetValueExW", "ULONG_PTR", $hKeyEx, "WSTR", $sValueName, "DWORD", 0, "DWORD", $dwType, "STRUCT*", $tData, "DWORD", $cbData)
        SetError(@Error + DllCall($hAdvapi32Dll, "LONG", "RegCloseKey", "ULONG_PTR", $hKeyEx))
    Else
        $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegSetKeyValueW", "ULONG_PTR", $hKey, "WSTR", $sSubKey, "WSTR", $sValueName, "DWORD", $dwType, "STRUCT*", $tData, "DWORD", $cbData)
        If Not @Error And $arDllCall[0] = 5 And $REG_SPECIAL_ACCESS Then
            $hKey = _WinAPI_RegCreateKey($arDllCall[1], $sSubKey, 2) ;; $KEY_SET_VALUE = 0x0002
            If @Error Then Return SetError(2, @Extended, @Extended)
            $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegSetKeyValueW", "ULONG_PTR", $hKey, "WSTR", Null, "WSTR", $sValueName, "DWORD", $dwType, "STRUCT*", $tData, "DWORD", $cbData)
            SetError(@Error + DllCall($hAdvapi32Dll, "LONG", "RegCloseKey", "ULONG_PTR", $hKey))
        EndIf
    EndIf
    If @Error Then Return SetError(1, -@Error, 1)
    Return SetError($arDllCall[0], $arDllCall[0], $arDllCall[0])
EndFunc


; #FUNCTION# ========================================================================================================================
; Name...........: _WinAPI_RegQueryValue
; Description ...: Retrieves the type and data for the specified value name associated with an open registry key.
; Syntax.........: _WinAPI_RegQueryValue($hKey[, $sSubKey[, $sValueName])
; Parameters ....: $hKey       - A handle to an open registry key. The key must have been opened with the KEY_QUERY_VALUE access right.
;                                  For more information, see Registry Key Security and Access Rights.
;                                This handle is returned by the _WinAPI_RegCreateKey, _WinAPI_RegCreateKeyEx, _WinAPI_RegOpenKey, _WinAPI_RegOpenKeyEx,
;                                  It can also be one of the following predefined keys:
;                                        $HKEY_CLASSES_ROOT
;                                        $HKEY_CURRENT_CONFIG
;                                        $HKEY_CURRENT_USER
;                                        $HKEY_LOCAL_MACHINE
;                                        $HKEY_PERFORMANCE_DATA
;                                        $HKEY_PERFORMANCE_NLSTEXT
;                                        $HKEY_PERFORMANCE_TEXT
;                                        $HKEY_USERS
;                                This parameter can be NULL, use the NULL or 0 to set NULL this parameter, If $hKey is NULL,
;                                  $sSubKey must be contain Full String KeyName, for more see $sSubKey
;                  $sSubKey    - Optional, The name of the registry key to query value. Key names are not case sensitive.
;                                  This key must be a subkey of the key identified by the $hKey parameter.
;                                  if $hKey is Null this key must be a Full String KeyName, example
;                                    "HKLM\SOFTWARE\Example" or "HKEY_USERS" or "HKEY_CURRENT_USER\Software"
;                                    "\Registry\Machine\SOFTWARE\Example" or "\Registry\User" or "\Registry\User\CurrentUser"
;                                    "MACHINE\Software\Example" or "USERS" or "CURRENT_USER\Software"
;                                    "CLASSES_ROOT\Example" or in a remote registry such as \\ComputerName\CLASSES_ROOT\Example.
;                                  If this parameter is NULL or an empty string, the function returns the same handle that was passed in.
;                  $sValueName - Optional, The name of the registry value.
;                                  If $sValueName is NULL or an empty string, "", the function retrieves the type and data for the key's
;                                    unnamed or default value, if any.
;                                  If $sValueName specifies a value that is not in the registry, the function returns ERROR_FILE_NOT_FOUND.
;                                  Keys do not automatically have an unnamed or default value. Unnamed values can be of any type. For more information,
;                                    see Registry Element Size Limits http://msdn.microsoft.com/en-us/library/windows/desktop/ms724872(v=vs.85).aspx
; Return values .: If the function succeeds, the return value is String or INT or Binary, and set error code ERROR_SUCCESS
;                    and set Extended code dwValueType
;                    @Extended: $REG_NONE (0)
;                               $REG_SZ (1)
;                               $REG_EXPAND_SZ (2)
;                               $REG_BINARY (3)
;                               $REG_DWORD (4) - $REG_DWORD_LITTLE_ENDIAN (4)
;                               $REG_DWORD_BIG_ENDIAN (5)
;                               $REG_LINK (6)
;                               $REG_MULTI_SZ (7)
;                               $REG_RESOURCE_LIST (8)
;                               $REG_FULL_RESOURCE_DESCRIPTOR (9)
;                               $REG_RESOURCE_REQUIREMENTS_LIST (10)
;                               $REG_QWORD (11) - $REG_QWORD_LITTLE_ENDIAN (11)
;                  If the function fails, the return value is a None '', and set nonzero error code
;                    @Extended : -1 = unable to use the DLL file,
;                                -2 = unknown "return type",
;                                -3 = "function" not found in the DLL file,
;                                -4 = bad number of parameters,
;                                -5 = bad parameter.
;                                0+ = error code defined in WinError.h
; Author ........: DXRW4E
; Modified.......:
; Remarks .......: An application typically calls _WinAPI_RegEnumValue to determine the value names and then
;                    _WinAPI_RegQueryValueEx to retrieve the data for the names.
;                  If the data has the REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ type, the string may not have been stored
;                    with the proper terminating null characters. Therefore, even if the function returns ERROR_SUCCESS,
;                    the application should ensure that the string is properly terminated before using it; otherwise, it
;                    may overwrite a buffer. (Note that REG_MULTI_SZ strings should have two terminating null characters.)
;                    One way an application can ensure that the string is properly terminated is to use RegGetValue, which
;                    adds terminating null characters if needed.
;                  When calling the _WinAPI_RegQueryValueEx function with $hKey set to the HKEY_PERFORMANCE_DATA handle and
;                    a value string of a specified object, the returned data structure sometimes has unrequested objects.
;                    Do not be surprised; this is normal behavior. When calling the _WinAPI_RegQueryValueEx function, you
;                    should always expect to walk the returned data structure to look for the requested object.
;                  Note that operations that access certain registry keys are redirected. For more information,
;                    see Registry Virtualization and 32-bit and 64-bit Application Data in the Registry.
; Related .......:
; Link ..........:
; Example .......:
; Example .......: _WinAPI_RegQueryValue($hKey, "Test")
; Note ..........:
; ===================================================================================================================================
Func _WinAPI_RegQueryValue(Const ByRef $hKey, $sValueName = "")
    Local $tData = DllStructCreate("BYTE[4096]")
    $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegQueryValueExW", "ULONG_PTR", $hKey, "WSTR", $sValueName, "DWORD", 0, "DWORD*", 0, "STRUCT*", $tData, "DWORD*", 4096)
    If @Error Then Return SetError(1, -@Error, "")
    If $arDllCall[6] > 4096 Then
        $tData = DllStructCreate("BYTE[" & $arDllCall[6] & "]")
        $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegQueryValueExW", "ULONG_PTR", $hKey, "WSTR", $sValueName, "DWORD", 0, "DWORD*", 0, "STRUCT*", $tData, "DWORD*", $arDllCall[6])
    EndIf
    If $arDllCall[0] Then Return SetError(2, $arDllCall[0], "")
    Switch $arDllCall[4]
        Case 1, 2, 6  ;; $REG_SZ, $REG_EXPAND_SZ, $REG_LINK
            Return SetExtended($arDllCall[4], BinaryToString(BinaryMid(DllStructGetData($tData, 1), 1, $arDllCall[6]), 2))
        Case 7  ;; $REG_MULTI_SZ
            Return SetExtended($arDllCall[4], StringRegExpReplace(BinaryToString(BinaryMid(DllStructGetData($tData, 1), 1, $arDllCall[6]), 2), "\x00+", @LF))
        Case 4  ;; $REG_DWORD, $REG_DWORD_LITTLE_ENDIAN
            Return SetExtended($arDllCall[4], DllStructGetData(DllStructCreate("DWORD", DllStructGetPtr($tData, 1)), 1)) ;; Or Dec(StringRegExpReplace(BinaryMid(DllStructGetData($tData, 1), 1, 4), "^..(..)(..)(..)(..)","$4$3$2$1"), 1)
        Case 5  ;; $REG_DWORD_BIG_ENDIAN
            Return SetExtended($arDllCall[4], Dec(StringMid(BinaryMid(DllStructGetData($tData, 1), 1, $arDllCall[6]), 3, 8), 1)) ;; Or Number(StringLeft(DllStructGetData($tData, 1), 10), 3)
        Case 11  ;; $REG_QWORD, $REG_QWORD_LITTLE_ENDIAN
            Return SetExtended($arDllCall[4], DllStructGetData(DllStructCreate("UINT64", DllStructGetPtr($tData, 1)), 1)) ;; Or Dec(StringRegExpReplace(BinaryMid(DllStructGetData($tData, 1), 1, 8), "^..(..)(..)(..)(..)(..)(..)(..)(..)","0x$8$7$6$5$4$3$2$1"), 2)
        Case Else ;; 0 To 11 ;; 0, 3, 8, 9, 10 ;; $REG_NONE, $REG_BINARY, $REG_RESOURCE_LIST, $REG_FULL_RESOURCE_DESCRIPTOR, $REG_RESOURCE_REQUIREMENTS_LIST
            Return SetExtended($arDllCall[4], BinaryMid(DllStructGetData($tData, 1), 1, $arDllCall[6]))
    EndSwitch
EndFunc   ;==>_WinAPI_RegQueryValue


; #FUNCTION# ========================================================================================================================
; Name...........: _WinAPI_RegQueryValueEx
; Description ...: Retrieves the type and data for the specified value name associated with an open registry key.
; Syntax.........: _WinAPI_RegQueryValueEx($hKey[, $sSubKey[, $sValueName[, $samDesired]]])
; Parameters ....: $hKey       - A handle to an open registry key. The key must have been opened with the KEY_QUERY_VALUE access right.
;                                  For more information, see Registry Key Security and Access Rights.
;                                This handle is returned by the _WinAPI_RegCreateKey, _WinAPI_RegCreateKeyEx, _WinAPI_RegOpenKey, _WinAPI_RegOpenKeyEx,
;                                  It can also be one of the following predefined keys:
;                                        $HKEY_CLASSES_ROOT
;                                        $HKEY_CURRENT_CONFIG
;                                        $HKEY_CURRENT_USER
;                                        $HKEY_LOCAL_MACHINE
;                                        $HKEY_PERFORMANCE_DATA
;                                        $HKEY_PERFORMANCE_NLSTEXT
;                                        $HKEY_PERFORMANCE_TEXT
;                                        $HKEY_USERS
;                                This parameter can be NULL, use the NULL or 0 to set NULL this parameter, If $hKey is NULL,
;                                  $sSubKey must be contain Full String KeyName, for more see $sSubKey
;                  $sSubKey    - Optional, The name of the registry key to be opened. Key names are not case sensitive.
;                                  This key must be a subkey of the key identified by the $hKey parameter.
;                                  if $hKey is Null this key must be a Full String KeyName, example
;                                    "HKLM\SOFTWARE\Example" or "HKEY_USERS" or "HKEY_CURRENT_USER\Software"
;                                    "\Registry\Machine\SOFTWARE\Example" or "\Registry\User" or "\Registry\User\CurrentUser"
;                                    "MACHINE\Software\Example" or "USERS" or "CURRENT_USER\Software"
;                                    "CLASSES_ROOT\Example" or in a remote registry such as \\ComputerName\CLASSES_ROOT\Example.
;                                  If this parameter is NULL or an empty string, the function returns the same handle that was passed in.
;                  $sValueName - Optional, The name of the registry value.
;                                  If $sValueName is NULL or an empty string, "", the function retrieves the type and data for the key's
;                                    unnamed or default value, if any.
;                                  If $sValueName specifies a value that is not in the registry, the function returns ERROR_FILE_NOT_FOUND.
;                                  Keys do not automatically have an unnamed or default value. Unnamed values can be of any type. For more information,
;                                    see Registry Element Size Limits http://msdn.microsoft.com/en-us/library/windows/desktop/ms724872(v=vs.85).aspx
;                  $samDesired - Optional, An access mask the specifies the platform-specific view of the registry.
;                  |               this flags will be ignored if the $sSubKey is Null
;                  |  This parameter can be one of the following values, These flags are ignored by 32-bit Windows
;                  |$KEY_WOW64_64KEY (256) - operate on the 64-bit registry view
;                  |$KEY_WOW64_32KEY (512) - operate on the 32-bit registry view
; Return values .: If the function succeeds, the return value is String or INT or Binary, and set error code ERROR_SUCCESS
;                    and set Extended code dwValueType
;                    @Extended: $REG_NONE (0)
;                               $REG_SZ (1)
;                               $REG_EXPAND_SZ (2)
;                               $REG_BINARY (3)
;                               $REG_DWORD (4) - $REG_DWORD_LITTLE_ENDIAN (4)
;                               $REG_DWORD_BIG_ENDIAN (5)
;                               $REG_LINK (6)
;                               $REG_MULTI_SZ (7)
;                               $REG_RESOURCE_LIST (8)
;                               $REG_FULL_RESOURCE_DESCRIPTOR (9)
;                               $REG_RESOURCE_REQUIREMENTS_LIST (10)
;                               $REG_QWORD (11) - $REG_QWORD_LITTLE_ENDIAN (11)
;                  If the function fails, the return value is a None '', and set nonzero error code
;                    @Extended : -1 = unable to use the DLL file,
;                                -2 = unknown "return type",
;                                -3 = "function" not found in the DLL file,
;                                -4 = bad number of parameters,
;                                -5 = bad parameter.
;                                0+ = error code defined in WinError.h
; Author ........: DXRW4E
; Modified.......:
; Remarks .......: An application typically calls _WinAPI_RegEnumValue to determine the value names and then
;                    _WinAPI_RegQueryValueEx to retrieve the data for the names.
;                  If the data has the REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ type, the string may not have been stored
;                    with the proper terminating null characters. Therefore, even if the function returns ERROR_SUCCESS,
;                    the application should ensure that the string is properly terminated before using it; otherwise, it
;                    may overwrite a buffer. (Note that REG_MULTI_SZ strings should have two terminating null characters.)
;                    One way an application can ensure that the string is properly terminated is to use RegGetValue, which
;                    adds terminating null characters if needed.
;                  When calling the _WinAPI_RegQueryValueEx function with $hKey set to the HKEY_PERFORMANCE_DATA handle and
;                    a value string of a specified object, the returned data structure sometimes has unrequested objects.
;                    Do not be surprised; this is normal behavior. When calling the _WinAPI_RegQueryValueEx function, you
;                    should always expect to walk the returned data structure to look for the requested object.
;                  Note that operations that access certain registry keys are redirected. For more information,
;                    see Registry Virtualization and 32-bit and 64-bit Application Data in the Registry.
; Related .......:
; Link ..........:
; Example .......:
; Example .......: _WinAPI_RegQueryValueEx($hKey, Null, "Test")
;                  _WinAPI_RegQueryValueEx($HKEY_LOCAL_MACHINE, "SOFTWARE\KeyName", "Test")
; Note ..........:
; ===================================================================================================================================
Func _WinAPI_RegQueryValueEx($hKey, $sSubKey = "", $sValueName = "", $samDesired = 0)
    Local $tData = DllStructCreate("BYTE[4096]")
    If Not $hKey Then $hKey = _RegGetPredefinedKeyEx($sSubKey, $samDesired)
    If $sSubKey Then $hKey = _WinAPI_RegOpenKey($hKey, $sSubKey, 1 + BitAND($samDesired, 768), BitAND($samDesired, 8)) ;; $KEY_QUERY_VALUE = 0x0001
    $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegQueryValueExW", "ULONG_PTR", $hKey, "WSTR", $sValueName, "DWORD", 0, "DWORD*", 0, "STRUCT*", $tData, "DWORD*", 4096)
    If @Error Then Return SetError(1, -@Error + ($sSubKey ? DllCall($hAdvapi32Dll, "LONG", "RegCloseKey", "ULONG_PTR", $hKey) : 0), "")
    If $arDllCall[6] > 4096 Then
        $tData = DllStructCreate("BYTE[" & $arDllCall[6] & "]")
        $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegQueryValueExW", "ULONG_PTR", $hKey, "WSTR", $sValueName, "DWORD", 0, "DWORD*", 0, "STRUCT*", $tData, "DWORD*", $arDllCall[6])
    EndIf
    If $sSubKey Then DllCall($hAdvapi32Dll, "LONG", "RegCloseKey", "ULONG_PTR", $hKey)
    If $arDllCall[0] Then Return SetError(2, $arDllCall[0], "")
    Switch $arDllCall[4]
        Case 1, 2, 6  ;; $REG_SZ, $REG_EXPAND_SZ, $REG_LINK
            Return SetExtended($arDllCall[4], BinaryToString(BinaryMid(DllStructGetData($tData, 1), 1, $arDllCall[6]), 2))
        Case 7  ;; $REG_MULTI_SZ
            Return SetExtended($arDllCall[4], StringRegExpReplace(BinaryToString(BinaryMid(DllStructGetData($tData, 1), 1, $arDllCall[6]), 2), "\x00+", @LF))
        Case 4  ;; $REG_DWORD, $REG_DWORD_LITTLE_ENDIAN
            Return SetExtended($arDllCall[4], DllStructGetData(DllStructCreate("DWORD", DllStructGetPtr($tData, 1)), 1)) ;; Or Dec(StringRegExpReplace(BinaryMid(DllStructGetData($tData, 1), 1, 4), "^..(..)(..)(..)(..)","$4$3$2$1"), 1)
        Case 5  ;; $REG_DWORD_BIG_ENDIAN
            Return SetExtended($arDllCall[4], Dec(StringMid(BinaryMid(DllStructGetData($tData, 1), 1, $arDllCall[6]), 3, 8), 1)) ;; Or Number(StringLeft(DllStructGetData($tData, 1), 10), 3)
        Case 11  ;; $REG_QWORD, $REG_QWORD_LITTLE_ENDIAN
            Return SetExtended($arDllCall[4], DllStructGetData(DllStructCreate("UINT64", DllStructGetPtr($tData, 1)), 1))  ;; Or Dec(StringRegExpReplace(BinaryMid(DllStructGetData($tData, 1), 1, 8), "^..(..)(..)(..)(..)(..)(..)(..)(..)","0x$8$7$6$5$4$3$2$1"), 2)
        Case Else ;; 0 To 11 ;; 0, 3, 8, 9, 10 ;; $REG_NONE, $REG_BINARY, $REG_RESOURCE_LIST, $REG_FULL_RESOURCE_DESCRIPTOR, $REG_RESOURCE_REQUIREMENTS_LIST
            Return SetExtended($arDllCall[4], BinaryMid(DllStructGetData($tData, 1), 1, $arDllCall[6]))
    EndSwitch
EndFunc   ;==>_WinAPI_RegQueryValueEx


; #FUNCTION# ========================================================================================================================
; Name...........: _WinAPI_RegSaveKeyEx
; Description ...: Saves the specified key and all of its subkeys and values to a registry file, in the specified format.
; Syntax.........: _WinAPI_RegSaveKeyEx($hKey, $lpFile[, $dwFlags])
; Parameters ....: $hKey   -  A handle to an open registry key. This function does not support the HKEY_CLASSES_ROOT predefined key.
;                  $lpFile - The name of the file in which the specified key and subkeys are to be saved. If the file already exists, the function fails.
;                             The new file has the archive attribute.
;                             If the string does not include a path, the file is created in the current directory of the calling process
;                              for a local key, or in the %systemroot%\system32 directory for a remote key.
;                  $dwFlags  - Optional The format of the saved key or hive. This parameter can be one of the following values.
;                  |$dwFlags = 1  The key or hive is saved in standard format. The standard format is the only format supported by Windows 2000.
;                  |$dwFlags = 2 (Default) The key or hive is saved in the latest format. The latest format is supported starting with Windows XP.
;                  |              After the key or hive is saved in this format, it cannot be loaded on an earlier system.
;                  |$dwFlags = 4 The hive is saved with no compression, for faster save operations. The hKey parameter must specify the root of
;                  |              a hive under HKEY_LOCAL_MACHINE or HKEY_USERS. For example, HKLM\SOFTWARE is the root of a hive.
; Return values .: If the function succeeds set ERROR_SUCCESS error code
;                  If the function fails set nonzero error code, and set Extended error code defined in WinError.h
; Author ........: DXRW4E
; Modified.......:
; Remarks .......: Unlike RegSaveKey, this function does not support the HKEY_CLASSES_ROOT predefined key.
;                  If hKey represents a key on a remote computer, the path described by lpFile is relative to the remote computer.
;                  The RegSaveKeyEx function saves only nonvolatile keys. It does not save volatile keys. A key is
;                    made volatile or nonvolatile at its creation; see RegCreateKeyEx.
;                  You can use the file created by RegSaveKeyEx in subsequent calls to the RegLoadKey, RegReplaceKey,
;                    or RegRestoreKey function. If RegSaveKeyEx fails partway through its operation, the file will be
;                    corrupt and subsequent calls to RegLoadKey, RegReplaceKey, or RegRestoreKey for the file will fail.
;                  Using RegSaveKeyEx together with RegRestoreKey to copy subtrees in the registry is not recommended.
;                    This method does not trigger notifications and can invalidate handles used by other applications.
;                    Instead, use the SHCopyKey function or the RegCopyTree function.
;                  The calling process must have the SE_BACKUP_NAME privilege enabled. For more information, see Running with Special Privileges.
; Related .......:
; Link ..........:
; Example .......:
; Example .......:  _WinAPI_RegSaveKeyEx($HKEY_LOCAL_MACHINE, "SOFTWARE\KeyName")
; Note ..........:
; ===================================================================================================================================
Func _WinAPI_RegSaveKeyEx(Const ByRef $hKey, $lpFile, $dwFlags = 2)
    FileDelete($lpFile)
    $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegSaveKeyExW", "ULONG_PTR", $hKey, "WSTR", $lpFile, "PTR", Null, "DWORD", $dwFlags)
    If @Error Then Return SetError(1, -@Error, 0)
    Return SetError($arDllCall[0], 0, 0)
EndFunc   ;==>_WinAPI_RegSaveKeyEx


; #FUNCTION# ========================================================================================================================
; Name...........: _WinAPI_RegRestoreKey
; Description ...: Reads the registry information in a specified file and copies it over the specified key. This registry
;                    information may be in the form of a key and multiple levels of subkeys.
;                  Applications that back up or restore system state including system files and registry hives
;                    should use the Volume Shadow Copy Service instead of the registry functions.
; Syntax.........: _WinAPI_RegRestoreKey($hKey, $lpFile[, $dwFlags])
; Parameters ....: $hKey    - A handle to an open registry key. The key must have been opened with the KEY_QUERY_VALUE access right.
;                               For more information, see Registry Key Security and Access Rights.
;                               This handle is returned by the _WinAPI_RegCreateKeyEx or _WinAPI_RegOpenKeyEx or _WinAPI_RegCreateKey or _WinAPI_RegOpenKey
;                                 function, or it can be one of the following predefined keys:
;                                     $HKEY_CLASSES_ROOT
;                                     $HKEY_CURRENT_CONFIG
;                                     $HKEY_CURRENT_USER
;                                     $HKEY_LOCAL_MACHINE
;                                     $HKEY_PERFORMANCE_DATA
;                                     $HKEY_USERS
;                               Any information contained in this key and its descendent keys is overwritten by the information
;                                 in the file pointed to by the $lpFile parameter.
;                  $lpFile  - The name of the file with the registry information. This file is typically created by using the _WinAPI_RegSaveKeyEx function.
;                  $dwFlags - Optional, The flags that indicate how the key or keys are to be restored. This parameter can be one of the following values.
;                  |$dwFlags = 1 If specified, a new, volatile (memory only) set of registry information, or hive, is created. If REG_WHOLE_HIVE_VOLATILE
;                                  is specified, the key identified by the hKey parameter must be either the HKEY_USERS or HKEY_LOCAL_MACHINE value.
;                  |$dwFlags = 8 If specified, the restore operation is executed even if open handles exist at or beneath the location
;                  |               in the registry hierarchy to which the hKey parameter points.
; Return values .: If the function succeeds set ERROR_SUCCESS error code
;                  If the function fails set nonzero error code, and set Extended error code defined in WinError.h
; Author ........: DXRW4E
; Modified.......:
; Remarks .......: There are two different registry hive file formats. Registry hives created on current operating systems
;                    typically cannot be loaded by earlier ones.
;                  If any subkeys of the hKey parameter are open, RegRestoreKey fails.
;                  The calling process must have the SE_RESTORE_NAME and SE_BACKUP_NAME privileges on the computer in which
;                    the registry resides. For more information, see Running with Special Privileges.
;                  This function replaces the keys and values below the specified key with the keys and values that are subsidiary
;                    to the top-level key in the file, no matter what the name of the top-level key in the file might be. For example,
;                    hKey might identify a key A with subkeys B and C, while the lpFile parameter specifies a file containing key X
;                    with subkeys Y and Z. After a call to RegRestoreKey, the registry would contain key A with subkeys Y and Z.
;                    The value entries of A would be replaced by the value entries of X.
;                  The new information in the file specified by lpFile overwrites the contents of the key specified by the hKey parameter,
;                    except for the key name.
;                  If hKey represents a key in a remote computer, the path described by lpFile is relative to the remote computer.
; Related .......:
; Link ..........:
; Example .......:
; Example .......:  _WinAPI_RegRestoreKey($HKEY_LOCAL_MACHINE, "SOFTWARE\KeyName")
; Note ..........:
; ===================================================================================================================================
Func _WinAPI_RegRestoreKey(Const ByRef $hKey, $lpFile, $dwFlags = 8)
    $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegRestoreKeyW", "ULONG_PTR", $hKey, "WSTR", $lpFile, "DWORD", $dwFlags)
    If @Error Then Return SetError(1, -@Error, 0)
    Return SetError($arDllCall[0], 0, 0)
EndFunc   ;==>_WinAPI_RegRestoreKey


; #FUNCTION# ====================================================================================================================
; Name...........: _RegGetPredefinedKeyEx
; Description ...: Get HKEY Handle\KeyName\ObjectName
; Syntax.........: _RegGetPredefinedKeyEx(ByRef $szKey, ByRef $iType[, $iFlags])
; Parameters ....: $szKey  - HKEY Name
;                  $iType  - A mask that specifies the access rights for the key
;                  $iFlags - Optional
;                  |0 - (Default) Return $iPredefinedKey
;                  |1 - Return HKEY String for Inf File (AddReg\DelReg Directive)
;                  |2 - Return SE_REGISTRY_KEY String for SDDL (StringSecurityDescriptorEx)
;                  |3 - Return KEY ObjectName String (Registry Key Object Routines)
; Return values .: HKEY Handle\KeyName\ObjectName
; Author ........: DXRW4E
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......:
; ===============================================================================================================================
Func _RegGetPredefinedKeyEx(ByRef $szKey, ByRef $iType, $iFlags = 0)
    $iFlags = BitAND($iFlags, 3)
    Local $ahKey = StringRegExp($szKey, "^[\h\\]*+([^\W\d]*+)((?:32|64)?+(?!\w))\\*+(.*)", 1)
    If @Error Then Return SetError(1, 0, $HKEY_PREDEFINED[10][$iFlags])
    Switch $ahKey[0]
        Case "HKCR","HKEY_CLASSES_ROOT", "CLASSES_ROOT";, "MACHINE\SOFTWARE\Classes"
            $ahKey[0] = 0
        Case "HKCU", "HKEY_CURRENT_USER", "CURRENT_USER"
            $ahKey[0] = 1
        Case "HKLM", "HKEY_LOCAL_MACHINE", "MACHINE"
            $ahKey[0] = 2
        Case "HKU", "HKEY_USERS", "USERS"
            $ahKey[0] = 3
        Case "HKCC", "HKEY_CURRENT_CONFIG";, "MACHINE\SYSTEM\CurrentControlSet\Hardware Profiles\Current"
            $ahKey[0] = 4
            If $iFlags = 1 Then $ahKey[2] = "SYSTEM\CurrentControlSet\Hardware Profiles\Current" & StringRegExpReplace($ahKey[2], "^.", "\\$0")
        Case "HKLS", "HKEY_CURRENT_USER_LOCAL_SETTINGS";, "CURRENT_USER\Software\Classes\Local Settings"
            $ahKey[0] = 5
            If $iFlags = 1 Then $ahKey[2] = "Software\Classes\Local Settings" & StringRegExpReplace($ahKey[2], "^.", "\\$0")
        Case "HKPD", "HKEY_PERFORMANCE_DATA"
            $ahKey[0] = 6
        Case "HKDD", "HKEY_DYN_DATA"
            $ahKey[0] = 7
        Case "HKPT", "HKEY_PERFORMANCE_TEXT"
            $ahKey[0] = 8
        Case "HKPN", "HKEY_PERFORMANCE_NLSTEXT"
            $ahKey[0] = 9
        Case "Registry"
            $ahKey = StringRegExp($ahKey[2], "(?i)^(?|(Machine)((?:\\+SYSTEM\\+CurrentControlSet\\+Hardware Profiles\\+Current(?!\w)|\\+SOFTWARE\\+Classes(?!\w))?+)|User((?:\\+CurrentUser(?!\w)|\\+S-1-5-\d+-\d+-\d+-\d+-\d+)?+)((?:\\+Software\\+Classes\\+Local Settings(?!\w)|\\+_CLASSES\\+Local Settings(?!\w)|\\+_CLASSES(?!\w))?+))\\*(.*)", 1)
            If @Error Then Return SetError(1, 0, $HKEY_PREDEFINED[10][$iFlags])
            If $ahKey[0] = "Machine" Then
                $ahKey[0] = Not $ahKey[1] ? 2 : (StringRegExp($ahKey[1], "(?i)^\\+SO") ? 0 : 4)
                If $ahKey[0] = 4 And $iFlags = 1  Then $ahKey[2] = "SYSTEM\CurrentControlSet\Hardware Profiles\Current" & StringRegExpReplace($ahKey[2], "^.", "\\$0")
            Else
                $ahKey[0] = Not $ahKey[0] ? 3 : (StringRight($ahKey[1], 2) = "gs" ? 5 : 1)
                If ($ahKey[0] = 5 And $iFlags = 1) Or ($ahKey[1] And $ahKey[0] = 3) Then $ahKey[2] = "Software\Classes" & ($ahKey[0] = 5 ? "\Local Settings" : "") & StringRegExpReplace($ahKey[2], "^.", "\\$0")
            EndIf
        Case Else
            If $iFlags = 2 Then $iType = ($iType = 12) ? $SE_REGISTRY_WOW64_32KEY : $SE_REGISTRY_KEY
            If $iFlags = 2 Or Not StringRegExp($szKey, "^\h*\\+[^\\]+\\+") Then Return SetError(1, 0, $HKEY_PREDEFINED[10][$iFlags])
            $ahKey[0] = StringRegExpReplace($szKey, "^\h*\\+[^\\]+\\+", "")
            $ahKey[1] = _RegGetPredefinedKeyEx($ahKey[0], $iType, $iFlags)
            If Not @Error Then $szKey = $ahKey[0]
            Return SetError(@Error, 0, $ahKey[1])
    EndSwitch
    If $iFlags = 2 Then
        $iType = ($ahKey[1] == "32") ? $SE_REGISTRY_WOW64_32KEY : $SE_REGISTRY_KEY
        $szKey = $HKEY_PREDEFINED[$ahKey[0]][$iFlags] & StringRegExpReplace($ahKey[2], "^.", "\\$0")
        Return $szKey
    ElseIf $iFlags = 3 Then
        If $ahKey[0] > 5 Then Return SetError(1, 0, "")
        Return $HKEY_PREDEFINED[$ahKey[0]][$iFlags] & StringRegExpReplace($ahKey[2], "^.", "\\$0")
    Else
        ;;If $ahKey[1] Then $iType = BitOR($iType, ($ahKey[1] == "32" ? $KEY_WOW64_32KEY : $KEY_WOW64_64KEY))
        If $ahKey[1] Then $iType = BitXOR(BitOR($iType, $KEY_WOW64_RES), ($ahKey[1] == "32" ? $KEY_WOW64_64KEY : $KEY_WOW64_32KEY))
        $szKey = $ahKey[2] ? $ahKey[2] : Null
        Return $HKEY_PREDEFINED[$ahKey[0]][$iFlags]
    EndIf
EndFunc


; #FUNCTION# ========================================================================================================================
; Name...........: _WinAPI_RegCloseKey
; Description ...: Closes a handle to the specified registry key.
; Syntax.........: _WinAPI_RegCloseKey($hKey)
; Parameters ....: $hKey - A handle to the open key to be closed. The handle must have been opened by the
;                            _WinAPI_RegCreateKey, _WinAPI_RegCreateKeyEx, _WinAPI_RegOpenKey, _WinAPI_RegOpenKeyEx function.
; Return values .: If the function succeeds, the return value is ERROR_SUCCESS and set ERROR_SUCCESS error code
;                  If the function fails, the return value is a 0, and set nonzero error code, and set Extended error code defined in WinError.h
;                    @Extended: -1 = unable to use the DLL file,
;                               -2 = unknown "return type",
;                               -3 = "function" not found in the DLL file,
;                               -4 = bad number of parameters,
;                               -5 = bad parameter.
;                               0+ = error code defined in WinError.h
; Author ........: DXRW4E
; Modified.......:
; Remarks .......: The handle for a specified key should not be used after it has been closed, because it will no longer be valid.
;                    Key handles should not be left open any longer than necessary.
;                  The _WinAPI_RegCloseKey function does not necessarily write information to the registry before returning; it can
;                    take as much as several seconds for the cache to be flushed to the hard disk. If an application must explicitly
;                    write registry information to the hard disk, it can use the _WinAPI_RegFlushKey function. _WinAPI_RegFlushKey,
;                    however, uses many system resources and should be called only when necessary.
; Related .......:
; Link ..........:
; Example .......:
; Example .......: _WinAPI_RegCloseKey($hKey)
; Note ..........:
; ===================================================================================================================================
Func _WinAPI_RegCloseKey(Const ByRef $hKey)
    $arDllCall = DllCall($hAdvapi32Dll, "LONG", "RegCloseKey", "ULONG_PTR", $hKey)
    If @Error Then Return SetError(1, -@Error, 0)
    Return SetError($arDllCall[0], $arDllCall[0], 0)
EndFunc

Func _RegGetObjectNameKey($sObjectName)
    Local $hKey = $sObjectName, $iDelete, $iError, $samDesired = 8 ;; $KEY_ENUMERATE_SUB_KEYS = 0x0008 Or $KEY_QUERY_VALUE = 0x0001
    If IsString($sObjectName) Then
        $hKey = _RegGetPredefinedKeyEx($sObjectName, $samDesired)
        If @Error Then SetError(1, 1, "")
        $hKey = _WinAPI_RegOpenKey($hKey, $sObjectName, $samDesired)
        If @Error Then
            $hKey = _WinAPI_RegCreateKey($hKey, $sObjectName, $samDesired)
            If @Error Then Return SetError(@Error, @Extended, "")
            $iDelete = @Extended = 1 ? 1 : 0
        EndIf
    EndIf
    $sObjectName = _NTAPI_GetRegKeyNameByHandle($hKey)
    $iError = @Error
    If $iDelete Then DllCall($hAdvapi32Dll, "LONG", "RegDeleteKeyExW", "ULONG_PTR", $hKey, "WSTR", Null, "DWORD", $samDesired, "DWORD", 0)
    DllCall($hAdvapi32Dll, "LONG", "RegCloseKey", "ULONG_PTR", $hKey)
    Return SetError($iError, 0, $sObjectName)
EndFunc


Func _NTAPI_GetRegKeyNameByHandle(Const ByRef $KeyHandle)
    Local $tKEY_INFORMATION_CLASS = DllStructCreate("ULONG;WCHAR[4096]")
    $arDllCall = DllCall("Ntdll.dll", "LONG", "ZwQueryKey", "ULONG_PTR", $KeyHandle, "INT", 3, "STRUCT*", $tKEY_INFORMATION_CLASS, "ULONG", DllStructGetSize($tKEY_INFORMATION_CLASS), "ULONG*", 0)
    If @Error Then Return SetError(@Error, 1, 0)
    If $arDllCall[5] > $arDllCall[4] Then ;;Or $arDllCall[0] = $STATUS_BUFFER_OVERFLOW Or $arDllCall[0] = $STATUS_BUFFER_TOO_SMALL
        $tKEY_INFORMATION_CLASS = DllStructCreate("ULONG;WCHAR[" & $arDllCall[5] & "]")
        $arDllCall = DllCall("Ntdll.dll", "LONG", "ZwQueryKey", "ULONG_PTR", $KeyHandle, "INT", 3, "STRUCT*", $tKEY_INFORMATION_CLASS, "ULONG", DllStructGetSize($tKEY_INFORMATION_CLASS), "ULONG*", 0)
    EndIf
    Return SetError($arDllCall[0], ($arDllCall[5] / 2) - 2, DllStructGetData($tKEY_INFORMATION_CLASS, 2))
EndFunc


 
#include <RegistryEx.au3>
Local $sData, $hKey, $fTimerDiff, $aData
;$fTimerDiff = TimerInit()
$aData = _WinAPI_RegEnumKeyEx($HKEY_CURRENT_USER, "Software", 1)
If @Error Then
    MsgBox(0,@error, @extended)
Else
    ;;_ArrayDisplay($aData)
    DirCreate(@DesktopDir & "\Test")
    For $i = 1 To $aData[0]
        $hKey = _WinAPI_RegOpenKey(0, "HKEY_CURRENT_USER\SOFTWARE\" & $aData[$i], $KEY_ALL_ACCESS)
        If @Error Then
            MsgBox(0,@error, @extended)
        Else
            _WinAPI_RegSaveKeyEx($hKey, @DesktopDir & "\Test\" & $aData[$i] & ".hive")
            If @Error Then
                MsgBox(0,@error, @extended)
            EndIf
            _WinAPI_RegCloseKey($hKey)
        EndIf
    Next
EndIf
;$fTimerDiff = TimerDiff($fTimerDiff)
ConsoleWrite($fTimerDiff & @LF)

$hKey = _WinAPI_RegCreateKey(0, "HKEY_LOCAL_MACHINE\SOFTWARE\Test", BitOr($KEY_ALL_ACCESS, $KEY_WOW64_64KEY))
If @Error Then
    MsgBox(0, @error, @extended)
Else
    _WinAPI_RegRestoreKey($hKey, @DesktopDir & "\test.hive")
    If @Error Then
        MsgBox(0, @error, @extended)
    EndIf
    _WinAPI_RegCloseKey($hKey)
EndIf

Exit
also fix the bugs of the log regkeyname in AutoIt Native Registry Function

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINESOFTWARE010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111]

"Test"="aaaaaaabbbbccc"

 

#include <RegistryEx.au3>
Local $sKeyPath = "HKEY_LOCAL_MACHINE\SOFTWARE\01\02\03\04\05\06\07\08\09\10\11\12\13\14\15\16\17\18\19\20"
$sKeyPath &= "\21\22\23\24\25\26\27\28\29\30\31\32\33\34\35\36\37\38\39\40\41\42\43\44\45\46\47\48\49\50\51\52\53\54\55"
$sKeyPath &= "\56\57\58\59\60\61\62\63\64\65\66\67\68\69\70\71\72\73\74\75\76\77\78\79\80\81\82\83\84\85\86\87\88\89\90"
$sKeyPath &= "\91\92\93\94\95\96\97\98\99\100\101\102\103\104\105\106\107\108\109\110\111"

Local $sVar = RegRead($sKeyPath, "Test")
MsgBox(0, 0, $sVar)

$hKey = _WinAPI_RegOpenKey(0, $sKeyPath, $KEY_ALL_ACCESS)
If @Error Then
    MsgBox(0,@error, @extended)
Else
    $sVar = _WinAPI_RegQueryValue($hKey, "Test")
    ;; _WinAPI_RegQueryValueEx(0, $sKeyPath, "Test")
    MsgBox(0, 0, $sVar)
    _WinAPI_RegCloseKey($hKey)
EndIf 
Ciao

RegistryEx.au3

Edited by DXRW4E

apps-odrive.pngdrive_app_badge.png box-logo.png new_logo.png MEGA_Logo.png

Share this post


Link to post
Share on other sites



OK you got my attention and I am confused.

 

These registry function I made them years ago, but being very busy i left all in the middle, however not need to use the RegCreateKey but just the RegOpenKey ;), http://support.microsoft.com/kb/128731 that should be in autoit

The page is ambiguous and refers to 

HOWTO: How to Back Up the Windows NT Registry

so Yes when you refer to

not need to use the RegCreateKey but just the RegOpenKey

 

if making a back up why would you be using RegCreateKey?

Any way please please would you take this and explain it much more thoroughly? I do not see the use of a windows 95 feature in a utility that we use in 2014, Expressly one of the very few items (the registry) that can demolish a box in 20 words or less. May I recommend ERUNT.

Not to smart and just attempting to learn the why and how things work and this has me scratching my head wondering.

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Because to do that needed to open the key with special permissions, at that time only the RegCreateKey has the flag option to open the key with the required permissions, instead now RegOpenKeyEx also uses the flag option, see the http://msdn.microsoft.com/en-us/library/windows/desktop/ms724897%28v=vs.85%29.aspx ulOptions flag

Ciao.

Edited by DXRW4E

apps-odrive.pngdrive_app_badge.png box-logo.png new_logo.png MEGA_Logo.png

Share this post


Link to post
Share on other sites

This script mentioned many times for the extended error it uses WinError.h.

I can't find where WinError.h is defined or an error table.

I'm trying to figure out what this means

@Error = 1 with @Extended = 6

Thanks,

Docfxit

Share this post


Link to post
Share on other sites

I found a way to easily get the explanation to the @Extended messages with an example from here:

https://www.autoitscript.com/autoit3/docs/libfunctions/_WinAPI_RegEnumKey.htm

#include <APIRegConstants.au3>
#include <Array.au3>
#include <MsgBoxConstants.au3>
#include <WinAPIDiag.au3>
#include <WinAPIReg.au3
If @error Then
    MsgBox(BitOR($MB_ICONERROR, $MB_SYSTEMMODAL), @extended, _WinAPI_GetErrorMessage(@extended))
    Exit
EndIf

Unfortunately there are a lot of duplicated constants in  RegistryEx.au3 when I tried to implement this code.

I have commented out the duplicates with three semicolons ;;;  in this version of RegistryEx.au3

 RegistryExModified2.7z

That part was pretty easy.  Unfortunately other errors popped up that prevented me from using the above code:

RegistryExModified2.au3"(548,110) : error: _WinAPI_RegOpenKey() called with wrong number of args.

I don't know how to resolve this.

It would be really great if you made RegistryEx.au3 compatible so it would fit in with other AutoIt functions.

Thank you very much for making/shareing RegistryEx.au3

Docfxit

RegistryExModified2.7z

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0