mirror of
https://github.com/DxWnd/DxWnd.reloaded
synced 2024-12-30 09:25:35 +01:00
662 lines
20 KiB
C++
662 lines
20 KiB
C++
#define _CRT_SECURE_NO_WARNINGS
|
|
|
|
#include <stdio.h>
|
|
#include "dxwnd.h"
|
|
#include "dxwcore.hpp"
|
|
#include "syslibs.h"
|
|
#include "dxhook.h"
|
|
#include "dxhelper.h"
|
|
|
|
typedef LONG (WINAPI *RegFlushKey_Type)(HKEY);
|
|
LONG WINAPI extRegFlushKey(HKEY);
|
|
RegFlushKey_Type pRegFlushKey = NULL;
|
|
typedef LONG (WINAPI *RegEnumValueA_Type)(HKEY, DWORD, LPTSTR, LPDWORD, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
|
|
LONG WINAPI extRegEnumValueA(HKEY, DWORD, LPTSTR, LPDWORD, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
|
|
RegEnumValueA_Type pRegEnumValueA = NULL;
|
|
|
|
static HookEntryEx_Type Hooks[]={
|
|
{HOOK_IAT_CANDIDATE, 0, "RegOpenKeyExA", NULL, (FARPROC *)&pRegOpenKeyEx, (FARPROC)extRegOpenKeyEx},
|
|
{HOOK_IAT_CANDIDATE, 0, "RegCloseKey", NULL, (FARPROC *)&pRegCloseKey, (FARPROC)extRegCloseKey},
|
|
{HOOK_IAT_CANDIDATE, 0, "RegQueryValueA", NULL, (FARPROC *)&pRegQueryValue, (FARPROC)extRegQueryValue},
|
|
{HOOK_IAT_CANDIDATE, 0, "RegQueryValueExA", NULL, (FARPROC *)&pRegQueryValueEx, (FARPROC)extRegQueryValueEx},
|
|
{HOOK_IAT_CANDIDATE, 0, "RegCreateKeyA", NULL, (FARPROC *)&pRegCreateKey, (FARPROC)extRegCreateKey},
|
|
{HOOK_IAT_CANDIDATE, 0, "RegCreateKeyExA", NULL, (FARPROC *)&pRegCreateKeyEx, (FARPROC)extRegCreateKeyEx},
|
|
{HOOK_IAT_CANDIDATE, 0, "RegSetValueExA", NULL, (FARPROC *)&pRegSetValueEx, (FARPROC)extRegSetValueEx},
|
|
{HOOK_IAT_CANDIDATE, 0, "RegFlushKey", NULL, (FARPROC *)&pRegFlushKey, (FARPROC)extRegFlushKey},
|
|
// v2.3.36
|
|
{HOOK_IAT_CANDIDATE, 0, "RegEnumValueA", NULL, (FARPROC *)&pRegEnumValueA, (FARPROC)extRegEnumValueA},
|
|
{HOOK_IAT_CANDIDATE, 0, 0, NULL, 0, 0} // terminator
|
|
};
|
|
|
|
void HookAdvApi32(HMODULE module)
|
|
{
|
|
if( (dxw.dwFlags3 & EMULATEREGISTRY) ||
|
|
(dxw.dwFlags4 & OVERRIDEREGISTRY) ||
|
|
(dxw.dwFlags6 & (WOW32REGISTRY|WOW64REGISTRY)) ||
|
|
(dxw.dwTFlags & OUTREGISTRY))
|
|
HookLibraryEx(module, Hooks, "ADVAPI32.dll");
|
|
}
|
|
|
|
FARPROC Remap_AdvApi32_ProcAddress(LPCSTR proc, HMODULE hModule)
|
|
{
|
|
FARPROC addr;
|
|
if(!(dxw.dwFlags3 & EMULATEREGISTRY) ||
|
|
(dxw.dwFlags4 & OVERRIDEREGISTRY) ||
|
|
(dxw.dwFlags6 & (WOW32REGISTRY|WOW64REGISTRY)) ||
|
|
(dxw.dwTFlags & OUTREGISTRY)) return NULL;
|
|
if (addr=RemapLibraryEx(proc, hModule, Hooks)) return addr;
|
|
return NULL;
|
|
}
|
|
|
|
#define HKEY_FAKE ((HKEY)0x7FFFFFFF)
|
|
#define HKEY_MASK 0x7FFFFF00
|
|
#define IsFake(hKey) (((DWORD)hKey & HKEY_MASK) == HKEY_MASK)
|
|
|
|
static FILE *OpenFakeRegistry();
|
|
static char *hKey2String(HKEY);
|
|
static LONG myRegOpenKeyEx(HKEY, LPCTSTR, PHKEY);
|
|
|
|
// int ReplaceVar(pData, lplpData, lpcbData):
|
|
// extract the token name from pData beginning up to '}' delimiter
|
|
// calculates the value of the token. If the token is unknown, the value is null string.
|
|
// if *lplpData, copies the token value string to *lplpData and increments *lplpData
|
|
// if lpcbData, increments the key length of the token value length
|
|
// returns the length of token label to advance the parsing loop
|
|
|
|
typedef enum {
|
|
LABEL_PATH = 0,
|
|
LABEL_WORKDIR,
|
|
LABEL_VOID,
|
|
LABEL_END
|
|
};
|
|
static char *sTokenLabels[LABEL_END+1]={
|
|
"path}",
|
|
"work}",
|
|
"}",
|
|
NULL
|
|
};
|
|
|
|
static int ReplaceVar(char *pData, LPBYTE *lplpData, LPDWORD lpcbData)
|
|
{
|
|
int iTokenLength;
|
|
int iLabelLength;
|
|
int iTokenIndex;
|
|
char sTokenValue[MAX_PATH];
|
|
// search for a matching token
|
|
for(iTokenIndex=0; sTokenLabels[iTokenIndex]; iTokenIndex++){
|
|
if(!_strnicmp(pData, sTokenLabels[iTokenIndex], strlen(sTokenLabels[iTokenIndex]))) break;
|
|
}
|
|
// set token label length
|
|
iLabelLength = strlen(sTokenLabels[iTokenIndex]);
|
|
// do replacement
|
|
switch(iTokenIndex){
|
|
case LABEL_PATH:
|
|
case LABEL_WORKDIR:
|
|
GetCurrentDirectory(MAX_PATH, sTokenValue);
|
|
break;
|
|
case LABEL_VOID:
|
|
case LABEL_END:
|
|
strcpy(sTokenValue, "");
|
|
break;
|
|
}
|
|
// set output vars if not NULL
|
|
iTokenLength = strlen(sTokenValue);
|
|
OutTraceR("REPLACED token=%d val=\"%s\" len=%d\n", iTokenIndex, sTokenValue, iTokenLength);
|
|
if(*lplpData) {
|
|
strcpy((char *)*lplpData, sTokenValue);
|
|
*lplpData += iTokenLength;
|
|
}
|
|
if(lpcbData) *lpcbData += iTokenLength;
|
|
// return label length to advance parsing
|
|
return iLabelLength;
|
|
}
|
|
|
|
static char *hKey2String(HKEY hKey)
|
|
{
|
|
char *skey;
|
|
static char sKey[MAX_PATH+1];
|
|
static char skeybuf[10];
|
|
if(IsFake(hKey)) {
|
|
FILE *regf;
|
|
char RegBuf[MAX_PATH+1];
|
|
regf=OpenFakeRegistry();
|
|
if(regf!=NULL){
|
|
HKEY hLocalKey=HKEY_FAKE;
|
|
fgets(RegBuf, 256, regf);
|
|
while (!feof(regf)){
|
|
if(RegBuf[0]=='['){
|
|
if(hLocalKey == hKey){
|
|
//OutTrace("building fake Key=\"%s\" hKey=%x\n", sKey, hKey);
|
|
fclose(regf);
|
|
strcpy(sKey, &RegBuf[1]);
|
|
//sKey[strlen(sKey)-2]=0; // get rid of "]"
|
|
for(int i=strlen(sKey)-1; i; i--){
|
|
if(sKey[i]==']'){
|
|
sKey[i]=0;
|
|
break;
|
|
}
|
|
}
|
|
return sKey;
|
|
}
|
|
else {
|
|
hLocalKey--;
|
|
}
|
|
}
|
|
fgets(RegBuf, 256, regf);
|
|
}
|
|
fclose(regf);
|
|
}
|
|
return "HKEY_NOT_FOUND";
|
|
}
|
|
switch((ULONG)hKey){
|
|
case HKEY_CLASSES_ROOT: skey="HKEY_CLASSES_ROOT"; break;
|
|
case HKEY_CURRENT_CONFIG: skey="HKEY_CURRENT_CONFIG"; break;
|
|
case HKEY_CURRENT_USER: skey="HKEY_CURRENT_USER"; break;
|
|
case HKEY_LOCAL_MACHINE: skey="HKEY_LOCAL_MACHINE"; break;
|
|
case HKEY_USERS: skey="HKEY_USERS"; break;
|
|
default: sprintf(skeybuf, "0x%x", hKey); skey=skeybuf; break;
|
|
}
|
|
return skey;
|
|
}
|
|
|
|
static char *Unescape(char *s, char **dest)
|
|
{
|
|
if(!*dest) *dest=(char *)malloc(strlen(s)+100);
|
|
else *dest=(char *)realloc(*dest, strlen(s)+100);
|
|
char *t = *dest;
|
|
for(; *s; s++){
|
|
if((*s=='\\') && (*(s+1)=='n')){
|
|
*t++ = '\n';
|
|
s++;
|
|
}
|
|
else{
|
|
*t++ = *s;
|
|
}
|
|
}
|
|
*t=0;
|
|
return *dest;
|
|
}
|
|
|
|
static FILE *OpenFakeRegistry()
|
|
{
|
|
DWORD dwAttrib;
|
|
char sSourcePath[MAX_PATH+1];
|
|
char *p;
|
|
dwAttrib = GetFileAttributes("dxwnd.dll");
|
|
if (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) return NULL;
|
|
GetModuleFileName(GetModuleHandle("dxwnd"), sSourcePath, MAX_PATH);
|
|
p=&sSourcePath[strlen(sSourcePath)-strlen("dxwnd.dll")];
|
|
strcpy(p, "dxwnd.reg");
|
|
return fopen(sSourcePath,"r");
|
|
}
|
|
|
|
static LONG SeekFakeKey(FILE *regf, HKEY hKey)
|
|
{
|
|
LONG res;
|
|
res = ERROR_FILE_NOT_FOUND;
|
|
char RegBuf[MAX_PATH+1];
|
|
HKEY hCurKey=HKEY_FAKE+1;
|
|
fgets(RegBuf, 256, regf);
|
|
while (!feof(regf)){
|
|
if(RegBuf[0]=='['){
|
|
hCurKey--;
|
|
}
|
|
if(hCurKey==hKey) {
|
|
//OutTraceB("DEBUG: SeekFakeKey fount key at line=%s\n", RegBuf);
|
|
res = ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
fgets(RegBuf, 256, regf);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
static LONG SeekValueName(FILE *regf, LPCTSTR lpValueName)
|
|
{
|
|
LONG res;
|
|
char RegBuf[MAX_PATH+1];
|
|
long KeySeekPtr;
|
|
res = ERROR_FILE_NOT_FOUND;
|
|
// v2.04.01: fix to handle the '@' case properly
|
|
if(lpValueName) if(!lpValueName[0]) lpValueName=NULL;
|
|
KeySeekPtr = ftell(regf);
|
|
fgets(RegBuf, 256, regf);
|
|
while (!feof(regf)){
|
|
if((RegBuf[0]=='"') &&
|
|
!_strnicmp(lpValueName, &RegBuf[1], strlen(lpValueName)) &&
|
|
(RegBuf[strlen(lpValueName)+1]=='"') &&
|
|
(RegBuf[strlen(lpValueName)+2]=='='))
|
|
{
|
|
fseek(regf, KeySeekPtr, SEEK_SET);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
if(!lpValueName && (RegBuf[0]=='@')){
|
|
fseek(regf, KeySeekPtr, SEEK_SET);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
if(RegBuf[0]=='[') return res;
|
|
KeySeekPtr = ftell(regf);
|
|
fgets(RegBuf, 256, regf);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
static LONG SeekValueIndex(FILE *regf, DWORD dwIndex, LPCTSTR lpValueName, LPDWORD lpcchValueName)
|
|
{
|
|
LONG res;
|
|
char RegBuf[MAX_PATH+1];
|
|
long KeySeekPtr;
|
|
res = ERROR_NO_MORE_ITEMS;
|
|
KeySeekPtr = ftell(regf);
|
|
fgets(RegBuf, 256, regf);
|
|
dwIndex++;
|
|
while (!feof(regf) && dwIndex){
|
|
if(RegBuf[0]=='"') dwIndex--;
|
|
if(dwIndex == 0){
|
|
fseek(regf, KeySeekPtr, SEEK_SET);
|
|
//sscanf(RegBuf, "\"%s\"=", lpValueName);
|
|
strncpy((char *)lpValueName, strtok(&RegBuf[1], "\""), *lpcchValueName);
|
|
*lpcchValueName = strlen(lpValueName);
|
|
//OutTrace("DEBUG: lpValueName=%s len=%d\n", lpValueName, *lpcchValueName);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
if(RegBuf[0]=='[') return res;
|
|
KeySeekPtr = ftell(regf);
|
|
fgets(RegBuf, 256, regf);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
static DWORD GetKeyValue(
|
|
FILE *regf,
|
|
char *ApiName,
|
|
LPCTSTR lpValueName,
|
|
LPDWORD lpType, // beware: could be NULL
|
|
LPBYTE lpData, // beware: could be NULL
|
|
LPDWORD lpcbData)
|
|
{
|
|
LONG res;
|
|
LPBYTE lpb;
|
|
char *pData;
|
|
char RegBuf[MAX_PATH+1];
|
|
DWORD cbData=0;
|
|
|
|
//OutTrace("GetKeyValue: ValueName=%s\n", lpValueName);
|
|
fgets(RegBuf, 256, regf);
|
|
if(RegBuf[0]=='@')
|
|
pData=&RegBuf[2];
|
|
else
|
|
pData=&RegBuf[strlen(lpValueName)+3];
|
|
lpb = lpData;
|
|
if(lpcbData) {
|
|
cbData = *lpcbData;
|
|
*lpcbData=0;
|
|
}
|
|
do {
|
|
if(*pData=='"'){ // string value
|
|
if(lpType) *lpType=REG_SZ;
|
|
pData++;
|
|
while(*pData && (*pData != '"')){
|
|
if(*pData=='\\') {
|
|
pData++;
|
|
switch(*pData){
|
|
case '{':{
|
|
pData++; // skip '{'
|
|
pData += ReplaceVar(pData, &lpb, lpcbData);
|
|
continue; // v2.04.13 fix
|
|
}
|
|
break;
|
|
default:
|
|
break; // skip first '\'
|
|
}
|
|
}
|
|
if(lpData && lpcbData) if(*lpcbData < cbData) *lpb++=*pData;
|
|
pData++;
|
|
if(lpcbData) (*lpcbData)++;
|
|
}
|
|
if(lpcbData) (*lpcbData)++; // extra space for string terminator ?
|
|
if(lpData && lpcbData) if(*lpcbData < cbData) *lpb = 0; // string terminator
|
|
OutTraceR("%s: type=REG_SZ cbData=%d Data=\"%s\"\n",
|
|
ApiName, lpcbData ? *lpcbData : 0, lpData ? (char *)lpData : "(NULL)");
|
|
// v2.04.14 fix: ERROR_MORE_DATA should be returned only in case lpData is not NULL
|
|
res=ERROR_SUCCESS;
|
|
if(lpData && lpcbData)
|
|
if (*lpcbData > cbData) res = ERROR_MORE_DATA;
|
|
break;
|
|
}
|
|
if(!strncmp(pData,"dword:",strlen("dword:"))){ //dword value
|
|
DWORD val;
|
|
if(lpType) *lpType=REG_DWORD;
|
|
pData+=strlen("dword:");
|
|
sscanf(pData, "%x", &val);
|
|
if(lpData) {
|
|
if (cbData >= sizeof(DWORD)) {
|
|
memcpy(lpData, &val, sizeof(DWORD));
|
|
res=ERROR_SUCCESS;
|
|
}
|
|
else
|
|
res=ERROR_MORE_DATA;
|
|
}
|
|
else
|
|
res=ERROR_SUCCESS; // data not needed
|
|
if (lpcbData) *lpcbData=sizeof(DWORD);
|
|
OutTraceR("%s: type=REG_DWORD cbData=%x Data=0x%x\n",
|
|
ApiName, lpcbData ? *lpcbData : 0, val);
|
|
break;
|
|
}
|
|
if(!strncmp(pData,"hex:",strlen("hex:"))){ //hex value
|
|
BYTE *p;
|
|
if(lpType) *lpType=REG_BINARY;
|
|
p = (BYTE *)pData;
|
|
p+=strlen("hex:");
|
|
while(TRUE){
|
|
p[strlen((char *)p)-1]=0; // eliminates \n at the end of line
|
|
while(strlen((char *)p)>1){
|
|
if((*lpcbData < cbData) && lpData){
|
|
sscanf((char *)p, "%x,", (char *)lpb);
|
|
lpb++;
|
|
}
|
|
p+=3;
|
|
if(lpcbData) (*lpcbData)++;
|
|
}
|
|
if(p[strlen((char *)p)-1]=='\\'){
|
|
fgets(RegBuf, 256, regf);
|
|
pData = RegBuf;
|
|
p = (BYTE *)pData;
|
|
}
|
|
else break;
|
|
}
|
|
OutTraceR("%s: type=REG_BINARY cbData=%d Data=%s\n",
|
|
ApiName,
|
|
lpcbData ? *lpcbData : 0,
|
|
lpData ? "(NULL)" : hexdump(lpData, *lpcbData));
|
|
res=(*lpcbData > cbData) ? ERROR_MORE_DATA : ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
} while(FALSE);
|
|
return res;
|
|
}
|
|
|
|
static void LogKeyValue(char *ApiName, LONG res, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
|
|
{
|
|
char sInfo[1024];
|
|
if(res) {
|
|
OutTrace("%s: ERROR res=%d\n", ApiName, res);
|
|
return;
|
|
}
|
|
sprintf(sInfo, "%s: res=ERROR_SUCCESS size=%d type=%x(%s)",
|
|
ApiName, lpcbData?*lpcbData:0, lpType?*lpType:0, lpType?ExplainRegType(*lpType):"none");
|
|
if(lpType && lpData && lpcbData) {
|
|
DWORD cbData = *lpcbData;
|
|
switch(*lpType){
|
|
case REG_SZ: sprintf(sInfo, "%s Data=\"%*.*s\"\n", sInfo, cbData-1, cbData-1, lpData); break;
|
|
case REG_DWORD: sprintf(sInfo, "%s Data=0x%x\n", sInfo, *(DWORD *)lpData); break;
|
|
case REG_BINARY: sprintf(sInfo, "%s Data=%s\n", sInfo, hexdump((BYTE *)lpData, cbData)); break;
|
|
case REG_NONE: sprintf(sInfo, "%s Data=\"%s\"\n", sInfo, lpData); break;
|
|
default: sprintf(sInfo, "%s Data=???\n", sInfo); break;
|
|
}
|
|
}
|
|
else
|
|
sprintf(sInfo, "%s\n", sInfo);
|
|
OutTrace(sInfo);
|
|
}
|
|
|
|
static LONG myRegOpenKeyEx(
|
|
LPCSTR label,
|
|
HKEY hKey,
|
|
LPCTSTR lpSubKey,
|
|
PHKEY phkResult)
|
|
{
|
|
FILE *regf;
|
|
char sKey[MAX_PATH+1];
|
|
char RegBuf[MAX_PATH+1];
|
|
|
|
sprintf(sKey,"%s\\%s", hKey2String(hKey), lpSubKey);
|
|
OutTraceR("%s: searching for key=\"%s\"\n", label, sKey);
|
|
|
|
regf=OpenFakeRegistry();
|
|
if(regf!=NULL){
|
|
if(phkResult) *phkResult=HKEY_FAKE;
|
|
fgets(RegBuf, 256, regf);
|
|
while (!feof(regf)){
|
|
if(RegBuf[0]=='['){
|
|
// beware: registry keys are case insensitive. Must use _strnicmp instead of strncmp
|
|
if((!_strnicmp(&RegBuf[1],sKey,strlen(sKey))) && (RegBuf[strlen(sKey)+1]==']')){
|
|
OutTraceR("%s: found fake Key=\"%s\" hkResult=%x\n", label, sKey, phkResult ? *phkResult : 0);
|
|
fclose(regf);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
else {
|
|
if(phkResult) (*phkResult)--;
|
|
}
|
|
}
|
|
fgets(RegBuf, 256, regf);
|
|
}
|
|
fclose(regf);
|
|
}
|
|
return ERROR_FILE_NOT_FOUND;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------------
|
|
|
|
LONG WINAPI extRegOpenKeyEx(
|
|
HKEY hKey,
|
|
LPCTSTR lpSubKey,
|
|
DWORD ulOptions,
|
|
REGSAM samDesired,
|
|
PHKEY phkResult)
|
|
{
|
|
LONG res;
|
|
|
|
OutTraceR("RegOpenKeyEx: hKey=%x(%s) SubKey=\"%s\" Options=%x\n",
|
|
hKey, hKey2String(hKey), lpSubKey, ulOptions);
|
|
|
|
if(dxw.dwFlags4 & OVERRIDEREGISTRY){
|
|
res = myRegOpenKeyEx("RegOpenKeyEx", hKey, lpSubKey, phkResult);
|
|
if(res == ERROR_SUCCESS) return res;
|
|
}
|
|
|
|
if(dxw.dwFlags6 & WOW64REGISTRY){
|
|
ulOptions &= ~KEY_WOW64_32KEY;
|
|
ulOptions |= KEY_WOW64_64KEY;
|
|
}
|
|
if(dxw.dwFlags6 & WOW32REGISTRY){
|
|
ulOptions &= ~KEY_WOW64_64KEY;
|
|
ulOptions |= KEY_WOW64_32KEY;
|
|
}
|
|
|
|
res=(*pRegOpenKeyEx)(hKey, lpSubKey, ulOptions, samDesired, phkResult);
|
|
OutTraceR("RegOpenKeyEx: res=%x phkResult=%x\n", res, phkResult ? *phkResult : 0);
|
|
|
|
if((res==ERROR_SUCCESS) || !(dxw.dwFlags3 & EMULATEREGISTRY) || (dxw.dwFlags4 & OVERRIDEREGISTRY)) return res;
|
|
|
|
return myRegOpenKeyEx("RegOpenKeyEx", hKey, lpSubKey, phkResult);
|
|
}
|
|
|
|
// extRegQueryValue: legacy API, almost always replaced by extRegQueryValueEx but referenced
|
|
// in "Warhammer 40.000 Shadow of the Horned Rat"
|
|
|
|
LONG WINAPI extRegQueryValue(
|
|
HKEY hKey,
|
|
LPCTSTR lpSubKey,
|
|
LPTSTR lpValue,
|
|
PLONG lpcbValue)
|
|
{
|
|
LONG res;
|
|
FILE *regf;
|
|
|
|
OutTraceR("RegQueryValue: hKey=%x(%s) SubKey=\"%s\"\n", hKey, hKey2String(hKey), lpSubKey);
|
|
|
|
if (!IsFake(hKey)){
|
|
res=(*pRegQueryValue)(hKey, lpSubKey, lpValue, lpcbValue);
|
|
if(IsTraceR) LogKeyValue("RegQueryValue", res, 0, (LPBYTE)lpValue, (LPDWORD)lpcbValue);
|
|
return res;
|
|
}
|
|
|
|
regf=OpenFakeRegistry();
|
|
if(regf==NULL) {
|
|
OutTraceR("RegQueryValue: error in OpenFakeRegistry err=%s\n", GetLastError());
|
|
return ERROR_FILE_NOT_FOUND;
|
|
}
|
|
res = SeekFakeKey(regf, hKey);
|
|
if(res != ERROR_SUCCESS) {
|
|
OutTraceR("RegQueryValue: error in SeekFakeKey res=%x hKey=%x\n", res, hKey);
|
|
return res;
|
|
}
|
|
res = SeekValueName(regf, lpSubKey);
|
|
if(res != ERROR_SUCCESS) {
|
|
OutTraceR("RegQueryValue: error in SeekValueName res=%x ValueName=%s\n", res, lpSubKey);
|
|
return res;
|
|
}
|
|
res = GetKeyValue(regf, "RegQueryValue", lpSubKey, NULL, (LPBYTE)lpValue, (LPDWORD)lpcbValue);
|
|
if(IsTraceR) LogKeyValue("RegQueryValue", res, NULL, (LPBYTE)lpValue, (LPDWORD)lpcbValue);
|
|
fclose(regf);
|
|
return res;
|
|
}
|
|
|
|
LONG WINAPI extRegQueryValueEx(
|
|
HKEY hKey,
|
|
LPCTSTR lpValueName,
|
|
LPDWORD lpReserved,
|
|
LPDWORD lpType, // beware: could be NULL
|
|
LPBYTE lpData, // beware: could be NULL
|
|
LPDWORD lpcbData)
|
|
{
|
|
LONG res;
|
|
FILE *regf;
|
|
DWORD cbData=0;
|
|
|
|
OutTraceR("RegQueryValueEx: hKey=%x(\"%s\") ValueName=\"%s\" Reserved=%x lpType=%x lpData=%x lpcbData=%x\n",
|
|
hKey, hKey2String(hKey), lpValueName, lpReserved, lpType, lpData, lpcbData);
|
|
if (!IsFake(hKey)){
|
|
res=(*pRegQueryValueEx)(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
|
|
if(IsTraceR) LogKeyValue("RegQueryValueEx", res, lpType, lpData, lpcbData);
|
|
return res;
|
|
}
|
|
|
|
regf=OpenFakeRegistry();
|
|
if(regf==NULL) {
|
|
OutTraceR("RegQueryValueEx: error in OpenFakeRegistry err=%s\n", GetLastError());
|
|
return ERROR_FILE_NOT_FOUND;
|
|
}
|
|
res = SeekFakeKey(regf, hKey);
|
|
if(res != ERROR_SUCCESS) {
|
|
OutTraceR("RegQueryValueEx: error in SeekFakeKey res=%x hKey=%x\n", res, hKey);
|
|
return res;
|
|
}
|
|
res = SeekValueName(regf, lpValueName);
|
|
if(res != ERROR_SUCCESS) {
|
|
OutTraceR("RegQueryValueEx: error in SeekValueName res=%x ValueName=%s\n", res, lpValueName);
|
|
return res;
|
|
}
|
|
res = GetKeyValue(regf, "RegQueryValueEx", lpValueName, lpType, lpData, lpcbData);
|
|
if(IsTraceR) LogKeyValue("RegQueryValueEx", res, lpType, lpData, lpcbData);
|
|
fclose(regf);
|
|
return res;
|
|
}
|
|
|
|
LONG WINAPI extRegCloseKey(HKEY hKey)
|
|
{
|
|
OutTraceR("RegCloseKey: hKey=%x\n", hKey);
|
|
if (IsFake(hKey)) return ERROR_SUCCESS;
|
|
return (*pRegCloseKey)(hKey);
|
|
}
|
|
|
|
LONG WINAPI extRegFlushKey(HKEY hKey)
|
|
{
|
|
OutTraceR("RegFlushKey: hKey=%x\n", hKey);
|
|
if (IsFake(hKey)) return ERROR_SUCCESS;
|
|
return (*pRegFlushKey)(hKey);
|
|
}
|
|
|
|
LONG WINAPI extRegSetValueEx(HKEY hKey, LPCTSTR lpValueName, DWORD Reserved, DWORD dwType, const BYTE *lpData, DWORD cbData)
|
|
{
|
|
if (IsTraceR){
|
|
char sInfo[1024];
|
|
sprintf(sInfo, "RegSetValueEx: hKey=%x ValueName=\"%s\" Type=%x(%s) cbData=%d", hKey, lpValueName, dwType, ExplainRegType(dwType), cbData);
|
|
switch(dwType){
|
|
case REG_DWORD: OutTrace("%s Data=%x\n", sInfo, *(DWORD *)lpData); break;
|
|
case REG_NONE: OutTrace("%s Data=\"%s\"\n", sInfo, lpData); break;
|
|
case REG_BINARY: OutTrace("%s Data=%s\n", sInfo, hexdump((BYTE *)lpData, cbData)); break;
|
|
case REG_SZ: OutTrace("%s Data=\"%*.*s\"\n", sInfo, cbData-1, cbData-1, lpData); break;
|
|
default: OutTrace("%s\n", sInfo);
|
|
}
|
|
}
|
|
if(IsFake(hKey) && (dxw.dwFlags3 & EMULATEREGISTRY)) {
|
|
OutTraceR("RegSetValueEx: SUPPRESS registry key set\n");
|
|
return ERROR_SUCCESS;
|
|
}
|
|
return (*pRegSetValueEx)(hKey, lpValueName, Reserved, dwType, lpData, cbData);
|
|
}
|
|
|
|
LONG WINAPI extRegCreateKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved, LPTSTR lpClass, DWORD dwOptions, REGSAM samDesired,
|
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition)
|
|
{
|
|
OutTraceR("RegCreateKeyEx: hKey=%x(%s) SubKey=\"%s\" Class=%x\n", hKey, hKey2String(hKey), lpSubKey, lpClass);
|
|
if (dxw.dwFlags3 & EMULATEREGISTRY){
|
|
*phkResult = HKEY_FAKE;
|
|
// V2.3.12: return existing fake key if any ....
|
|
if(dxw.dwFlags4 & OVERRIDEREGISTRY) myRegOpenKeyEx("RegCreateKeyEx", hKey, lpSubKey, phkResult);
|
|
if(lpdwDisposition) *lpdwDisposition=REG_OPENED_EXISTING_KEY;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
else
|
|
return (*pRegCreateKeyEx)(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired,
|
|
lpSecurityAttributes, phkResult, lpdwDisposition);
|
|
}
|
|
|
|
LONG WINAPI extRegCreateKey(HKEY hKey, LPCTSTR lpSubKey, PHKEY phkResult)
|
|
{
|
|
OutTraceR("RegCreateKey: hKey=%x(%s) SubKey=\"%s\"\n", hKey, hKey2String(hKey), lpSubKey);
|
|
if (dxw.dwFlags3 & EMULATEREGISTRY){
|
|
*phkResult = HKEY_FAKE;
|
|
// V2.3.12: return existing fake key if any ....
|
|
if(dxw.dwFlags4 & OVERRIDEREGISTRY) myRegOpenKeyEx("RegCreateKey", hKey, lpSubKey, phkResult);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
else
|
|
return (*pRegCreateKey)(hKey, lpSubKey, phkResult);
|
|
}
|
|
|
|
LONG WINAPI extRegEnumValueA(HKEY hKey, DWORD dwIndex, LPTSTR lpValueName, LPDWORD lpcchValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
|
|
{
|
|
LONG res;
|
|
|
|
OutTraceR("RegEnumValue: hKey=%x(\"%s\") index=%d cchValueName=%d Reserved=%x lpType=%x lpData=%x lpcbData=%x\n",
|
|
hKey, hKey2String(hKey), dwIndex, *lpcchValueName, lpReserved, lpType, lpData, lpcbData);
|
|
if (!IsFake(hKey)){
|
|
res=(*pRegEnumValueA)(hKey, dwIndex, lpValueName, lpcchValueName, lpReserved, lpType, lpData, lpcbData);
|
|
if(IsTraceR) LogKeyValue("RegQueryValueEx", res, lpType, lpData, lpcbData);
|
|
return res;
|
|
}
|
|
|
|
// try emulated registry
|
|
FILE *regf;
|
|
regf=OpenFakeRegistry();
|
|
if(regf==NULL) return ERROR_FILE_NOT_FOUND;
|
|
res = SeekFakeKey(regf, hKey);
|
|
if(res != ERROR_SUCCESS) return res;
|
|
res = SeekValueIndex(regf, dwIndex, lpValueName, lpcchValueName);
|
|
if(res != ERROR_SUCCESS) return res;
|
|
res = GetKeyValue(regf, "RegEnumValue", lpValueName, lpType, lpData, lpcbData);
|
|
if(IsTraceR) LogKeyValue("RegEnumValue", res, lpType, lpData, lpcbData);
|
|
fclose(regf);
|
|
return res;
|
|
}
|
|
|
|
#ifdef TOBEDONE
|
|
LONG WINAPI RegQueryInfoKey(
|
|
_In_ HKEY hKey,
|
|
_Out_opt_ LPTSTR lpClass,
|
|
_Inout_opt_ LPDWORD lpcClass,
|
|
_Reserved_ LPDWORD lpReserved,
|
|
_Out_opt_ LPDWORD lpcSubKeys,
|
|
_Out_opt_ LPDWORD lpcMaxSubKeyLen,
|
|
_Out_opt_ LPDWORD lpcMaxClassLen,
|
|
_Out_opt_ LPDWORD lpcValues,
|
|
_Out_opt_ LPDWORD lpcMaxValueNameLen,
|
|
_Out_opt_ LPDWORD lpcMaxValueLen,
|
|
_Out_opt_ LPDWORD lpcbSecurityDescriptor,
|
|
_Out_opt_ PFILETIME lpftLastWriteTime
|
|
);
|
|
#endif |