Skip to content

Instantly share code, notes, and snippets.

@aquanox
Last active November 7, 2025 12:27
Show Gist options
  • Select an option

  • Save aquanox/bcfc0d087f928aefacdf49bcf0f83be1 to your computer and use it in GitHub Desktop.

Select an option

Save aquanox/bcfc0d087f928aefacdf49bcf0f83be1 to your computer and use it in GitHub Desktop.
PHP 8.4 FFI Windows Registry Query
#define FFI_LIB "kernel32.dll"
#define FFI_SCOPE "kernel32"
typedef unsigned short wchar_t;
typedef int BOOL;
typedef unsigned long DWORD;
typedef void *PVOID;
typedef PVOID HANDLE;
typedef DWORD *LPDWORD;
typedef unsigned short WORD;
typedef wchar_t WCHAR;
typedef short SHORT;
typedef unsigned short USHORT;
typedef unsigned int UINT;
typedef char CHAR;
typedef char BYTE;
typedef unsigned char UBYTE;
typedef WCHAR TCHAR;
typedef long LSTATUS;
typedef long HKEY;
typedef HKEY* PHKEY;
typedef DWORD ACCESS_MASK;
typedef ACCESS_MASK *PACCESS_MASK;
typedef ACCESS_MASK REGSAM;
typedef const char* LPCSTR;
typedef char* LPSTR;
typedef const wchar_t* LPCWSTR;
typedef wchar_t* LPWSTR;
typedef BYTE* LPBYTE;
LSTATUS
RegOpenKeyExA(
/*_In_*/ HKEY hKey,
/*_In_opt_*/ LPCSTR lpSubKey,
/*_In_opt_*/ DWORD ulOptions,
/*_In_*/ REGSAM samDesired,
/*_Out_*/ PHKEY phkResult
);
LSTATUS
RegOpenKeyExW(
/*_In_*/ HKEY hKey,
/*_In_opt_*/ LPCWSTR lpSubKey,
/*_In_opt_*/ DWORD ulOptions,
/*_In_*/ REGSAM samDesired,
/*_Out_*/ PHKEY phkResult
);
LSTATUS
RegEnumValueA(
/*_In_*/ HKEY hKey,
/*_In_*/ DWORD dwIndex,
/*_Out_writes_to_opt_(*lpcchValueName,*lpcchValueName + 1)*/ LPSTR lpValueName,
/*_Inout_*/ LPDWORD lpcchValueName,
/*_Reserved_*/ LPDWORD lpReserved,
/*_Out_opt_*/ LPDWORD lpType,
/*_Out_writes_bytes_to_opt_(*lpcbData, *lpcbData) __out_data_source(REGISTRY)*/ LPBYTE lpData,
/*_Inout_opt_*/ LPDWORD lpcbData
);
LSTATUS
RegEnumValueW(
/*_In_*/ HKEY hKey,
/*_In_*/ DWORD dwIndex,
/*_Out_writes_to_opt_(*lpcchValueName,*lpcchValueName + 1)*/ LPWSTR lpValueName,
/*_Inout_*/ LPDWORD lpcchValueName,
/*_Reserved_*/ LPDWORD lpReserved,
/*_Out_opt_*/ LPDWORD lpType,
/*_Out_writes_bytes_to_opt_(*lpcbData, *lpcbData) __out_data_source(REGISTRY)*/ LPBYTE lpData,
/*_Inout_opt_*/ LPDWORD lpcbData
);
<?php
if (!extension_loaded('ffi'))
die("FFI Extension is not loaded");
const ERROR_SUCCESS = 0;
const ERROR_NO_MORE_ITEMS = 259;
const HKEY_CLASSES_ROOT = 0x80000000;
const HKEY_CURRENT_USER = 0x80000001;
const HKEY_LOCAL_MACHINE = 0x80000002;
const HKEY_USERS = 0x80000003;
const HKEY_PERFORMANCE_DATA = 0x80000004;
const HKEY_PERFORMANCE_TEXT = 0x80000050;
const HKEY_PERFORMANCE_NLSTEXT = 0x80000060;
const HKEY_CURRENT_CONFIG = 0x80000005;
const HKEY_DYN_DATA = 0x80000006;
const HKEY_CURRENT_USER_LOCAL_SETTINGS = 0x80000007;
const KEY_QUERY_VALUE = (0x0001);
const KEY_SET_VALUE = (0x0002);
const KEY_CREATE_SUB_KEY = (0x0004);
const KEY_ENUMERATE_SUB_KEYS = (0x0008);
const KEY_NOTIFY = (0x0010);
const KEY_CREATE_LINK = (0x0020);
const KEY_WOW64_32KEY = (0x0200);
const KEY_WOW64_64KEY = (0x0100);
const KEY_WOW64_RES = (0x0300);
const STANDARD_RIGHTS_READ = 0x00020000;
const KEY_READ = STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY;
function EnumInstalledEngines() : array
{
$result = array();
$ffi = FFI::load(__DIR__ . DIRECTORY_SEPARATOR . 'ffi-kernel32.h');
$hKey = $ffi->new('HKEY');
$hResult = $ffi->RegOpenKeyExA(HKEY_CURRENT_USER,
"SOFTWARE\\Epic Games\\Unreal Engine\\Builds",
null,
KEY_READ,
FFI::addr($hKey)
);
if ($hResult == ERROR_SUCCESS)
{
for($Index = 0;$Index < 256; ++$Index)
{
$ValueName = $ffi->new('CHAR[256]');
$ValueData = $ffi->new('BYTE[256]');
$ValueType = $ffi->new('DWORD');
$ValueType->cdata = 0;
$ValueNameLength = $ffi->new('DWORD');
$ValueNameLength->cdata = FFI::sizeof($ValueName);
$ValueDataLength = $ffi->new('DWORD');
$ValueDataLength->cdata = FFI::sizeof($ValueData);
$hResult = $ffi->RegEnumValueA(
$hKey->cdata,
$Index,
$ValueName,
FFI::addr($ValueNameLength),
null,
FFI::addr($ValueType),
$ffi->cast('LPBYTE', FFI::addr($ValueData)),
FFI::addr($ValueDataLength)
);
if ($hResult == ERROR_SUCCESS)
{
$name = FFI::string($ValueName);
$data = FFI::string($ValueData);
//echo "$name => $data" . PHP_EOL;
$result[] = array(
'Key' => $name,
'Path' => $data
);
}
elseif ($hResult == ERROR_NO_MORE_ITEMS)
{
break;
}
}
}
return $result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment