1
1
Fork 0
mirror of https://github.com/QB64Official/qb64.git synced 2024-07-16 20:05:14 +00:00
qb64/internal/help/Windows-Registry-Access.md

297 lines
11 KiB
Markdown

The following procedure demonstrates how Registry information can be altered by disabling and re-enabling the Autorun/Autoplay for the current user. It then reads the Registry to list some of the programs that auto start for all users.
<sub>Code courtesy of Michael Calkins</sub>
**WARNING! Use care when editing or altering Registry settings! YOU will be responsible for any damages incurred!**
```vb
' winreg.h
CONST HKEY_CLASSES_ROOT = &H80000000~&
CONST HKEY_CURRENT_USER = &H80000001~&
CONST HKEY_LOCAL_MACHINE = &H80000002~&
CONST HKEY_USERS = &H80000003~&
CONST HKEY_PERFORMANCE_DATA = &H80000004~&
CONST HKEY_CURRENT_CONFIG = &H80000005~&
CONST HKEY_DYN_DATA = &H80000006~&
CONST REG_OPTION_VOLATILE = 1
CONST REG_OPTION_NON_VOLATILE = 0
CONST REG_CREATED_NEW_KEY = 1
CONST REG_OPENED_EXISTING_KEY = 2
' **http://msdn.microsoft.com/en-us/library/ms724884(v=VS.85).aspx**
CONST REG_NONE = 0
CONST REG_SZ = 1
CONST REG_EXPAND_SZ = 2
CONST REG_BINARY = 3
CONST REG_DWORD_LITTLE_ENDIAN = 4 ' value is defined REG_DWORD in Windows header files
CONST REG_DWORD = 4 ' 32-bit number
CONST REG_DWORD_BIG_ENDIAN = 5 ' some UNIX systems support big-endian architectures
CONST REG_LINK = 6
CONST REG_MULTI_SZ = 7
CONST REG_RESOURCE_LIST = 8
CONST REG_FULL_RESOURCE_DESCRIPTOR = 9
CONST REG_RESOURCE_REQUIREMENTS_LIST = 10
CONST REG_QWORD_LITTLE_ENDIAN = 11 ' 64-bit number in little-endian format
CONST REG_QWORD = 11 ' 64-bit number
CONST REG_NOTIFY_CHANGE_NAME = 1
CONST REG_NOTIFY_CHANGE_ATTRIBUTES = 2
CONST REG_NOTIFY_CHANGE_LAST_SET = 4
CONST REG_NOTIFY_CHANGE_SECURITY = 8
' **http://msdn.microsoft.com/en-us/library/ms724878(v=VS.85).aspx**
CONST KEY_ALL_ACCESS = &HF003F&
CONST KEY_CREATE_LINK = &H0020&
CONST KEY_CREATE_SUB_KEY = &H0004&
CONST KEY_ENUMERATE_SUB_KEYS = &H0008&
CONST KEY_EXECUTE = &H20019&
CONST KEY_NOTIFY = &H0010&
CONST KEY_QUERY_VALUE = &H0001&
CONST KEY_READ = &H20019&
CONST KEY_SET_VALUE = &H0002&
CONST KEY_WOW64_32KEY = &H0200&
CONST KEY_WOW64_64KEY = &H0100&
CONST KEY_WRITE = &H20006&
' winerror.h
' **http://msdn.microsoft.com/en-us/library/ms681382(v=VS.85).aspx**
CONST ERROR_SUCCESS = 0
CONST ERROR_FILE_NOT_FOUND = &H2&
CONST ERROR_INVALID_HANDLE = &H6&
CONST ERROR_MORE_DATA = &HEA&
CONST ERROR_NO_MORE_ITEMS = &H103&
'---------------------------------------------------------------------------------------------
' REGSAM is an ACCESS_MASK (winreg.h), which is a DWORD (winnt.h)
DECLARE DYNAMIC LIBRARY "advapi32"
' http://msdn.microsoft.com/en-us/library/ms724897(v=VS.85).aspx
FUNCTION RegOpenKeyExA& (BYVAL hKey AS _OFFSET, BYVAL lpSubKey AS _OFFSET, BYVAL ulOptions AS _UNSIGNED LONG, BYVAL samDesired AS _UNSIGNED LONG, BYVAL phkResult AS _OFFSET)
' http://msdn.microsoft.com/en-us/library/ms724837(v=VS.85).aspx
FUNCTION RegCloseKey& (BYVAL hKey AS _OFFSET)
' http://msdn.microsoft.com/en-us/library/ms724865(v=VS.85).aspx
FUNCTION RegEnumValueA& (BYVAL hKey AS _OFFSET, BYVAL dwIndex AS _UNSIGNED LONG, BYVAL lpValueName AS _OFFSET, BYVAL lpcchValueName AS _OFFSET, BYVAL lpReserved AS _OFFSET, BYVAL lpType AS _OFFSET, BYVAL lpData AS _OFFSET, BYVAL lpcbData AS _OFFSET)
' http://msdn.microsoft.com/en-us/library/ms724911(v=VS.85).aspx
FUNCTION RegQueryValueExA& (BYVAL hKey AS _OFFSET, BYVAL lpValueName AS _OFFSET, BYVAL lpReserved AS _OFFSET, BYVAL lpType AS _OFFSET, BYVAL lpData AS _OFFSET, BYVAL lpcbData AS _OFFSET)
' http://msdn.microsoft.com/en-us/library/ms724923(v=VS.85).aspx
FUNCTION RegSetValueExA& (BYVAL hKey AS _OFFSET, BYVAL lpValueName AS _OFFSET, BYVAL Reserved AS _UNSIGNED LONG, BYVAL dwType AS _UNSIGNED LONG, BYVAL lpData AS _OFFSET, BYVAL cbData AS _UNSIGNED LONG)
'untested:
' http://msdn.microsoft.com/en-us/library/ms724862(v=VS.85).aspx
FUNCTION RegEnumKeyExA& (BYVAL hKey AS _OFFSET, BYVAL dwIndex AS _UNSIGNED LONG, BYVAL lpName AS _OFFSET, BYVAL lpcName AS _OFFSET, BYVAL lpReserved AS _OFFSET, BYVAL lpClass AS _OFFSET, BYVAL lpcClass AS _OFFSET, BYVAL lpftLastWriteTime AS _OFFSET)
' http://msdn.microsoft.com/en-us/library/ms724844(v=VS.85).aspx
FUNCTION RegCreateKeyExA& (BYVAL hKey AS _OFFSET, BYVAL lpSubKey AS _OFFSET, BYVAL Reserved AS _UNSIGNED LONG, BYVAL lpClass AS _OFFSET, BYVAL dwOptions AS _UNSIGNED LONG, BYVAL samDesired AS _UNSIGNED LONG, BYVAL lpSecurityAttributes AS _OFFSET, BYVAL phkResult AS _OFFSET, BYVAL lpdwDisposition AS _OFFSET)
' http://msdn.microsoft.com/en-us/library/ms724851(v=VS.85).aspx
FUNCTION RegDeleteValueA& (BYVAL hKey AS _OFFSET, BYVAL lpValueName AS _OFFSET) '<<< DANGER
' http://msdn.microsoft.com/en-us/library/ms724845(v=VS.85).aspx
FUNCTION RegDeleteKeyA& (BYVAL hKey AS _OFFSET, BYVAL lpSubKey AS _OFFSET) '<<< DANGER
' http://msdn.microsoft.com/en-us/library/ms724905(v=VS.85).aspx
FUNCTION RegQueryMultipleValuesA& (BYVAL hKey AS _OFFSET, BYVAL val_list AS _OFFSET, BYVAL num_vals AS _UNSIGNED LONG, BYVAL lpValueBuf AS _OFFSET, BYVAL ldwTotsize AS _OFFSET)
' http://msdn.microsoft.com/en-us/library/ms724902(v=VS.85).aspx
FUNCTION RegQueryInfoKeyA& (BYVAL hKey AS _OFFSET, BYVAL lpClass AS _OFFSET, BYVAL lpcClass AS _OFFSET, BYVAL lpReserved AS _OFFSET, BYVAL lpcSubKeys AS _OFFSET, BYVAL lpcMaxSubKeyLen AS _OFFSET, BYVAL lpcMaxClassLen AS _OFFSET, BYVAL lpcValues AS _OFFSET, BYVAL lpcMaxValueNameLen AS _OFFSET, BYVAL lpcMaxValueLen AS _OFFSET, BYVAL lpcbSecurityDescriptor AS _OFFSET, BYVAL lpftLastWriteTime AS _OFFSET)
END DECLARE
' http://msdn.microsoft.com/en-us/library/ms725490(v=VS.85).aspx
TYPE VALENT 'for RegQueryMultipleValues
ve_valuename AS _OFFSET
ve_valuelen AS _UNSIGNED LONG
ve_valueptr AS _OFFSET
ve_type AS _UNSIGNED LONG
END TYPE
' example:
DIM hKey AS _OFFSET
DIM Ky AS _OFFSET
DIM SubKey AS STRING
DIM Value AS STRING
DIM bData AS STRING
DIM t AS STRING
DIM dwType AS _UNSIGNED LONG
DIM numBytes AS _UNSIGNED LONG
DIM numTchars AS _UNSIGNED LONG
DIM l AS LONG
DIM dwIndex AS _UNSIGNED LONG
Ky = HKEY_CURRENT_USER
SubKey = "Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" + CHR$(0)
Value = "NoDriveTypeAutoRun" + CHR$(0)
bData = SPACE$(4)
numBytes = LEN(bData)
DO
PRINT "This value enables/disables AutoRun/AutoPlay for the current user:"
l = RegOpenKeyExA(Ky, _OFFSET(SubKey), 0, KEY_READ, _OFFSET(hKey))
IF l THEN
PRINT "RegOpenKeyExA failed. Error: 0x" + LCASE$(HEX$(l))
ELSE
l = RegQueryValueExA(hKey, _OFFSET(Value), 0, _OFFSET(dwType), _OFFSET(bData), _OFFSET(numBytes))
IF l THEN
PRINT "RegQueryValueExA failed. Error: 0x" + LCASE$(HEX$(l))
ELSE
PRINT whatKey$(Ky) + "\" + SubKey
PRINT whatType(dwType) + " " + Value + " = " + formatData(dwType, numBytes, bData)
END IF
l = RegCloseKey(hKey)
IF l THEN
PRINT "RegCloseKey failed. Error: 0x" + LCASE$(HEX$(l))
END
END IF
END IF
IF dwType <> REG_DWORD THEN
PRINT "Oops. I expected that value to be a DWORD."
EXIT DO
END IF
PRINT
PRINT "Would you like to change that value? ";
DO
_LIMIT 20
t = LCASE$(INKEY$)
LOOP UNTIL (t = "y") OR (t = "n")
PRINT t
IF t = "y" THEN
PRINT "I recommend setting this value to 0xff to disable AutoRun for the current user."
PRINT "Enter a new DWORD value: 0x";
LINE INPUT t
bData = MKL$(VAL("&h" + t + "&"))
t = "y"
l = RegOpenKeyExA(Ky, _OFFSET(SubKey), 0, KEY_ALL_ACCESS, _OFFSET(hKey))
IF l THEN
PRINT "RegOpenKeyExA failed. Error: 0x" + LCASE$(HEX$(l))
ELSE
l = RegSetValueExA(hKey, _OFFSET(Value), 0, dwType, _OFFSET(bData), numBytes)
IF l THEN
PRINT "RegSetValueExA failed. Error: 0x" + LCASE$(HEX$(l))
END IF
l = RegCloseKey(hKey)
IF l THEN
PRINT "RegCloseKey failed. Error: 0x" + LCASE$(HEX$(l))
END
END IF
END IF
PRINT
END IF
LOOP UNTIL t = "n"
PRINT
PRINT "This key lists some of the programs that auto start for all users:"
Ky = HKEY_LOCAL_MACHINE
SubKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Run" + CHR$(0)
Value = SPACE$(261) 'ANSI Value name limit 260 chars + 1 null
bData = SPACE$(&H7FFF) 'arbitrary
l = RegOpenKeyExA(Ky, _OFFSET(SubKey), 0, KEY_READ, _OFFSET(hKey))
IF l THEN
PRINT "RegOpenKeyExA failed. Error: 0x" + LCASE$(HEX$(l))
ELSE
PRINT whatKey$(Ky) + "\" + SubKey
dwIndex = 0
DO
SLEEP 1
numBytes = LEN(bData)
numTchars = LEN(Value)
l = RegEnumValueA(hKey, dwIndex, _OFFSET(Value), _OFFSET(numTchars), 0, _OFFSET(dwType), _OFFSET(bData), _OFFSET(numBytes))
IF l THEN
IF l <> ERROR_NO_MORE_ITEMS THEN
PRINT "RegEnumValueA failed. Error: 0x" + LCASE$(HEX$(l))
END IF
EXIT DO
ELSE
PRINT whatType(dwType) + " " + LEFT$(Value, numTchars) + " = " + formatData(dwType, numBytes, bData)
END IF
dwIndex = dwIndex + 1
LOOP
PRINT dwIndex; "Values."
l = RegCloseKey(hKey)
IF l THEN
PRINT "RegCloseKey failed. Error: 0x" + LCASE$(HEX$(l))
END
END IF
END IF
END
FUNCTION whatType$ (dwType AS _UNSIGNED LONG)
SELECT CASE dwType
CASE REG_SZ: whatType = "REG_SZ"
CASE REG_EXPAND_SZ: whatType = "REG_EXPAND_SZ"
CASE REG_BINARY: whatType = "REG_BINARY"
CASE REG_DWORD: whatType = "REG_DWORD"
CASE REG_DWORD_BIG_ENDIAN: whatType = "REG_DWORD_BIG_ENDIAN"
CASE REG_LINK: whatType = "REG_LINK"
CASE REG_MULTI_SZ: whatType = "REG_MULTI_SZ"
CASE REG_RESOURCE_LIST: whatType = "REG_RESOURCE_LIST"
CASE REG_FULL_RESOURCE_DESCRIPTOR: whatType = "REG_FULL_RESOURCE_DESCRIPTOR"
CASE REG_RESOURCE_REQUIREMENTS_LIST: whatType = "REG_RESOURCE_REQUIREMENTS_LIST"
CASE REG_QWORD: whatType = "REG_QWORD"
CASE ELSE: whatType = "unknown"
END SELECT
END FUNCTION
FUNCTION whatKey$ (hKey AS _OFFSET)
SELECT CASE hKey
CASE HKEY_CLASSES_ROOT: whatKey = "HKEY_CLASSES_ROOT"
CASE HKEY_CURRENT_USER: whatKey = "HKEY_CURRENT_USER"
CASE HKEY_LOCAL_MACHINE: whatKey = "HKEY_LOCAL_MACHINE"
CASE HKEY_USERS: whatKey = "HKEY_USERS"
CASE HKEY_PERFORMANCE_DATA: whatKey = "HKEY_PERFORMANCE_DATA"
CASE HKEY_CURRENT_CONFIG: whatKey = "HKEY_CURRENT_CONFIG"
CASE HKEY_DYN_DATA: whatKey = "HKEY_DYN_DATA"
END SELECT
END FUNCTION
FUNCTION formatData$ (dwType AS _UNSIGNED LONG, numBytes AS _UNSIGNED LONG, bData AS STRING)
DIM t AS STRING
DIM ul AS _UNSIGNED LONG
DIM b AS _UNSIGNED _BYTE
SELECT CASE dwType
CASE REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ
formatData = LEFT$(bData, numBytes)
CASE REG_DWORD
t = LCASE$(HEX$(CVL(LEFT$(bData, 4))))
formatData = "0x" + STRING$(8 - LEN(t), &H30) + t
CASE ELSE
IF numBytes THEN
b = ASC(LEFT$(bData, 1))
IF b < &H10 THEN
t = t + "0" + LCASE$(HEX$(b))
ELSE
t = t + LCASE$(HEX$(b))
END IF
END IF
FOR ul = 2 TO numBytes
b = ASC(MID$(bData, ul, 1))
IF b < &H10 THEN
t = t + " 0" + LCASE$(HEX$(b))
ELSE
t = t + " " + LCASE$(HEX$(b))
END IF
NEXT
formatData = t
END SELECT
END FUNCTION
```
> *Note:* This procedure lists most of the Constants and Registry functions available, but only uses a few of them in this demo. All of these functions, except RegCloseKey, have both ANSI (ending in A) and Unicode (ending in W) versions. I am not aware of any reason why both versions could not be used in the same program. To add the Unicode version, duplicate the function declaration, but change the ending A to W. Be sure that you know how to use the [Unicode](Unicode) version!
**WARNING! Use care when editing or altering Registry settings! YOU will be responsible for any damages incurred!**
**Your code contribution using the above Registry Libraries could end up here!**
## See Also
* [Windows Libraries](Windows-Libraries)
* [DECLARE LIBRARY](DECLARE-LIBRARY)
* [_OFFSET](_OFFSET)