mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3312 lines
94 KiB
3312 lines
94 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Custom.cpp
|
|
|
|
Abstract:
|
|
|
|
Module to add custom behaviour to virtual registry.
|
|
|
|
Fixes:
|
|
|
|
VersionNumber string for Microsoft Playpack
|
|
Expanders for DevicePath, ProgramFilesPath and WallPaperDir
|
|
Redirectors for screen savers
|
|
Virtual HKEY_DYN_DATA structure
|
|
Add ProductName to all Network Cards
|
|
Locale has been moved
|
|
Wordpad filenames
|
|
NoDriveTypeAutorun has a different type
|
|
|
|
Notes:
|
|
|
|
This file should be used to add custom behavior to virtual registry.
|
|
|
|
History:
|
|
|
|
05/05/2000 linstev Created
|
|
09/01/2000 t-adams Added support for PCI devices to BuildDynData()
|
|
09/01/2000 robkenny Added Krondor
|
|
09/09/2000 robkenny Updated Wordpad to return a short path to the exe
|
|
09/21/2000 prashkud Added fix for SpellItDeluxe
|
|
10/25/2000 maonis Added CookieMaster
|
|
10/17/2000 robkenny Added HKEY_DYN_DATA\Display\Settings
|
|
11/27/2000 a-fwills Added display guid to redirectors
|
|
12/28/2000 a-brienw Added BuildTalkingDictionary for American Heritage
|
|
Talking Dictionary which is looking for a SharedDir key
|
|
01/15/2001 maonis Added PageKeepPro
|
|
02/06/2001 a-larrsh Added FileNet Web Server
|
|
02/27/2001 maonis Added PageMaker
|
|
02/27/2001 robkenny Converted to use tcs.h
|
|
03/01/2001 prashkud Added NetBT keys in BuildNetworkCards()
|
|
04/05/2001 mnikkel Added HKLM\Microsoft\Windows\CurrentVersion\App Paths\DXDIAG.EXE
|
|
04/27/2001 prashkud Added custom MiddleSchoolAdvantage 2001 entry
|
|
05/04/2001 prashkud Added custom entry for BOGUSCTRLID - Win2K layer
|
|
05/19/2001 hioh Added NOWROBLUE, BuildNowroBlue
|
|
06/13/2001 carlco Added Princeton ACT
|
|
08/10/2001 mikrause Added Airline Tycoon, DirectSound hacks.
|
|
11/06/2001 mikrause Added Delphi 5.0 Pro
|
|
01/02/2002 mamathas Added NortonAntiVirus2002, BuildNortonAntiVirus
|
|
04/23/2002 garyma Added Word Perfect Office 2002
|
|
|
|
--*/
|
|
|
|
#define SHIM_LIB_BUILD_FLAG
|
|
|
|
#include "precomp.h"
|
|
|
|
#include "secutils.h"
|
|
#include <stdio.h>
|
|
|
|
IMPLEMENT_SHIM_BEGIN(VirtualRegistry)
|
|
#include "ShimHookMacro.h"
|
|
#include "VRegistry.h"
|
|
#include "VRegistry_dsound.h"
|
|
|
|
//
|
|
// Functions that modify the behaviour of virtualregistry
|
|
//
|
|
|
|
void BuildWin98SE(char* szParam);
|
|
void BuildRedirectors(char* szParam);
|
|
void BuildCookiePath(char* szParam);
|
|
void BuildHasbro(char* szParam);
|
|
void BuildDynData(char* szParam);
|
|
void BuildCurrentConfig(char* szParam);
|
|
void BuildLocale(char* szParam);
|
|
void BuildWordPad(char* szParam);
|
|
void BuildAutoRun(char* szParam);
|
|
void BuildTalkingDictionary(char* szParam);
|
|
void BuildNetworkCards(char* szParam);
|
|
void BuildNT4SP5(char* szParam);
|
|
void BuildNT50(char* szParam);
|
|
void BuildNT51(char* szParam);
|
|
void BuildBogusCtrlID(char* szParam);
|
|
void BuildExpanders(char* szParam);
|
|
void BuildDX7A(char* szParam);
|
|
void BuildDXDiag(char* szParam);
|
|
void BuildFutureCop(char* szParam);
|
|
void BuildKrondor(char* szParam);
|
|
void BuildPageKeepProDirectory(char* szParam);
|
|
void BuildProfile(char* szParam);
|
|
void BuildSpellItDeluxe(char* szParam);
|
|
void BuildIE401(char* szParam);
|
|
void BuildIE55(char* szParam);
|
|
void BuildIE60(char* szParam);
|
|
void BuildJoystick(char* szParam);
|
|
void BuildIllustrator8(char* szParam);
|
|
void BuildModemWizard(char* szParam);
|
|
void BuildMSI(char* szParam);
|
|
void BuildFileNetWebServer(char* szParam);
|
|
void BuildPrinter(char* szParam);
|
|
void BuildPageMaker65(char* szParam);
|
|
void BuildStarTrekArmada(char* szParam);
|
|
void BuildMSA2001(char* szParam);
|
|
void BuildNowroBlue(char* szParam);
|
|
void BuildRegisteredOwner(char* szParam);
|
|
void BuildPrincetonACT(char* szParam);
|
|
void BuildHEDZ(char* szParam);
|
|
void BuildAirlineTycoon(char* szParam);
|
|
void BuildDSDevAccel(char* szParam);
|
|
void BuildDSPadCursors(char* szParam);
|
|
void BuildDSCachePositions(char* szParam);
|
|
void BuildDSReturnWritePos(char* szParam);
|
|
void BuildDSSmoothWritePos(char* szParam);
|
|
void BuildDSDisableDevice(char* szParam);
|
|
void BuildDelphi5Pro(char* szParam);
|
|
void BuildNortonAntiVirus(char* szParam);
|
|
void BuildWordPerfect2002(char* szParam);
|
|
|
|
|
|
// Table that contains all the fixes - note, must be terminated by a NULL entry.
|
|
|
|
VENTRY g_VList[] =
|
|
{
|
|
{L"WIN98SE", BuildWin98SE, eWin9x, FALSE, NULL },
|
|
{L"REDIRECT", BuildRedirectors, eWin9x, FALSE, NULL },
|
|
{L"COOKIEPATH", BuildCookiePath, eWin9x, FALSE, NULL },
|
|
{L"HASBRO", BuildHasbro, eWin9x, FALSE, NULL },
|
|
{L"DYN_DATA", BuildDynData, eWin9x, FALSE, NULL },
|
|
{L"CURRENT_CONFIG", BuildCurrentConfig, eWin9x, FALSE, NULL },
|
|
{L"LOCALE", BuildLocale, eWin9x, FALSE, NULL },
|
|
{L"WORDPAD", BuildWordPad, eWin9x, FALSE, NULL },
|
|
{L"AUTORUN", BuildAutoRun, eWin9x, FALSE, NULL },
|
|
{L"TALKINGDICTIONARY", BuildTalkingDictionary, eWin9x, FALSE, NULL },
|
|
{L"PRINTER", BuildPrinter, eWin9x, FALSE, NULL },
|
|
{L"REGISTEREDOWNER", BuildRegisteredOwner, eWin9x, FALSE, NULL },
|
|
{L"NETWORK_CARDS", BuildNetworkCards, eWinNT, FALSE, NULL },
|
|
{L"NT4SP5", BuildNT4SP5, eWinNT, FALSE, NULL },
|
|
{L"NT50", BuildNT50, eWin2K, FALSE, NULL },
|
|
{L"BOGUSCTRLID", BuildBogusCtrlID, eWin2K, FALSE, NULL },
|
|
{L"NT51", BuildNT51, eWinXP, FALSE, NULL },
|
|
{L"EXPAND", BuildExpanders, eCustom, FALSE, NULL },
|
|
{L"DX7A", BuildDX7A, eCustom, FALSE, NULL },
|
|
{L"DXDIAG", BuildDXDiag, eCustom, FALSE, NULL },
|
|
{L"FUTURECOP", BuildFutureCop, eCustom, FALSE, NULL },
|
|
{L"KRONDOR", BuildKrondor, eCustom, FALSE, NULL },
|
|
{L"PROFILE", BuildProfile, eCustom, FALSE, NULL },
|
|
{L"SPELLITDELUXE", BuildSpellItDeluxe, eCustom, FALSE, NULL },
|
|
{L"IE401", BuildIE401, eCustom, FALSE, NULL },
|
|
{L"IE55", BuildIE55, eCustom, FALSE, NULL },
|
|
{L"IE60", BuildIE60, eCustom, FALSE, NULL },
|
|
{L"JOYSTICK", BuildJoystick, eCustom, FALSE, NULL },
|
|
{L"ILLUSTRATOR8", BuildIllustrator8, eCustom, FALSE, NULL },
|
|
{L"PAGEKEEPPRO30", BuildPageKeepProDirectory, eCustom, FALSE, NULL },
|
|
{L"MODEMWIZARD", BuildModemWizard, eCustom, FALSE, NULL },
|
|
{L"MSI", BuildMSI, eCustom, FALSE, NULL },
|
|
{L"FILENETWEBSERVER", BuildFileNetWebServer, eCustom, FALSE, NULL },
|
|
{L"PAGEMAKER65", BuildPageMaker65, eCustom, FALSE, NULL },
|
|
{L"STARTREKARMADA", BuildStarTrekArmada, eCustom, FALSE, NULL },
|
|
{L"MSA2001", BuildMSA2001, eCustom, FALSE, NULL },
|
|
{L"NOWROBLUE", BuildNowroBlue, eCustom, FALSE, NULL },
|
|
{L"PRINCETONACT", BuildPrincetonACT, eCustom, FALSE, NULL },
|
|
{L"HEDZ", BuildHEDZ, eCustom, FALSE, NULL },
|
|
{L"AIRLINETYCOON", BuildAirlineTycoon, eCustom, FALSE, NULL },
|
|
{L"DSDEVACCEL", BuildDSDevAccel, eCustom, FALSE, NULL },
|
|
{L"DSPADCURSORS", BuildDSPadCursors, eCustom, FALSE, NULL },
|
|
{L"DSCACHEPOSITIONS", BuildDSCachePositions, eCustom, FALSE, NULL },
|
|
{L"DSRETURNWRITEPOS", BuildDSReturnWritePos, eCustom, FALSE, NULL },
|
|
{L"DSSMOOTHWRITEPOS", BuildDSSmoothWritePos, eCustom, FALSE, NULL },
|
|
{L"DSDISABLEDEVICE", BuildDSDisableDevice, eCustom, FALSE, NULL },
|
|
{L"DELPHI5PRO", BuildDelphi5Pro, eCustom, FALSE, NULL },
|
|
{L"NORTONANTIVIRUS", BuildNortonAntiVirus, eCustom, FALSE, NULL },
|
|
{L"WORDPERFECT2002", BuildWordPerfect2002, eCustom, FALSE, NULL },
|
|
// Must Be The Last Entry
|
|
{L"", NULL, eCustom, FALSE, NULL }
|
|
};
|
|
VENTRY *g_pVList = &g_VList[0];
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Add Win98 SE registry value - so far we only know about the Play Pack that
|
|
needs it.
|
|
|
|
History:
|
|
|
|
05/04/2000 linstev Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildWin98SE(char* /*szParam*/)
|
|
{
|
|
VIRTUALKEY *key;
|
|
|
|
// Add version number string for emulation of Win98 SE
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion");
|
|
if (key)
|
|
{
|
|
key->AddValue(L"VersionNumber", REG_SZ, (LPBYTE)L"4.10.2222");
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Known moved locations for which we need redirectors
|
|
|
|
History:
|
|
|
|
05/04/2000 linstev Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildRedirectors(char* /*szParam*/)
|
|
{
|
|
// Display property page add ons and controls have changed location.
|
|
VRegistry.AddRedirect(
|
|
L"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\Display",
|
|
L"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\Desk");
|
|
|
|
// this key moved somewhere around build 2200.
|
|
// System config scan type apps (ip.exe bundled in EA sports)
|
|
// starting failing again.
|
|
VRegistry.AddRedirect(
|
|
L"HKLM\\System\\CurrentControlSet\\Services\\Class",
|
|
L"HKLM\\System\\CurrentControlSet\\Control\\Class");
|
|
|
|
// Nightmare Ned wasn't finding display starting from Class.
|
|
// Directing it from Display to the GUID.
|
|
VRegistry.AddRedirect(
|
|
L"HKLM\\System\\CurrentControlSet\\Services\\Class\\Display",
|
|
L"HKLM\\System\\CurrentControlSet\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}");
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
CookieMaster gets the wrong path to cookies
|
|
because HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Cache\\Special Paths\\Cookies
|
|
contains bogus value (shell is going to fix this). We change this to the correct value %USERPROFILE%\Cookies.
|
|
|
|
History:
|
|
|
|
10/25/2000 maonis Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildCookiePath(char* /*szParam*/)
|
|
{
|
|
WCHAR wCookiePath[] = L"%USERPROFILE%\\Cookies";
|
|
|
|
VIRTUALKEY *key = VRegistry.AddKey(L"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Cache\\Special Paths\\Cookies");
|
|
if (key)
|
|
{
|
|
key->AddValue(L"Directory", REG_EXPAND_SZ, (LPBYTE)wCookiePath, 0);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
During the Slingo installation, the program places a value in the registry
|
|
called 'PALFILE'. When you run the app, it checks this value to determine
|
|
where the CD-ROM is located. For example, if the CD-ROM drive is 'E', it
|
|
should put 'E:\Slingo.pal'. It fails to do this correctly on Win2K or Whistler,
|
|
as it puts the install path instead. When the app runs, if the value doesn't
|
|
refer to 'x:\Slingo.pal (where x is the CD-ROM drive)', the app immediately
|
|
starts to do a FindFirstFile->FindNextFile looking for the file on the hard
|
|
drive. Eventually it AVs during the search with no error message. This code
|
|
sets the value in the registry on behalf of the app.
|
|
|
|
History:
|
|
|
|
11/1/2000 rparsons Created
|
|
|
|
--*/
|
|
|
|
LONG
|
|
WINAPI
|
|
VR_Hasbro(
|
|
OPENKEY *key,
|
|
VIRTUALKEY * /* vkey */,
|
|
VIRTUALVAL *vvalue
|
|
)
|
|
{
|
|
DWORD dwType;
|
|
WCHAR wszPath[MAX_PATH];
|
|
DWORD dwSize = sizeof(wszPath);
|
|
DWORD dwAttributes;
|
|
|
|
//
|
|
// Query the original value
|
|
//
|
|
|
|
LONG lRet = RegQueryValueExW(
|
|
key->hkOpen,
|
|
vvalue->wName,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)wszPath,
|
|
&dwSize);
|
|
|
|
//
|
|
// Query failed - something went wrong
|
|
//
|
|
|
|
if (FAILURE(lRet))
|
|
{
|
|
DPFN( eDbgLevelError, "[Hasbro hack] Failed to query %S for expansion", vvalue->wName);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Not a string type!
|
|
//
|
|
|
|
if ((dwType != REG_SZ) || (dwSize > sizeof(wszPath)))
|
|
{
|
|
DPFN( eDbgLevelError, "[Hasbro hack] Failed to query %S", vvalue->wName);
|
|
lRet = ERROR_BAD_ARGUMENTS;
|
|
goto Exit;
|
|
}
|
|
|
|
// Check what's there
|
|
dwAttributes = GetFileAttributes(wszPath);
|
|
|
|
// If it's not a file, or it's a directory, then we have to find it ourselves
|
|
if ((dwAttributes == (DWORD)-1) || (dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
WCHAR *lpDrives = L"";
|
|
DWORD dwBufferLen = 0;
|
|
|
|
//
|
|
// The plan is to run all the drives and find one with a .PAL file on
|
|
// it. We also have the restriction that it must be a CDRom. It has
|
|
// been pointed out that if the user has multiple CD drives and has
|
|
// different HasBro titles in each drive, we could cause a failure,
|
|
// but we're considering that a pathological case for now. Especially
|
|
// considering we have no way of knowing what the palfile name is ahead
|
|
// of time.
|
|
//
|
|
|
|
dwBufferLen = GetLogicalDriveStringsW(0, lpDrives);
|
|
if (dwBufferLen)
|
|
{
|
|
lpDrives = (WCHAR *) malloc((dwBufferLen + 1) * sizeof(WCHAR));
|
|
if (lpDrives)
|
|
{
|
|
GetLogicalDriveStrings(dwBufferLen, lpDrives);
|
|
|
|
WCHAR *lpCurrent = lpDrives;
|
|
while (lpCurrent && lpCurrent[0])
|
|
{
|
|
if (GetDriveTypeW(lpCurrent) == DRIVE_CDROM)
|
|
{
|
|
//
|
|
// We've found a CD drive, now see if it has a .PAL
|
|
// file on it.
|
|
//
|
|
|
|
WCHAR wszFile[MAX_PATH];
|
|
WIN32_FIND_DATAW ffData;
|
|
HANDLE hFindFile;
|
|
|
|
if (SUCCEEDED(StringCchCopyW(wszFile, MAX_PATH, lpCurrent)) &&
|
|
SUCCEEDED(StringCchCatW(wszFile, MAX_PATH, L"*.PAL")))
|
|
|
|
{
|
|
hFindFile = FindFirstFileW(wszFile, &ffData);
|
|
|
|
if (hFindFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
// A .PAL file exists, return that.
|
|
FindClose(hFindFile);
|
|
|
|
if (SUCCEEDED(StringCchCopyW(wszPath, MAX_PATH, lpCurrent)) &&
|
|
SUCCEEDED(StringCchCatW(wszPath, MAX_PATH, ffData.cFileName)))
|
|
{
|
|
|
|
LOGN( eDbgLevelInfo, "[Hasbro hack] Returning path %S", wszPath);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Advance to the next drive letter
|
|
lpCurrent += wcslen(lpCurrent) + 1;
|
|
}
|
|
|
|
free(lpDrives);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Copy the result into the output of QueryValue
|
|
|
|
vvalue->cbData = (wcslen(wszPath) + 1) * sizeof(WCHAR);
|
|
vvalue->lpData = (LPBYTE) malloc(vvalue->cbData);
|
|
|
|
if (!vvalue->lpData)
|
|
{
|
|
DPFN( eDbgLevelError, szOutOfMemory);
|
|
lRet = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
MoveMemory(vvalue->lpData, wszPath, vvalue->cbData);
|
|
|
|
//
|
|
// Never call us again, since we've done the work to set this value up and
|
|
// stored it in our virtual value
|
|
//
|
|
vvalue->pfnQueryValue = NULL;
|
|
|
|
lRet = ERROR_SUCCESS;
|
|
|
|
Exit:
|
|
return lRet;
|
|
}
|
|
|
|
void
|
|
BuildHasbro(char* /*szParam*/)
|
|
{
|
|
HKEY hHasbroKey;
|
|
WCHAR wszKeyName[MAX_PATH];
|
|
DWORD dwIndex;
|
|
|
|
const WCHAR wszHasbroPath[] = L"SOFTWARE\\Hasbro Interactive";
|
|
|
|
if (FAILURE(RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszHasbroPath, 0, KEY_READ, &hHasbroKey)))
|
|
{
|
|
DPFN( eDbgLevelSpew, "[Hasbro hack] Ignoring fix - no titles found");
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Enum the keys under Hasbro Interactive and add a virtual PALFILE value.
|
|
// Attach our callback to this value (see above)
|
|
//
|
|
|
|
dwIndex = 0;
|
|
|
|
while (SUCCESS(RegEnumKeyW(hHasbroKey, dwIndex, wszKeyName, MAX_PATH)))
|
|
{
|
|
WCHAR wszName[MAX_PATH] = L"HKLM\\";
|
|
|
|
if (SUCCEEDED(StringCchCatW(wszName, MAX_PATH, wszHasbroPath)) &&
|
|
SUCCEEDED(StringCchCatW(wszName, MAX_PATH, L"\\")) &&
|
|
SUCCEEDED(StringCchCatW(wszName, MAX_PATH, wszKeyName)))
|
|
{
|
|
VIRTUALKEY *key = VRegistry.AddKey(wszName);
|
|
if (key)
|
|
{
|
|
VIRTUALVAL *val = key->AddValue(L"PALFILE", REG_SZ, 0, 0);
|
|
if (val)
|
|
{
|
|
val->pfnQueryValue = VR_Hasbro;
|
|
}
|
|
|
|
DPFN( eDbgLevelInfo, "[Hasbro hack] Adding fix for %S", wszKeyName);
|
|
}
|
|
}
|
|
dwIndex++;
|
|
}
|
|
|
|
RegCloseKey(hHasbroKey);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
A simple DYN_DATA structure which emulates win9x.
|
|
|
|
History:
|
|
|
|
05/04/2000 linstev Created
|
|
09/01/2000 t-adams Added support for PCI devices so EA's 3dSetup.exe & others can
|
|
detect hardware.
|
|
|
|
--*/
|
|
|
|
#define ENUM_BASE 0xC29A28C0
|
|
|
|
void
|
|
BuildDynData(char* /*szParam*/)
|
|
{
|
|
VIRTUALKEY *key, *nkey;
|
|
HKEY hkPCI = 0;
|
|
DWORD i = 0;
|
|
DWORD dwNameLen = 0;
|
|
LPWSTR wstrName = NULL;
|
|
LPWSTR wstrVName = NULL;
|
|
FILETIME fileTime;
|
|
DWORD dwValue;
|
|
|
|
// Entries in HKDD\Config Manager\Enum were references to entries in HKLM\Enum\PCI that are now
|
|
// located at HKLM\SYSTEM\CurrentControlSet\Enum\PCI
|
|
VRegistry.AddRedirect(
|
|
L"HKLM\\Enum",
|
|
L"HKLM\\SYSTEM\\CurrentControlSet\\Enum");
|
|
|
|
// Construct HKDD\Config Manager\Enum so that it reflects the entries in HKLM\SYSTEM\CurrentControlSet\Enum\PCI
|
|
key = VRegistry.AddKey(L"HKDD\\Config Manager\\Enum");
|
|
if (!key)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
if (SUCCESS(RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Enum\\PCI",0, KEY_READ, &hkPCI)))
|
|
{
|
|
dwNameLen = MAX_PATH;
|
|
wstrName = (LPWSTR) malloc(dwNameLen * sizeof(WCHAR));
|
|
if (NULL == wstrName)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
wstrVName = (LPWSTR) malloc(dwNameLen * sizeof(WCHAR));
|
|
if (NULL == wstrName)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
i = 0;
|
|
while (ERROR_SUCCESS == RegEnumKeyExW(hkPCI, i, wstrName, &dwNameLen, NULL, NULL, NULL, &fileTime))
|
|
{
|
|
if (FAILED(StringCchPrintf(wstrVName, MAX_PATH, L"%x", ENUM_BASE+i)))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
nkey = key->AddKey(wstrVName);
|
|
if (!nkey) continue;
|
|
|
|
if (SUCCEEDED(StringCchCopy(wstrVName, MAX_PATH, L"PCI\\")) &&
|
|
SUCCEEDED(StringCchCat(wstrVName, MAX_PATH, wstrName)))
|
|
{
|
|
nkey->AddValue(L"HardWareKey", REG_SZ, (LPBYTE)wstrVName);
|
|
}
|
|
nkey->AddValueDWORD(L"Problem", 0);
|
|
|
|
dwNameLen = MAX_PATH;
|
|
++i;
|
|
}
|
|
}
|
|
|
|
key = VRegistry.AddKey(L"HKDD\\Config Manager\\Global");
|
|
|
|
key = VRegistry.AddKey(L"HKDD\\PerfStats");
|
|
|
|
key = VRegistry.AddKey(L"HKDD\\PerfStats\\StartSrv");
|
|
if (key)
|
|
{
|
|
dwValue = 0x0000001;
|
|
key->AddValue(L"KERNEL", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VFAT", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
}
|
|
|
|
key = VRegistry.AddKey(L"HKDD\\PerfStats\\StartStat");
|
|
if (key)
|
|
{
|
|
dwValue = 0x0000001;
|
|
key->AddValue(L"KERNEL\\CPUUsage", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"KERNEL\\Threads", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"KERNEL\\VMs", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
|
|
key->AddValue(L"VCACHE\\cCurPages", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\cMacPages", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\cMinPages", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\FailedRecycles", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\Hits", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\LRUBuffers", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\LRURecycles", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\Misses", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\RandomRecycles", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
|
|
key->AddValue(L"VFAT\\BReadsSec", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VFAT\\BWritesSec", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VFAT\\DirtyData", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VFAT\\ReadsSec", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VFAT\\WritesSec", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
|
|
key->AddValue(L"VMM\\cDiscards", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cInstanceFaults", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cPageFaults", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cPageIns", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cPageOuts", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgCommit", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgDiskcache", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgDiskcacheMac", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgDiskcacheMid", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgDiskcacheMin", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgFree", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgLocked", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgLockedNonCache", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgOther", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgSharedPages", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgSwap", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgSwapFile", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgSwapFileDefective", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgSwapFileInUse", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
}
|
|
|
|
key = VRegistry.AddKey(L"HKDD\\PerfStats\\StatData");
|
|
if (key)
|
|
{
|
|
dwValue = 0x0000001;
|
|
key->AddValue(L"KERNEL\\CPUUsage", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"KERNEL\\Threads", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"KERNEL\\VMs", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
|
|
key->AddValue(L"VCACHE\\cCurPages", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\cMacPages", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\cMinPages", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\FailedRecycles", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\Hits", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\LRUBuffers", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\LRURecycles", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\Misses", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\RandomRecycles", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
|
|
key->AddValue(L"VFAT\\BReadsSec", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VFAT\\BWritesSec", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VFAT\\DirtyData", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VFAT\\ReadsSec", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VFAT\\WritesSec", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
|
|
key->AddValue(L"VMM\\cDiscards", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cInstanceFaults", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cPageFaults", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cPageIns", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cPageOuts", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgCommit", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgDiskcache", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgDiskcacheMac", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgDiskcacheMid", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgDiskcacheMin", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgFree", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgLocked", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgLockedNonCache", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgOther", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgSharedPages", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgSwap", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgSwapFile", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgSwapFileDefective", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgSwapFileInUse", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
}
|
|
|
|
key = VRegistry.AddKey(L"HKDD\\PerfStats\\StopSrv");
|
|
if (key)
|
|
{
|
|
dwValue = 0x0000001;
|
|
key->AddValue(L"KERNEL", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VFAT", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
}
|
|
|
|
key = VRegistry.AddKey(L"HKDD\\PerfStats\\StopStat");
|
|
if (key)
|
|
{
|
|
dwValue = 0x0000001;
|
|
key->AddValue(L"KERNEL\\CPUUsage", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"KERNEL\\Threads", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"KERNEL\\VMs", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
|
|
key->AddValue(L"VCACHE\\cCurPages", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\cMacPages", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\cMinPages", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\FailedRecycles", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\Hits", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\LRUBuffers", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\LRURecycles", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\Misses", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VCACHE\\RandomRecycles", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
|
|
key->AddValue(L"VFAT\\BReadsSec", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VFAT\\BWritesSec", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VFAT\\DirtyData", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VFAT\\ReadsSec", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VFAT\\WritesSec", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
|
|
key->AddValue(L"VMM\\cDiscards", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cInstanceFaults", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cPageFaults", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cPageIns", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cPageOuts", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgCommit", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgDiskcache", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgDiskcacheMac", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgDiskcacheMid", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgDiskcacheMin", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgFree", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgLocked", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgLockedNonCache", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgOther", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgSharedPages", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgSwap", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgSwapFile", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgSwapFileDefective", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
key->AddValue(L"VMM\\cpgSwapFileInUse", REG_BINARY, (LPBYTE)&dwValue, 4);
|
|
}
|
|
|
|
exit:
|
|
if (NULL != wstrName)
|
|
{
|
|
free(wstrName);
|
|
}
|
|
|
|
if (NULL != wstrVName)
|
|
{
|
|
free(wstrVName);
|
|
}
|
|
|
|
if (0 != hkPCI)
|
|
{
|
|
RegCloseKey(hkPCI);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
DisplaySettings
|
|
|
|
History:
|
|
|
|
10/17/2000 robkenny Added HKEY_CURRENT_CONFIG
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildCurrentConfig(char* /*szParam*/)
|
|
{
|
|
DEVMODE devMode;
|
|
memset(&devMode, 0, sizeof(devMode));
|
|
devMode.dmSize = sizeof(devMode);
|
|
|
|
// Get the current display settings
|
|
BOOL bSuccessful = EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode);
|
|
if (bSuccessful)
|
|
{
|
|
// Create fake registry keys with dmPelsWidth, dmPelsHeight, dmPelsWidth and dmBitsPerPel
|
|
VIRTUALKEY *key = VRegistry.AddKey(L"HKCC\\Display\\Settings");
|
|
if (key)
|
|
{
|
|
WCHAR lpValue[100];
|
|
if (SUCCEEDED(StringCchPrintf(lpValue, 100, L"%d",devMode.dmBitsPerPel)))
|
|
{
|
|
key->AddValue(L"BitsPerPixel", REG_SZ, (LPBYTE)lpValue, 0);
|
|
}
|
|
|
|
if (SUCCEEDED(StringCchPrintf(lpValue, 100,L"%d,%d", devMode.dmPelsWidth, devMode.dmPelsHeight)))
|
|
{
|
|
key->AddValue(L"Resolution", REG_SZ, (LPBYTE)lpValue, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Redirect the current desktop fonts
|
|
VRegistry.AddRedirect(
|
|
L"HKCC\\Display\\Fonts",
|
|
L"HKCC\\Software\\Fonts");
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Make RegQueryValue return the value that's in the "(Default)" value, rather
|
|
than the NULL which is in there now. Not sure why the Locale key has this
|
|
difference.
|
|
|
|
History:
|
|
|
|
06/29/2000 linstev Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildLocale(char* /*szParam*/)
|
|
{
|
|
#define LOCALE_KEY HKEY_LOCAL_MACHINE
|
|
#define LOCALE_SUBKEY L"System\\CurrentControlSet\\Control\\Nls\\Locale"
|
|
|
|
HKEY hkBase;
|
|
|
|
if (FAILURE(RegOpenKeyExW(
|
|
LOCALE_KEY,
|
|
LOCALE_SUBKEY,
|
|
0,
|
|
KEY_READ,
|
|
&hkBase)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
WCHAR wValue[MAX_PATH];
|
|
DWORD dwSize = MAX_PATH * sizeof(WCHAR);
|
|
|
|
if (SUCCESS(RegQueryValueExW(hkBase, L"(Default)", 0, 0, (LPBYTE)wValue, &dwSize)))
|
|
{
|
|
LPWSTR wzPath;
|
|
VIRTUALKEY *localekey;
|
|
|
|
// Convert the KEY and SUBKEY into a path we can use for the vregistry
|
|
wzPath = MakePath(LOCALE_KEY, 0, LOCALE_SUBKEY);
|
|
if (wzPath)
|
|
{
|
|
localekey = VRegistry.AddKey(wzPath);
|
|
if (localekey)
|
|
{
|
|
localekey->AddValue(L"", REG_SZ, (LPBYTE)wValue);
|
|
}
|
|
free(wzPath);
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkBase);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
On NT, the strings in these values are of the form:
|
|
|
|
C:\Program Files\Windows NT\Accessories\WORDPAD.EXE "%1"
|
|
|
|
Note that the entire string is NOT quoted. On win9x, the string was:
|
|
|
|
C:\Windows\wordpad.exe "%1"
|
|
|
|
This causes problems when apps parse the NT version, because they hit the
|
|
space between Program and Files.
|
|
|
|
The fix is to return a shortened pathname to wordpad.exe
|
|
|
|
History:
|
|
|
|
05/04/2000 linstev Created
|
|
05/04/2000 robkenny Updated to return a correct short pathname to wordpad.exe
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildWordPad(char* /*szParam*/)
|
|
{
|
|
// Allocate memory so we don't use up lots of stack
|
|
WCHAR *lpwzWordpadOpen = (WCHAR *)malloc(MAX_PATH * sizeof(WCHAR));
|
|
WCHAR *lpwzWordpadPrint = (WCHAR *)malloc(MAX_PATH * sizeof(WCHAR));
|
|
WCHAR *lpwzWordpadPrintTo = (WCHAR *)malloc(MAX_PATH * sizeof(WCHAR));
|
|
|
|
WCHAR *lpwzWordpadLong = lpwzWordpadOpen; // borrow the buffer to save space
|
|
WCHAR *lpwzWordpadShort = (WCHAR *)malloc(MAX_PATH * sizeof(WCHAR));
|
|
|
|
DWORD lpType;
|
|
DWORD cbValue;
|
|
LONG result;
|
|
|
|
if (lpwzWordpadOpen == NULL ||
|
|
lpwzWordpadPrint == NULL ||
|
|
lpwzWordpadPrintTo == NULL ||
|
|
lpwzWordpadShort == NULL)
|
|
{
|
|
goto AllDone;
|
|
}
|
|
|
|
// Read the path to WORDPAD.EXE directly from the registry.
|
|
HKEY hKeyAppPaths;
|
|
result = RegOpenKeyExW(
|
|
HKEY_LOCAL_MACHINE,
|
|
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\WORDPAD.EXE",
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&hKeyAppPaths
|
|
);
|
|
|
|
if (result != ERROR_SUCCESS)
|
|
{
|
|
goto AllDone;
|
|
}
|
|
|
|
cbValue = MAX_PATH * sizeof(DWORD);
|
|
result = RegQueryValueExW(
|
|
hKeyAppPaths,
|
|
NULL, // default value
|
|
NULL,
|
|
&lpType,
|
|
(LPBYTE)lpwzWordpadLong,
|
|
&cbValue);
|
|
|
|
RegCloseKey(hKeyAppPaths);
|
|
if (result != ERROR_SUCCESS)
|
|
{
|
|
goto AllDone;
|
|
}
|
|
|
|
// turn bytes into string length (includes EOS)
|
|
DWORD cchValue = cbValue /sizeof(WCHAR);
|
|
|
|
if (lpType == REG_EXPAND_SZ)
|
|
{
|
|
WCHAR * lpwzWordpadExpand = lpwzWordpadPrintTo; // borrow the lpwzWordpadPrintTo buffer for a moment.
|
|
|
|
cchValue = ExpandEnvironmentStringsW(lpwzWordpadLong, lpwzWordpadExpand, MAX_PATH);
|
|
if (cchValue == 0 || cchValue > MAX_PATH )
|
|
goto AllDone;
|
|
|
|
lpwzWordpadLong = lpwzWordpadExpand;
|
|
}
|
|
|
|
// Rip off the trailing Quote
|
|
lpwzWordpadLong[cchValue-2] = 0;
|
|
lpwzWordpadLong += 1;
|
|
|
|
// Build the short path to wordpad
|
|
cchValue = GetShortPathNameW(lpwzWordpadLong, lpwzWordpadShort, MAX_PATH);
|
|
if (cchValue == 0 || cchValue > MAX_PATH)
|
|
{
|
|
goto AllDone;
|
|
}
|
|
|
|
if (FAILED(StringCchPrintf(lpwzWordpadOpen, MAX_PATH,L"%s \"%%1\"", lpwzWordpadShort)) ||
|
|
FAILED(StringCchPrintf(lpwzWordpadPrint, MAX_PATH, L"%s /p \"%%1\"",lpwzWordpadShort)) ||
|
|
FAILED(StringCchPrintf(lpwzWordpadPrintTo, MAX_PATH,L"%s /pt \"%%1\" \"%%2\" \"%%3\" \"%%4\"", lpwzWordpadShort)))
|
|
{
|
|
goto AllDone;
|
|
}
|
|
|
|
#define WORDPAD_OPEN ((LPBYTE)lpwzWordpadOpen)
|
|
#define WORDPAD_PRINT ((LPBYTE)lpwzWordpadPrint)
|
|
#define WORDPAD_PRINTTO ((LPBYTE)lpwzWordpadPrintTo)
|
|
|
|
VIRTUALKEY *key;
|
|
|
|
key = VRegistry.AddKey(L"HKCR\\rtffile\\shell\\open\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_OPEN);
|
|
key = VRegistry.AddKey(L"HKCR\\rtffile\\shell\\print\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_PRINT);
|
|
key = VRegistry.AddKey(L"HKCR\\rtffile\\shell\\printto\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_PRINTTO);
|
|
|
|
key = VRegistry.AddKey(L"HKCR\\Wordpad.Document.1\\shell\\open\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_OPEN);
|
|
key = VRegistry.AddKey(L"HKCR\\Wordpad.Document.1\\shell\\print\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_PRINT);
|
|
key = VRegistry.AddKey(L"HKCR\\Wordpad.Document.1\\shell\\printto\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_PRINTTO);
|
|
|
|
key = VRegistry.AddKey(L"HKCR\\wrifile\\shell\\open\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_OPEN);
|
|
key = VRegistry.AddKey(L"HKCR\\wrifile\\shell\\print\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_PRINT);
|
|
key = VRegistry.AddKey(L"HKCR\\wrifile\\shell\\printto\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_PRINTTO);
|
|
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Classes\\Applications\\wordpad.exe\\shell\\open\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_OPEN);
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Classes\\Applications\\wordpad.exe\\shell\\print\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_PRINT);
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Classes\\Applications\\wordpad.exe\\shell\\printto\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_PRINTTO);
|
|
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Classes\\rtffile\\shell\\open\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_OPEN);
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Classes\\rtffile\\shell\\print\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_PRINT);
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Classes\\rtffile\\shell\\printto\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_PRINTTO);
|
|
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Classes\\Wordpad.Document.1\\shell\\open\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_OPEN);
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Classes\\Wordpad.Document.1\\shell\\print\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_PRINT);
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Classes\\Wordpad.Document.1\\shell\\printto\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_PRINTTO);
|
|
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Classes\\wrifile\\shell\\open\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_OPEN);
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Classes\\wrifile\\shell\\print\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_PRINT);
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Classes\\wrifile\\shell\\printto\\command");
|
|
if (key) key->AddValue(0, REG_SZ, WORDPAD_PRINTTO);
|
|
|
|
AllDone:
|
|
free(lpwzWordpadOpen);
|
|
free(lpwzWordpadPrint);
|
|
free(lpwzWordpadPrintTo);
|
|
|
|
free(lpwzWordpadShort);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
This is a REG_BINARY on win9x
|
|
|
|
History:
|
|
|
|
07/18/2000 linstev Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildAutoRun(char* /*szParam*/)
|
|
{
|
|
#define AUTORUN_KEY HKEY_CURRENT_USER
|
|
#define AUTORUN_SUBKEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"
|
|
|
|
HKEY hkBase;
|
|
|
|
if (FAILURE(RegOpenKeyExW(
|
|
AUTORUN_KEY,
|
|
AUTORUN_SUBKEY,
|
|
0,
|
|
KEY_READ,
|
|
&hkBase)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
DWORD dwValue;
|
|
DWORD dwSize = sizeof(DWORD);
|
|
|
|
if (SUCCESS(RegQueryValueExW(hkBase, L"NoDriveTypeAutoRun", 0, 0, (LPBYTE)&dwValue, &dwSize)))
|
|
{
|
|
LPWSTR wzPath;
|
|
VIRTUALKEY *vkey;
|
|
|
|
// Convert the KEY and SUBKEY into a path we can use for the vregistry
|
|
wzPath = MakePath(AUTORUN_KEY, 0, AUTORUN_SUBKEY);
|
|
if (wzPath)
|
|
{
|
|
vkey = VRegistry.AddKey(wzPath);
|
|
if (vkey)
|
|
{
|
|
vkey->AddValue(L"NoDriveTypeAutoRun", REG_BINARY, (LPBYTE)&dwValue, sizeof(DWORD));
|
|
}
|
|
free(wzPath);
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkBase);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Add SharedDir value to HKLM\Software\Microsoft\Windows\CurrentVersion\Setup
|
|
The SharedDir in this case is just the windows directory (as it was on 9x).
|
|
|
|
History:
|
|
|
|
12/28/2000 a-brienw Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildTalkingDictionary(char* /*szParam*/)
|
|
{
|
|
VIRTUALKEY *key;
|
|
WCHAR szWindowsDir[MAX_PATH];
|
|
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Setup");
|
|
if (key)
|
|
{
|
|
DWORD cchSize = GetWindowsDirectoryW( (LPWSTR)szWindowsDir, MAX_PATH);
|
|
if (cchSize != 0 && cchSize <= MAX_PATH)
|
|
key->AddValue(L"SharedDir", REG_SZ, (LPBYTE)szWindowsDir);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Add a ProductName value to every network card description as on NT 4. The
|
|
product name in this case is just the first 8 characters of the
|
|
description.
|
|
|
|
History:
|
|
|
|
01/18/2000 linstev Created
|
|
03/01/2001 prashkud Added NetBT\Adapter key and the corresponding values
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildNetworkCards(char* /*szParam*/)
|
|
{
|
|
#define NETCARD_KEY HKEY_LOCAL_MACHINE
|
|
#define NETCARD_SUBKEY L"Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"
|
|
#define NETBT_SUBKEY L"System\\CurrentControlSet\\Services\\NetBT"
|
|
|
|
// For NetBT
|
|
LPWSTR wzNetBTPath;
|
|
WCHAR wAdapter[MAX_PATH];
|
|
VIRTUALKEY *vkAdapter = NULL;
|
|
HKEY hkNetBT;
|
|
|
|
if (FAILURE(RegOpenKeyExW(
|
|
NETCARD_KEY,
|
|
NETBT_SUBKEY,
|
|
0,
|
|
KEY_READ,
|
|
&hkNetBT)))
|
|
{
|
|
DPFN( eDbgLevelError, "Failed to add NetBT settings");
|
|
return;
|
|
}
|
|
|
|
if (FAILED(StringCchCopy(wAdapter, MAX_PATH, NETBT_SUBKEY)))
|
|
{
|
|
RegCloseKey(hkNetBT);
|
|
return;
|
|
}
|
|
if (FAILED(StringCchCat(wAdapter, MAX_PATH, L"\\Adapters")))
|
|
{
|
|
RegCloseKey(hkNetBT);
|
|
return;
|
|
}
|
|
|
|
// Make this a Virtual path
|
|
wzNetBTPath = MakePath(NETCARD_KEY, 0, wAdapter);
|
|
if (!wzNetBTPath)
|
|
{
|
|
DPFN( eDbgLevelError, "Failed to make NetBT path");
|
|
RegCloseKey(hkNetBT);
|
|
return;
|
|
}
|
|
|
|
// Adding the Adapters subkey to NetBT
|
|
vkAdapter = VRegistry.AddKey(wzNetBTPath);
|
|
free(wzNetBTPath);
|
|
|
|
HKEY hkBase;
|
|
|
|
// Check for network cards
|
|
if (FAILURE(RegOpenKeyExW(
|
|
NETCARD_KEY,
|
|
NETCARD_SUBKEY,
|
|
0,
|
|
KEY_READ,
|
|
&hkBase)))
|
|
{
|
|
DPFN( eDbgLevelError, "Failed to add Network card registry settings");
|
|
return;
|
|
}
|
|
|
|
LPWSTR wzPath;
|
|
VIRTUALKEY *netkey;
|
|
|
|
// Convert the KEY and SUBKEY into a path we can use for the vregistry
|
|
wzPath = MakePath(NETCARD_KEY, 0, NETCARD_SUBKEY);
|
|
netkey = wzPath ? VRegistry.AddKey(wzPath) : NULL;
|
|
|
|
if (wzPath && netkey)
|
|
{
|
|
// Enumerate the keys and add them to the virtual registry
|
|
DWORD dwIndex = 0;
|
|
WCHAR wName[MAX_PATH];
|
|
|
|
while (SUCCESS(RegEnumKeyW(
|
|
hkBase,
|
|
dwIndex,
|
|
wName,
|
|
MAX_PATH)))
|
|
{
|
|
HKEY hKey;
|
|
VIRTUALKEY *keyn;
|
|
WCHAR wTemp[MAX_PATH];
|
|
|
|
keyn = netkey->AddKey(wName);
|
|
|
|
if (!keyn)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (SUCCEEDED(StringCchCopy(wTemp, MAX_PATH, NETCARD_SUBKEY)) &&
|
|
SUCCEEDED(StringCchCat(wTemp, MAX_PATH, L"\\")) &&
|
|
SUCCEEDED(StringCchCat(wTemp, MAX_PATH,wName)))
|
|
|
|
{
|
|
// Open the actual key
|
|
if (SUCCESS(RegOpenKeyExW(
|
|
NETCARD_KEY,
|
|
wTemp,
|
|
0,
|
|
KEY_READ,
|
|
&hKey)))
|
|
{
|
|
WCHAR wDesc[MAX_PATH];
|
|
WCHAR wServName[MAX_PATH];
|
|
DWORD dwSize = MAX_PATH;
|
|
|
|
// check for description
|
|
if (SUCCESS(RegQueryValueExW(
|
|
hKey,
|
|
L"Description",
|
|
0,
|
|
0,
|
|
(LPBYTE)wDesc,
|
|
&dwSize)))
|
|
{
|
|
// Max out at 8 characters
|
|
wDesc[8] = L'\0';
|
|
keyn->AddValue(L"ProductName", REG_SZ, (LPBYTE)wDesc);
|
|
}
|
|
|
|
// Query for the ServiceName Value
|
|
dwSize = MAX_PATH;
|
|
if (SUCCESS(RegQueryValueExW(
|
|
hKey,
|
|
L"ServiceName",
|
|
0,
|
|
0,
|
|
(LPBYTE)wServName,
|
|
&dwSize)))
|
|
{
|
|
if (vkAdapter)
|
|
{
|
|
if (!vkAdapter->AddKey(wServName))
|
|
{
|
|
DPFN( eDbgLevelError, "Error adding the Key to NetBT");
|
|
}
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
dwIndex++;
|
|
}
|
|
}
|
|
|
|
free(wzPath);
|
|
|
|
RegCloseKey(hkBase);
|
|
RegCloseKey(hkNetBT);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Add NT4 SP5 Credentials.
|
|
|
|
History:
|
|
|
|
05/23/2000 linstev Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildNT4SP5(char* /*szParam*/)
|
|
{
|
|
VIRTUALKEY *key;
|
|
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion");
|
|
if (key)
|
|
{
|
|
key->AddValue(L"CSDVersion", REG_SZ, (LPBYTE)L"Service Pack 5");
|
|
}
|
|
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion");
|
|
if (key)
|
|
{
|
|
key->AddValue(L"CurrentVersion", REG_SZ, (LPBYTE)L"4.0");
|
|
}
|
|
|
|
key = VRegistry.AddKey(L"HKLM\\System\\CurrentControlSet\\Control\\Windows");
|
|
if (key)
|
|
{
|
|
key->AddValueDWORD(L"CSDVersion", 0x0500);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Add Win2k version number
|
|
|
|
History:
|
|
|
|
05/22/2001 linstev Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildNT50(char* /*szParam*/)
|
|
{
|
|
VIRTUALKEY *key;
|
|
|
|
// Add Win2k version number
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion");
|
|
if (key)
|
|
{
|
|
key->AddValue(L"CurrentVersion", REG_SZ, (LPBYTE)L"5.0");
|
|
key->AddValue(L"ProductName", REG_SZ, (LPBYTE)L"Microsoft Windows 2000");
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Add WinXP version number
|
|
|
|
History:
|
|
|
|
05/01/2002 linstev Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildNT51(char* /*szParam*/)
|
|
{
|
|
VIRTUALKEY *key;
|
|
|
|
// Add Win2k version number
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion");
|
|
if (key)
|
|
{
|
|
key->AddValue(L"CurrentVersion", REG_SZ, (LPBYTE)L"5.1");
|
|
key->AddValue(L"ProductName", REG_SZ, (LPBYTE)L"Microsoft Windows XP");
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
This function adds the Shell compatibility flag for apps that need the
|
|
bogus Ctrl ID of IDOK for ToolBarWindows32 class.
|
|
|
|
This also gets applied through the Win2K layer as this is a regression from
|
|
Win2K.
|
|
|
|
History:
|
|
|
|
05/04/2001 prashkud Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildBogusCtrlID(char* /*szParam*/)
|
|
{
|
|
CSTRING_TRY
|
|
{
|
|
WCHAR wszFileName[MAX_PATH];
|
|
CString csFileName, csFileTitle;
|
|
CString csRegPath(L"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Applications");
|
|
VIRTUALKEY *Key;
|
|
|
|
if (GetModuleFileName(NULL, wszFileName, MAX_PATH))
|
|
{
|
|
csFileName = wszFileName;
|
|
csFileName.GetLastPathComponent(csFileTitle);
|
|
csRegPath.AppendPath(csFileTitle);
|
|
|
|
Key = VRegistry.AddKey(csRegPath.Get());
|
|
if (Key)
|
|
{
|
|
Key->AddValue(L"FILEOPENBOGUSCTRLID", REG_SZ, 0, 0);
|
|
LOGN(eDbgLevelInfo, "Added FILEOPENBOGUSCTRLID value for app %S", csFileTitle.Get());
|
|
}
|
|
}
|
|
}
|
|
CSTRING_CATCH
|
|
{
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Known different values from Win9x.
|
|
|
|
History:
|
|
|
|
05/04/2000 linstev Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildExpanders(char* /*szParam*/)
|
|
{
|
|
VIRTUALKEY *key;
|
|
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion");
|
|
if (key)
|
|
{
|
|
// These are REG_EXPAND_SZ on NT and REG_SZ on Win9x
|
|
key->AddExpander(L"DevicePath");
|
|
key->AddExpander(L"ProgramFilesPath");
|
|
key->AddExpander(L"WallPaperDir");
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Add DX7a Credentials.
|
|
|
|
History:
|
|
|
|
05/23/2000 linstev Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildDX7A(char* /*szParam*/)
|
|
{
|
|
VIRTUALKEY *key;
|
|
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Microsoft\\DirectX");
|
|
if (key)
|
|
{
|
|
key->AddValue(L"Version", REG_SZ, (LPBYTE)L"4.07.00.0716");
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Add DXDIAG path.
|
|
|
|
History:
|
|
|
|
04/05/2001 mnikkel Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildDXDiag(char* /*szParam*/)
|
|
{
|
|
VIRTUALKEY *key;
|
|
WCHAR wszPathDir[MAX_PATH];
|
|
DWORD cchSize = GetSystemDirectoryW(wszPathDir, MAX_PATH);
|
|
|
|
if (cchSize == 0 || cchSize > MAX_PATH)
|
|
{
|
|
DPFN( eDbgLevelError, "BuildDXDiag: GetSystemDirectory Failed");
|
|
return;
|
|
}
|
|
|
|
if (FAILED(StringCchCat(wszPathDir, MAX_PATH, L"\\dxdiag.exe")))
|
|
{
|
|
return;
|
|
}
|
|
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\DXDIAG.EXE");
|
|
if (key)
|
|
{
|
|
key->AddValue(L"", REG_EXPAND_SZ, (LPBYTE)wszPathDir, 0);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Add FullScreen == 1 to fix bug in Future Cop that makes it not always run
|
|
in fullscreen mode.
|
|
|
|
History:
|
|
|
|
09/01/2000 linstev Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildFutureCop(char* /*szParam*/)
|
|
{
|
|
VIRTUALKEY *key;
|
|
|
|
key = VRegistry.AddKey(L"HKLM\\Software\\Electronic Arts\\Future Cop\\Settings");
|
|
if (key)
|
|
{
|
|
key->AddValueDWORD(L"FullScreen", 0x01);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Return to Krondor attempts to find ACM drivers, this key was moved and renamed.
|
|
Was: HKLM\System\CurrentControlSet\Control\MediaResources\ACM\MSACM.MSADPCM\drivers = msadp32.acm
|
|
Is: HKLM\Software\Microsoft\Windows NT\CurrentVersion\Drivers32\Msacm.Msadpcm = msadp32.acm
|
|
Grab the current value from the registry, and build a virtual key and value
|
|
|
|
History:
|
|
|
|
09/06/2000 robkenny Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildKrondor(char* /*szParam*/)
|
|
{
|
|
HKEY msadpcmKey;
|
|
LONG error = RegOpenKeyExW(
|
|
HKEY_LOCAL_MACHINE,
|
|
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32",
|
|
0, KEY_READ, &msadpcmKey);
|
|
|
|
if (SUCCESS(error))
|
|
{
|
|
// Found the key, grab the name of the driver
|
|
WCHAR driverName[MAX_PATH];
|
|
DWORD driverNameSize = sizeof(driverName);
|
|
DWORD driverNameType = REG_SZ;
|
|
|
|
error = RegQueryValueExW(
|
|
msadpcmKey,
|
|
L"MSACM.MSADPCM",
|
|
0, &driverNameType,
|
|
(LPBYTE)driverName,
|
|
&driverNameSize);
|
|
|
|
if (SUCCESS(error))
|
|
{
|
|
// We got all the data, so we can now add the virtual key and value
|
|
VIRTUALKEY *key = VRegistry.AddKey(L"HKLM\\System\\CurrentControlSet\\Control\\MediaResources\\ACM\\MSACM.MSADPCM");
|
|
if (key)
|
|
{
|
|
key->AddValue(L"driver", REG_SZ, (LPBYTE)driverName, 0);
|
|
}
|
|
}
|
|
|
|
RegCloseKey(msadpcmKey);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Redirect changes from CURRENT_USER to LOCAL_MACHINE.
|
|
|
|
History:
|
|
|
|
09/17/2000 linstev Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildProfile(char* /*szParam*/)
|
|
{
|
|
VRegistry.AddRedirect(
|
|
L"HKCU\\Software\\Microsoft\\Windows",
|
|
L"HKLM\\Software\\Microsoft\\Windows");
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
In Spell it Deluxe setup, the path for the SpeechFonts DLL ECN_1K8.DLL is
|
|
hardcoded to " C:\Voices32". If the installation is on a D: partition, the
|
|
LoadLibraryA( ) call fails and the App AV's.
|
|
Now the current partition drive will be taken and added to the path.
|
|
|
|
History:
|
|
|
|
09/21/2000 prashkud Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildSpellItDeluxe(char* /*szParam*/)
|
|
{
|
|
HKEY hSpeechFonts;
|
|
WCHAR wszSystemDir[MAX_PATH], wszPathDir[MAX_PATH];
|
|
|
|
if (GetSystemDirectory(wszSystemDir, MAX_PATH))
|
|
{
|
|
*(wszSystemDir+3) = L'\0';
|
|
}
|
|
else
|
|
{
|
|
DPFN( eDbgLevelError, "SpellIt: GetSystemDirectory Failed");
|
|
return;
|
|
}
|
|
|
|
|
|
if (FAILED(StringCchCopy(wszPathDir, MAX_PATH, wszSystemDir)))
|
|
{
|
|
return;
|
|
}
|
|
if (FAILED(StringCchCat(wszPathDir, MAX_PATH, L"Voices32")))
|
|
{
|
|
return;
|
|
}
|
|
|
|
LONG error = RegOpenKeyExW(
|
|
HKEY_LOCAL_MACHINE,
|
|
L"Software\\FirstByte\\ProVoice\\SpeechFonts",
|
|
0, KEY_READ | KEY_WRITE, &hSpeechFonts);
|
|
|
|
if (SUCCESS(error))
|
|
{
|
|
if (FAILED(RegSetValueExW(
|
|
hSpeechFonts,
|
|
L"Path",
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE) wszPathDir,
|
|
wcslen(wszPathDir) * sizeof(WCHAR))))
|
|
{
|
|
DPFN( eDbgLevelError, "SpellIt: RegSetValueEx failed");
|
|
}
|
|
|
|
RegCloseKey(hSpeechFonts);
|
|
}
|
|
else
|
|
{
|
|
DPFN( eDbgLevelError, "SpellIt: RegOpenKeyExW failed");
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Some applications need internet explorer for their functionality. The
|
|
applications try get the version of the internet explorer from the following
|
|
registry key : HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion. But
|
|
under WHISTLER environment, the key entry will not be created. So, the apps
|
|
fail to continue.
|
|
|
|
The app looks for the version info of the Internet Explorer in the registry
|
|
at HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion from the "Plus!
|
|
VersionNumber" Key. In WHISTLER the key will not be created in the registry.
|
|
|
|
To solve the problem we use Virtual Registry Keys. So, the app will assume
|
|
the key is existing in the registry.
|
|
|
|
WHISTLER, by default, will install I.E.6. So, I have created the key as
|
|
"IE 6 6.0.2404.0000" and this is the latest version of I.E. on WHISTLER as
|
|
on today.(11/22/2000).
|
|
|
|
History:
|
|
|
|
11/22/2000 v-rbabu Created
|
|
07/03/2001 linstev Added IE 5.5 from Win2k
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildIE401(char* /*szParam*/)
|
|
{
|
|
|
|
VIRTUALKEY *key = VRegistry.AddKey(L"HKLM\\Software\\Microsoft\\Internet Explorer");
|
|
if (key)
|
|
{
|
|
key->AddValue(L"Version", REG_SZ, (LPBYTE)L"4.72.2106.9", 0);
|
|
}
|
|
}
|
|
|
|
void
|
|
BuildIE55(char* /*szParam*/)
|
|
{
|
|
|
|
VIRTUALKEY *key = VRegistry.AddKey(L"HKLM\\Software\\Microsoft\\Internet Explorer");
|
|
if (key)
|
|
{
|
|
key->AddValue(L"Version", REG_SZ, (LPBYTE)L"5.50.4522.1800", 0);
|
|
}
|
|
}
|
|
|
|
void
|
|
BuildIE60(char* /*szParam*/)
|
|
{
|
|
WCHAR wIE[] = L"IE 6 6.0.2404.0000";
|
|
|
|
// Now add the virtual key and value
|
|
VIRTUALKEY *key = VRegistry.AddKey(L"HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion");
|
|
if (key)
|
|
{
|
|
key->AddValue(L"Plus! VersionNumber", REG_SZ, (LPBYTE)wIE, 0);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
The idea here is to fix apps that depend on short names for input devices.
|
|
We just trim the name to 32 characters (including terminator).
|
|
|
|
History:
|
|
|
|
12/06/2000 linstev Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildJoystick(char* /*szParam*/)
|
|
{
|
|
HKEY hJoystickKey;
|
|
WCHAR wszKeyName[MAX_PATH];
|
|
DWORD dwIndex;
|
|
|
|
const WCHAR wszJoystickPath[] = L"System\\CurrentControlSet\\Control\\MediaProperties\\PrivateProperties\\Joystick\\OEM";
|
|
|
|
if (FAILURE(RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszJoystickPath, 0, KEY_READ, &hJoystickKey)))
|
|
{
|
|
DPFN( eDbgLevelSpew, "[Joystick hack] No joysticks found");
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Enum the keys under Joystick and make virtual entries
|
|
//
|
|
|
|
dwIndex = 0;
|
|
|
|
while (SUCCESS(RegEnumKeyW(hJoystickKey, dwIndex, wszKeyName, MAX_PATH)))
|
|
{
|
|
WCHAR wszID[MAX_PATH] = L"HKLM\\";
|
|
if (SUCCEEDED(StringCchCat(wszID, MAX_PATH, wszJoystickPath)) &&
|
|
SUCCEEDED(StringCchCat(wszID, MAX_PATH, L"\\")) &&
|
|
SUCCEEDED(StringCchCat(wszID, MAX_PATH, wszKeyName)))
|
|
{
|
|
HKEY hkOEM;
|
|
if (SUCCESS(RegOpenKeyExW(hJoystickKey, wszKeyName, 0, KEY_READ, &hkOEM)))
|
|
{
|
|
WCHAR wszName[MAX_PATH + 1];
|
|
DWORD dwSize = MAX_PATH * sizeof(WCHAR);
|
|
if (SUCCESS(RegQueryValueExW(hkOEM, L"OEMName", 0, NULL, (LPBYTE) wszName, &dwSize)))
|
|
{
|
|
if (dwSize > 31 * sizeof(WCHAR))
|
|
{
|
|
VIRTUALKEY *key = VRegistry.AddKey(wszID);
|
|
if (key)
|
|
{
|
|
dwSize = 31 * sizeof(WCHAR);
|
|
wszName[31] = L'\0';
|
|
key->AddValue(L"OEMName", REG_SZ, (LPBYTE) wszName);
|
|
}
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkOEM);
|
|
}
|
|
}
|
|
|
|
dwIndex++;
|
|
}
|
|
|
|
RegCloseKey(hJoystickKey);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Hack for Adobe Illustrator 8
|
|
|
|
History:
|
|
|
|
12/18/2000 linstev Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildIllustrator8(char* /*szParam*/)
|
|
{
|
|
if (ShouldApplyShim())
|
|
{
|
|
// Redirect everything
|
|
VRegistry.AddRedirect(
|
|
L"HKLM\\Software\\Adobe",
|
|
L"HKCU\\Software\\Adobe");
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Hack for Adobe PageMaker 6.5
|
|
|
|
History:
|
|
|
|
02/27/2001 maonis Created
|
|
|
|
--*/
|
|
|
|
void BuildPageMaker65(char* /*szParam*/)
|
|
{
|
|
if (ShouldApplyShim())
|
|
{
|
|
VRegistry.AddRedirect(
|
|
L"HKCU\\Software\\Adobe\\PageMaker65",
|
|
L"HKLM\\Software\\Adobe\\PageMaker65");
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Hack for PageKeepPro30.
|
|
|
|
History:
|
|
|
|
01/15/2000 maonis Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildPageKeepProDirectory(char* /*szParam*/)
|
|
{
|
|
// We cannot call ShGetSpecialFolderPath since we are still in our DLL main,
|
|
// so we get the path to "My Documents" directly from the registry.
|
|
HKEY hkFolders;
|
|
if (SUCCESS(RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_READ, &hkFolders)))
|
|
{
|
|
DWORD dwType;
|
|
WCHAR wszPath[MAX_PATH];
|
|
DWORD dwSize = MAX_PATH*sizeof(WCHAR);
|
|
|
|
if (SUCCESS(RegQueryValueExW( hkFolders, L"Personal", NULL, &dwType, (LPBYTE)wszPath, &dwSize)))
|
|
{
|
|
VIRTUALKEY *key = VRegistry.AddKey(L"HKCU\\Software\\Caere Corp\\PageKeepPro30\\Preference");
|
|
if (key)
|
|
{
|
|
key->AddValue(L"Directory", REG_EXPAND_SZ, (LPBYTE)wszPath, 0);
|
|
}
|
|
}
|
|
RegCloseKey(hkFolders);
|
|
}
|
|
|
|
// Secondly, since we don't support using UI-less mode for TWAIN layer
|
|
// we mandatorily set BASICMODE for scanners to 2 instead of 0 - 2 means
|
|
// to always use UI mode.
|
|
HKEY hkScanners;
|
|
WCHAR wszKeyName[MAX_PATH] = L"";
|
|
DWORD dwIndex;
|
|
|
|
const WCHAR wszScanner[] = L"Software\\Caere Corp\\Scan Manager\\4.02\\Scanners";
|
|
|
|
if (FAILURE(RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszScanner,0, KEY_READ, &hkScanners)))
|
|
{
|
|
DPFN( eDbgLevelSpew, "[PageKeepPro 3.0] No scanner found");
|
|
return;
|
|
}
|
|
|
|
dwIndex = 0;
|
|
|
|
while (SUCCESS(RegEnumKeyW(hkScanners, dwIndex, wszKeyName, MAX_PATH)))
|
|
{
|
|
WCHAR wszID[MAX_PATH] = L"HKLM\\";
|
|
|
|
if (SUCCEEDED(StringCchCat(wszID, MAX_PATH,wszScanner)) &&
|
|
SUCCEEDED(StringCchCat(wszID, MAX_PATH,L"\\")) &&
|
|
SUCCEEDED(StringCchCat(wszID, MAX_PATH,wszKeyName)))
|
|
{
|
|
HKEY hkScanner;
|
|
if (SUCCESS(RegOpenKeyExW(hkScanners, wszKeyName, 0, KEY_READ, &hkScanner)))
|
|
{
|
|
VIRTUALKEY *keyMode = VRegistry.AddKey(wszID);
|
|
if (keyMode)
|
|
{
|
|
keyMode->AddValueDWORD(L"BASICMODE", 2);
|
|
}
|
|
|
|
RegCloseKey(hkScanner);
|
|
}
|
|
}
|
|
|
|
dwIndex++;
|
|
}
|
|
|
|
RegCloseKey(hkScanners);
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Hack for ModemWizard because the keys moved
|
|
|
|
History:
|
|
|
|
01/18/2001 linstev & a-leelat Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildModemWizard(char* /*szParam*/)
|
|
{
|
|
// Redirect everything
|
|
VRegistry.AddRedirect(
|
|
L"HKLM\\SYSTEM\\CurrentControlSet\\Enum\\Root",
|
|
L"HKLM\\SYSTEM\\CurrentControlSet\\Enum");
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Hack for Office2000 Developer 1.5 which looks in the wrong place for
|
|
components.
|
|
|
|
From ChetanP:
|
|
|
|
Basically the redirect code would have to do something like this -
|
|
|
|
if HKLM\Software\Microsoft\Windows\CurrentVersion\Installer\UserData\<user sid>\Components\359E92CC2CB71D119A12000A9CE1A22A
|
|
exists, redirect to that location
|
|
else if HKLM\Software\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\359E92CC2CB71D119A12000A9CE1A22A
|
|
exists, redirect to that location
|
|
else, no redirection.
|
|
|
|
Whistler Bug #241596
|
|
|
|
History:
|
|
|
|
02/01/2001 linstev Created
|
|
|
|
--*/
|
|
|
|
#define SIZE_OF_TOKEN_INFORMATION \
|
|
sizeof(TOKEN_USER) + \
|
|
sizeof(SID) + \
|
|
sizeof(ULONG) * SID_MAX_SUB_AUTHORITIES
|
|
|
|
#define SIZE_OF_SID_MAX \
|
|
sizeof(SID) + \
|
|
SID_MAX_SUB_AUTHORITIES * sizeof(DWORD)
|
|
|
|
#define cchMaxSID 256
|
|
|
|
//
|
|
// Get the current SID as text
|
|
//
|
|
|
|
BOOL
|
|
GetStringSID(
|
|
WCHAR *szSID
|
|
)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
HANDLE hToken = NULL;
|
|
int i;
|
|
PISID pISID;
|
|
UCHAR rgSID[SIZE_OF_SID_MAX];
|
|
UCHAR TokenInformation[SIZE_OF_TOKEN_INFORMATION];
|
|
ULONG ReturnLength;
|
|
WCHAR Buffer[cchMaxSID];
|
|
|
|
//
|
|
// Get a token
|
|
//
|
|
|
|
if (!OpenThreadToken(
|
|
GetCurrentThread(),
|
|
TOKEN_IMPERSONATE | TOKEN_QUERY,
|
|
TRUE,
|
|
&hToken))
|
|
{
|
|
if (GetLastError() == ERROR_NO_TOKEN)
|
|
{
|
|
bRet = OpenProcessToken(
|
|
GetCurrentProcess(),
|
|
TOKEN_IMPERSONATE | TOKEN_QUERY,
|
|
&hToken);
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
|
|
if (!bRet)
|
|
{
|
|
DPFN( eDbgLevelError, "[GetStringSID] Failed to OpenProcessToken");
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Get the binary form of the token
|
|
//
|
|
|
|
bRet = GetTokenInformation(
|
|
hToken,
|
|
TokenUser,
|
|
TokenInformation,
|
|
sizeof(TokenInformation),
|
|
&ReturnLength);
|
|
|
|
if (bRet)
|
|
{
|
|
bRet = FALSE;
|
|
pISID = (PISID)((PTOKEN_USER) TokenInformation)->User.Sid;
|
|
|
|
if (!CopySid(SIZE_OF_SID_MAX, rgSID, pISID))
|
|
{
|
|
DPFN( eDbgLevelError, "CopySID failed");
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Get the text form of the token
|
|
//
|
|
|
|
HRESULT hr = StringCchPrintf(Buffer, cchMaxSID,L"S-%u-", (USHORT) pISID->Revision);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
hr = StringCchCopy(szSID, 1024, Buffer);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if ((pISID->IdentifierAuthority.Value[0] != 0) ||
|
|
(pISID->IdentifierAuthority.Value[1] != 0))
|
|
{
|
|
hr = StringCchPrintf(Buffer, cchMaxSID,
|
|
L"0x%02hx%02hx%02hx%02hx%02hx%02hx",
|
|
(USHORT) pISID->IdentifierAuthority.Value[0],
|
|
(USHORT) pISID->IdentifierAuthority.Value[1],
|
|
(USHORT) pISID->IdentifierAuthority.Value[2],
|
|
(USHORT) pISID->IdentifierAuthority.Value[3],
|
|
(USHORT) pISID->IdentifierAuthority.Value[4],
|
|
(USHORT) pISID->IdentifierAuthority.Value[5]);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
hr = StringCchCat(szSID, 1024, Buffer);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ULONG Tmp =
|
|
(ULONG) pISID->IdentifierAuthority.Value[5] +
|
|
(ULONG)(pISID->IdentifierAuthority.Value[4] << 8) +
|
|
(ULONG)(pISID->IdentifierAuthority.Value[3] << 16) +
|
|
(ULONG)(pISID->IdentifierAuthority.Value[2] << 24);
|
|
|
|
hr = StringCchPrintf(Buffer, cchMaxSID, L"%lu", Tmp);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
hr = StringCchCat(szSID, 1024, Buffer);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
for (i=0; i < pISID->SubAuthorityCount; i++)
|
|
{
|
|
hr = StringCchPrintf(Buffer, cchMaxSID, L"-%lu", pISID->SubAuthority[i]);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
hr = StringCchCat(szSID, 1024, Buffer);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPFN( eDbgLevelError, "GetTokenInformation failed");
|
|
goto Exit;
|
|
}
|
|
|
|
bRet = TRUE;
|
|
Exit:
|
|
if (hToken)
|
|
{
|
|
CloseHandle(hToken);
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
void
|
|
BuildMSI(char* /*szParam*/)
|
|
{
|
|
WCHAR szSID[1024];
|
|
|
|
// Get the current users SID as a string
|
|
if (!GetStringSID(szSID))
|
|
{
|
|
DPFN( eDbgLevelError, "BuildMSI Failed");
|
|
return;
|
|
}
|
|
|
|
HKEY hKey;
|
|
WCHAR szTemp[1024];
|
|
|
|
const WCHAR szBase[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\";
|
|
const WCHAR szComp[] = L"\\Components\\359E92CC2CB71D119A12000A9CE1A22A";
|
|
|
|
HRESULT hr;
|
|
hr = StringCchCopy(szTemp, 1024, szBase);
|
|
if (FAILED(hr))
|
|
{
|
|
return;
|
|
}
|
|
hr = StringCchCat(szTemp, 1024, szSID);
|
|
if (FAILED(hr))
|
|
{
|
|
return;
|
|
}
|
|
hr = StringCchCat(szTemp, 1024, szComp);
|
|
if (FAILED(hr))
|
|
{
|
|
return;
|
|
}
|
|
// Attempt to open szBase + <user sid> + szComp
|
|
if (RegOpenKeyW(HKEY_LOCAL_MACHINE, szTemp, &hKey) != ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hKey);
|
|
|
|
// Attempt to open szBase + S-1-5-18 + szComp
|
|
hr = StringCchCopy(szTemp, 1024, szBase);
|
|
if (FAILED(hr))
|
|
{
|
|
return;
|
|
}
|
|
hr = StringCchCat(szTemp, 1024, L"S-1-5-18");
|
|
if (FAILED(hr))
|
|
{
|
|
return;
|
|
}
|
|
hr = StringCchCat(szTemp, 1024, szComp);
|
|
if (FAILED(hr))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (RegOpenKeyW(HKEY_LOCAL_MACHINE, szTemp, &hKey) != ERROR_SUCCESS)
|
|
{
|
|
DPFN( eDbgLevelError, "BuildMSI Failed to find keys");
|
|
RegCloseKey(hKey);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Redirect as appropriate
|
|
WCHAR szTarget[1024] = L"HKLM\\";
|
|
hr = StringCchCat(szTarget,1024, szTemp);
|
|
if (FAILED(hr))
|
|
{
|
|
return;
|
|
}
|
|
VRegistry.AddRedirect(
|
|
L"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\Components\\359E92CC2CB71D119A12000A9CE1A22A",
|
|
szTarget);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Added FileNet Web Server
|
|
|
|
History:
|
|
|
|
02/06/2001 a-larrsh Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildFileNetWebServer(char* /*szParam*/)
|
|
{
|
|
VIRTUALKEY *key;
|
|
|
|
key = VRegistry.AddKey(L"HKLM\\System\\CurrentControlSet\\Services\\W3SVC\\Parameters");
|
|
if (key)
|
|
{
|
|
key->AddValueDWORD(L"MajorVersion", 0x00000005);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Added default printer key. We have to effectively delay load this, because
|
|
we can't be guaranteed that winspool will have had it's init routine loaded
|
|
before us. Of course, we still can't guarentee that somebody won't try to
|
|
get at this key from their dllmain, so we wrap the whole thing in an
|
|
exception handler.
|
|
|
|
History:
|
|
|
|
02/06/2001 linstev & mnikkel Created
|
|
|
|
--*/
|
|
|
|
LONG
|
|
WINAPI
|
|
VR_Printer(
|
|
OPENKEY * /* key */,
|
|
VIRTUALKEY * /* vkey */,
|
|
VIRTUALVAL *vvalue
|
|
)
|
|
{
|
|
LOGN( eDbgLevelInfo, "[Printer] Query for legacy printer");
|
|
|
|
__try
|
|
{
|
|
DWORD dwSize;
|
|
|
|
// Get the default printer name
|
|
if (GetDefaultPrinterW(NULL, &dwSize) == 0)
|
|
{
|
|
// Now that we have the right size, allocate a buffer
|
|
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
LPWSTR pszName = (LPWSTR) malloc(dwSize * sizeof(WCHAR));
|
|
if (pszName)
|
|
{
|
|
// Now get the default printer with the right buffer size.
|
|
if (GetDefaultPrinterW(pszName, &dwSize))
|
|
{
|
|
//
|
|
// Set up the virtual value. Note we don't have free the
|
|
// memory since it's a once off allocation that persists
|
|
// with the value
|
|
//
|
|
vvalue->cbData = dwSize * sizeof(WCHAR);
|
|
vvalue->lpData = (LPBYTE) pszName;
|
|
|
|
//
|
|
// Never call us again, since we've found the printer and
|
|
// stored it in our virtual value
|
|
//
|
|
vvalue->pfnQueryValue = NULL;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We failed to get the default printer, may as well
|
|
// clean up gracefully.
|
|
//
|
|
|
|
free(pszName);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
DPFN( eDbgLevelError, "[Printer] No printers found or out of memory");
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DPFN( eDbgLevelError, "[Printer] Exception encountered, winspool not initialized?");
|
|
}
|
|
|
|
//
|
|
// Going for the graceful exit: there's no default printer or we get an
|
|
// error trying to find it.
|
|
//
|
|
|
|
return ERROR_FILE_NOT_FOUND;
|
|
}
|
|
|
|
void
|
|
BuildPrinter(char* /*szParam*/)
|
|
{
|
|
VIRTUALKEY *key;
|
|
|
|
key = VRegistry.AddKey(L"HKCC\\System\\CurrentControlSet\\Control\\Print\\Printers");
|
|
|
|
if (key)
|
|
{
|
|
VIRTUALVAL *val = key->AddValue(L"Default", REG_SZ, 0, 0);
|
|
if (val)
|
|
{
|
|
val->pfnQueryValue = VR_Printer;
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
The app is multi-threaded, but the app sets the DX DDSCL_MULTITHREADED flag
|
|
too late: after D3D is initialized. This hack basically turns on
|
|
multi-threaded locking for D3D.
|
|
|
|
History:
|
|
|
|
02/27/2001 rankala + ssteiner Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildStarTrekArmada(char* /*szParam*/)
|
|
{
|
|
VIRTUALKEY *key;
|
|
|
|
key = VRegistry.AddKey(L"HKLM\\SOFTWARE\\Microsoft\\Direct3D");
|
|
if (key)
|
|
{
|
|
key->AddValueDWORD(L"DisableST", 1);
|
|
}
|
|
}
|
|
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
This function gets called whenever the app queries for "Health" value.This
|
|
is not set properly by the app and this causes the app not to function
|
|
properly. We fix this issue by obtaining the right path which the app sets
|
|
in another registry key and sending that back as the value for "Health".
|
|
|
|
History:
|
|
|
|
05/04/2001 prashkud Created
|
|
|
|
--*/
|
|
|
|
LONG
|
|
WINAPI
|
|
VR_MSA2001(
|
|
OPENKEY * /* key */,
|
|
VIRTUALKEY * /* vkey */,
|
|
VIRTUALVAL *vvalue
|
|
)
|
|
{
|
|
HKEY hPath = NULL;
|
|
LONG lRet = ERROR_SUCCESS;
|
|
|
|
CSTRING_TRY
|
|
{
|
|
CString csBody5Reg(L"Software\\Classes\\Body5\\Open\\Shell\\Command");
|
|
WCHAR wPath[MAX_PATH];
|
|
DWORD dwSize = MAX_PATH*sizeof(WCHAR);
|
|
|
|
if (FAILURE(lRet = RegOpenKeyExW(
|
|
HKEY_LOCAL_MACHINE,
|
|
csBody5Reg.Get(),
|
|
0, KEY_READ, &hPath)))
|
|
{
|
|
DPFN(eDbgLevelError, "MSA2001: RegOpenKeyExW failed");
|
|
goto exit;
|
|
}
|
|
|
|
if (FAILURE( lRet = RegQueryValueExW(
|
|
hPath, L"", // Default value
|
|
0, NULL, (LPBYTE)wPath, &dwSize)))
|
|
{
|
|
DPFN(eDbgLevelError, "MSA2001: RegQueryValueEx failed");
|
|
goto exit;
|
|
}
|
|
|
|
CString csPath(wPath);
|
|
int len = csPath.Find(L" ");
|
|
|
|
// We get the space in the string
|
|
wPath[len] = L'\0';
|
|
csPath = wPath;
|
|
CString csPathName;
|
|
csPath.GetNotLastPathComponent(csPathName);
|
|
|
|
vvalue->cbData = (csPathName.GetLength()+1) * sizeof(WCHAR);
|
|
vvalue->lpData = (LPBYTE) malloc(vvalue->cbData);
|
|
|
|
if (!vvalue->lpData)
|
|
{
|
|
DPFN(eDbgLevelError, szOutOfMemory);
|
|
lRet = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
MoveMemory(vvalue->lpData, csPathName.Get(), vvalue->cbData);
|
|
DPFN(eDbgLevelInfo, "MSA2001: The data value is %S",csPathName.Get());
|
|
|
|
lRet = ERROR_SUCCESS;
|
|
vvalue->dwType = REG_SZ;
|
|
|
|
return lRet;
|
|
}
|
|
CSTRING_CATCH
|
|
{
|
|
}
|
|
|
|
exit:
|
|
if (hPath)
|
|
{
|
|
RegCloseKey(hPath);
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
|
|
History:
|
|
|
|
04/27/2001 prashkud Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildMSA2001(char* /*szParam*/)
|
|
{
|
|
VIRTUALKEY *Key = VRegistry.AddKey(L"HKLM\\Software\\Encore Software\\Middle School Advantage 2001\\1.0");
|
|
|
|
if (Key)
|
|
{
|
|
VIRTUALVAL *val = Key->AddValue(L"health", REG_SZ, 0, 0);
|
|
if (val)
|
|
{
|
|
val->pfnQueryValue = VR_MSA2001;
|
|
DPFN(eDbgLevelInfo, "[Middle School Advantage 2001] Added Health");
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Hack for Nowro Blue (Korean App)
|
|
|
|
History:
|
|
|
|
05/17/2001 hioh Created
|
|
|
|
--*/
|
|
|
|
void BuildNowroBlue(char* /*szParam*/)
|
|
{
|
|
// Below HKCU include location of files.
|
|
// Non install user could not locate files and could not run app properly.
|
|
// Redirect from HKCU to HKLM for commonly use.
|
|
VRegistry.AddRedirect(
|
|
L"HKCU\\Software\\nowcom",
|
|
L"HKLM\\Software\\nowcom");
|
|
VRegistry.AddRedirect(
|
|
L"HKCU\\Software\\nowirc",
|
|
L"HKLM\\Software\\nowirc");
|
|
VRegistry.AddRedirect(
|
|
L"HKCU\\Software\\nownuri",
|
|
L"HKLM\\Software\\nownuri");
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
To enable the trial version, WebWasher looks for RegisteredOrganization at:
|
|
|
|
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion
|
|
|
|
rather than:
|
|
|
|
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
|
|
|
|
History:
|
|
|
|
05/31/2001 stevepro Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildRegisteredOwner(char* /*szParam*/)
|
|
{
|
|
HKEY hkCurrentVersion;
|
|
|
|
if (FAILURE(RegOpenKeyExW(
|
|
HKEY_LOCAL_MACHINE,
|
|
L"Software\\Microsoft\\Windows NT\\CurrentVersion",
|
|
0,
|
|
KEY_READ,
|
|
&hkCurrentVersion)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Read the registered owner values from the old location
|
|
WCHAR szOrg[MAX_PATH];
|
|
*szOrg = L'\0';
|
|
DWORD dwSize = ARRAYSIZE(szOrg);
|
|
if (FAILURE(RegQueryValueExW(
|
|
hkCurrentVersion,
|
|
L"RegisteredOrganization",
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szOrg,
|
|
&dwSize)))
|
|
{
|
|
RegCloseKey(hkCurrentVersion);
|
|
return;
|
|
}
|
|
|
|
WCHAR szOwner[MAX_PATH];
|
|
*szOwner = L'\0';
|
|
dwSize = ARRAYSIZE(szOwner);
|
|
if (FAILURE(RegQueryValueExW(
|
|
hkCurrentVersion,
|
|
L"RegisteredOwner",
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szOwner,
|
|
&dwSize)))
|
|
{
|
|
RegCloseKey(hkCurrentVersion);
|
|
return;
|
|
}
|
|
|
|
RegCloseKey(hkCurrentVersion);
|
|
|
|
// Add them as virtual values to the new location
|
|
if (*szOrg || *szOwner)
|
|
{
|
|
VIRTUALKEY *pKey = VRegistry.AddKey(L"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion");
|
|
if (pKey)
|
|
{
|
|
if (*szOrg)
|
|
{
|
|
pKey->AddValue(L"RegisteredOrganization", REG_SZ, (LPBYTE)szOrg);
|
|
}
|
|
|
|
if (*szOwner)
|
|
{
|
|
pKey->AddValue(L"RegisteredOwner", REG_SZ, (LPBYTE)szOwner);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
The ACT CD of Princeton review looks for and, if not found, creates an "MSN"
|
|
key illegally in the root of HKLM. Win9x allows this, but Win2k does not.
|
|
This fix will redirect the program to look in the normal location for this
|
|
key.
|
|
|
|
|
|
History:
|
|
|
|
02/22/2001 a-noahy Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildPrincetonACT(char* /*szParam*/)
|
|
{
|
|
VRegistry.AddRedirect(
|
|
L"HKLM\\MSN",
|
|
L"HKLM\\Software\\Microsoft\\MSN");
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Fix for HEDZ which uses the registry to determine the resolution
|
|
|
|
History:
|
|
|
|
06/28/2001 linstev Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildHEDZ(char* /*szParam*/)
|
|
{
|
|
VIRTUALKEY *key;
|
|
|
|
//
|
|
// Add just what this app needs - don't bother with full emulation of this
|
|
// part of the registry
|
|
//
|
|
key = VRegistry.AddKey(L"HKLM\\Config\\0001\\Display\\Settings");
|
|
if (key)
|
|
{
|
|
WCHAR wzRes[10];
|
|
DWORD dwCX, dwCY;
|
|
key->AddValue(L"BitsPerPixel", REG_SZ, (LPBYTE)L"16");
|
|
dwCX = GetSystemMetrics(SM_CXSCREEN);
|
|
dwCY = GetSystemMetrics(SM_CYSCREEN);
|
|
if (FAILED(StringCchPrintfW(
|
|
wzRes, 10, L"%d,%d", dwCX, dwCY)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
key->AddValue(L"Resolution", REG_SZ, (LPBYTE)wzRes);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Called by BuildAirlineTycoon to recursively search for the key describing a CDROM
|
|
|
|
History:
|
|
|
|
08/07/2001 mikrause Created
|
|
|
|
--*/
|
|
|
|
void FindCDROMKey(HKEY hKey, CString& csCurrentPath)
|
|
{
|
|
LONG lRet;
|
|
DWORD dwKeyNameSize = MAX_PATH;
|
|
WCHAR wszKeyName[MAX_PATH];
|
|
HKEY hSubKey;
|
|
DWORD dwIndex = 0;
|
|
|
|
// Recurse into all subkeys.
|
|
while( ORIGINAL_API(RegEnumKeyExW)(hKey, dwIndex, wszKeyName, &dwKeyNameSize,
|
|
NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
|
|
{
|
|
lRet = ORIGINAL_API(RegOpenKeyExW)(hKey, wszKeyName, 0, KEY_READ, &hSubKey);
|
|
if (lRet == ERROR_SUCCESS)
|
|
{
|
|
// Add this key to the path
|
|
csCurrentPath += L"\\";
|
|
csCurrentPath += wszKeyName;
|
|
|
|
// Check this key's subkeys.
|
|
FindCDROMKey(hSubKey, csCurrentPath);
|
|
ORIGINAL_API(RegCloseKey)(hSubKey);
|
|
|
|
// Trim the path back.
|
|
int index = csCurrentPath.ReverseFind(L'\\');
|
|
csCurrentPath.Truncate(index);
|
|
}
|
|
|
|
dwKeyNameSize = MAX_PATH;
|
|
dwIndex++;
|
|
}
|
|
|
|
// Check if this key has a Class value equal to "cdrom"
|
|
|
|
DWORD dwDataSize;
|
|
BYTE pData[MAX_PATH*sizeof(WCHAR)];
|
|
|
|
DWORD dwType;
|
|
|
|
dwDataSize = MAX_PATH * sizeof(WCHAR);
|
|
|
|
lRet = ORIGINAL_API(RegQueryValueExW)(hKey, L"CLASS", NULL, &dwType, pData,
|
|
&dwDataSize);
|
|
if ( (lRet == ERROR_SUCCESS) && (dwType == REG_SZ)
|
|
&& (_wcsicmp((LPWSTR)pData, L"CDROM")==0))
|
|
{
|
|
// Get location information on the device
|
|
WCHAR wszLocationInformation[MAX_PATH];
|
|
DWORD dwLocInfoSize = MAX_PATH * sizeof(WCHAR);
|
|
|
|
lRet = ORIGINAL_API(RegQueryValueExW)(hKey, L"LocationInformation",
|
|
NULL, &dwType, (BYTE*)wszLocationInformation, &dwLocInfoSize);
|
|
if ( (lRet == ERROR_SUCCESS) && (dwType == REG_SZ))
|
|
{
|
|
// Create the device name (like "\\?\cdrom0\".
|
|
CString csDevice = L"\\\\?\\cdrom";
|
|
csDevice += wszLocationInformation;
|
|
csDevice += L"\\";
|
|
|
|
// Find which volume name this is mapped to.
|
|
WCHAR wszCDRomMountPoint[50];
|
|
if (GetVolumeNameForVolumeMountPoint(csDevice.Get(),
|
|
wszCDRomMountPoint, 50))
|
|
{
|
|
// Find which drive this is mapped to.
|
|
WCHAR wszDriveMountPoint[50];
|
|
WCHAR wszDrive[] = L"A:\\";
|
|
|
|
// Find what drive has an identical volume mount point.
|
|
for(; wszDrive[0] <= L'Z'; wszDrive[0]++)
|
|
{
|
|
if (GetVolumeNameForVolumeMountPoint(wszDrive,
|
|
wszDriveMountPoint, 50))
|
|
{
|
|
// Check if the CD-ROM and this disk drive
|
|
// map to the same volume.
|
|
if (_wcsicmp(wszDriveMountPoint, wszCDRomMountPoint)==0)
|
|
{
|
|
// Add a value to the CD-ROM key.
|
|
VIRTUALKEY* key = VRegistry.AddKey(csCurrentPath);
|
|
if (key)
|
|
{
|
|
// Only use a single letter.
|
|
wszDrive[1] = L'\0';
|
|
VIRTUALVAL* val =
|
|
key->AddValue(L"CurrentDriveLetterAssignment",
|
|
REG_SZ, (BYTE*) wszDrive, sizeof(WCHAR));
|
|
if (val)
|
|
{
|
|
DPFN(eDbgLevelInfo,
|
|
"[Airline Tycoon]Added drive letter \
|
|
%S for %S to PNP data", wszDrive,
|
|
csDevice.Get());
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Fix for Airline Tycoon which uses PNP registry entries to determine the
|
|
drive letter assignments for CD-ROM drives.
|
|
|
|
History:
|
|
|
|
08/07/2001 mikrause Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildAirlineTycoon(char* /*szParam*/)
|
|
{
|
|
// Search for CD-ROM keys in the registry.
|
|
HKEY hKey;
|
|
LONG lRet;
|
|
lRet = ORIGINAL_API(RegOpenKeyExW)(HKEY_LOCAL_MACHINE,
|
|
L"System\\CurrentControlSet\\Enum", 0, KEY_READ, &hKey);
|
|
if (lRet != ERROR_SUCCESS)
|
|
{
|
|
DPFN(eDbgLevelError, "[AirlineTycoon] Cannot open ENUM key!");
|
|
return;
|
|
}
|
|
|
|
// Enumerate subkeys
|
|
CString csBasePath = L"HKLM\\System\\CurrentControlSet\\Enum";
|
|
FindCDROMKey(hKey, csBasePath);
|
|
|
|
ORIGINAL_API(RegCloseKey)(hKey);
|
|
|
|
// Set up so that PNP data is redirected.
|
|
BuildDynData("");
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Sets the DirectSound acceleration level the app will be allowed to use.
|
|
|
|
Arguments:
|
|
|
|
szParam - Command line of the form: accellevel | device1 | device2 | ...
|
|
Accellevel is the device acceleration level, and devices 1 through n
|
|
are the devices to apply to.
|
|
Accellevel can be: NONE, STANDARD, or FULL
|
|
Devices can be: EMULATEDRENDER, KSRENDER, EMULATEDCAPTURE, KSCAPTURE
|
|
|
|
History:
|
|
|
|
08/10/2001 mikrause Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildDSDevAccel(
|
|
char* szParam)
|
|
{
|
|
// No Try/Catch needed, already in ParseCommandLine
|
|
CStringToken csParam(szParam, "|");
|
|
CString csTok;
|
|
|
|
DWORD dwAccelLevel;
|
|
DWORD dwDevices = 0;
|
|
|
|
if (csParam.GetToken(csTok))
|
|
{
|
|
if (csTok.CompareNoCase(L"NONE")==0)
|
|
{
|
|
dwAccelLevel = DSAPPHACK_ACCELNONE;
|
|
}
|
|
else if (csTok.CompareNoCase(L"STANDARD")==0)
|
|
{
|
|
dwAccelLevel = DSAPPHACK_ACCELSTANDARD;
|
|
}
|
|
else if (csTok.CompareNoCase(L"FULL")==0)
|
|
{
|
|
dwAccelLevel = DSAPPHACK_ACCELFULL;
|
|
}
|
|
else
|
|
{
|
|
DPFN(eDbgLevelError, "[DSDEVACCEL] Invalid Acceleration Level %s", csTok.GetAnsi());
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPFN(eDbgLevelError, "[DSDEVACCEL] Invalid Parameters");
|
|
return;
|
|
}
|
|
|
|
while (csParam.GetToken(csTok))
|
|
{
|
|
if (csTok.CompareNoCase(L"EMULATEDRENDER")==0)
|
|
{
|
|
dwDevices |= DSAPPHACK_DEV_EMULATEDRENDER;
|
|
}
|
|
else if (csTok.CompareNoCase(L"KSRENDER")==0)
|
|
{
|
|
dwDevices |= DSAPPHACK_DEV_KSRENDER;
|
|
}
|
|
else if (csTok.CompareNoCase(L"EMULATEDCAPTURE")==0)
|
|
{
|
|
dwDevices |= DSAPPHACK_DEV_EMULATEDCAPTURE;
|
|
}
|
|
else if (csTok.CompareNoCase(L"KSCAPTURE")==0)
|
|
{
|
|
dwDevices |= DSAPPHACK_DEV_KSCAPTURE;
|
|
}
|
|
else
|
|
{
|
|
DPFN(eDbgLevelError, "[DSDEVACCEL] Unknown device %s", csTok.GetAnsi());
|
|
}
|
|
}
|
|
|
|
if (dwDevices == 0)
|
|
{
|
|
DPFN(eDbgLevelError, "[DSDEVACCEL] No devices specified.");
|
|
return;
|
|
}
|
|
|
|
if (AddDSHackDeviceAcceleration(dwAccelLevel, dwDevices) == FALSE)
|
|
{
|
|
DPFN(eDbgLevelError, "[DSDEVACCEL] Unabled to add DirectSound hack");
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Makes IDirectSoundBuffer::GetCurrentPosition() tell the app
|
|
that the play and write cursors are X milliseconds further
|
|
along than they really are.
|
|
|
|
Arguments:
|
|
|
|
szParam - Command line of the form: milliseconds
|
|
Where milliseconds is the number of milliseconds to pad the cursors.
|
|
|
|
History:
|
|
|
|
08/10/2001 mikrause Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildDSPadCursors(
|
|
char* szParam)
|
|
{
|
|
// No Try/Catch needed, already in ParseCommandLine
|
|
CString csParam(szParam);
|
|
DWORD dwMilliseconds = 0;
|
|
|
|
dwMilliseconds = atol(csParam.GetAnsi());
|
|
if ( dwMilliseconds == 0)
|
|
{
|
|
DPFN(eDbgLevelWarning, "[DSPADCURSORS] Invalid number of milliseconds");
|
|
return;
|
|
}
|
|
|
|
if (AddDSHackPadCursors(dwMilliseconds) == FALSE)
|
|
{
|
|
DPFN(eDbgLevelError, "[DSPADCURSORS] Unabled to add DirectSound hack");
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Caches the positions of the cursors for apps that abuse
|
|
IDirectSoundBuffer::GetCurrentPosition().
|
|
|
|
Arguments:
|
|
szParam - Command line of the form: Dev1 | Dev2 | . . .
|
|
Devices affected. See BuildDSDevAccel().
|
|
|
|
History:
|
|
|
|
08/10/2001 mikrause Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildDSCachePositions(
|
|
char* szParam)
|
|
{
|
|
// No Try/Catch needed, already in ParseCommandLine
|
|
CStringToken csParam(szParam, "|");
|
|
CString csTok;
|
|
|
|
DWORD dwDevices = 0;
|
|
|
|
while (csParam.GetToken(csTok))
|
|
{
|
|
if (csTok.CompareNoCase(L"EMULATEDRENDER")==0)
|
|
{
|
|
dwDevices |= DSAPPHACK_DEV_EMULATEDRENDER;
|
|
}
|
|
else if (csTok.CompareNoCase(L"KSRENDER")==0)
|
|
{
|
|
dwDevices |= DSAPPHACK_DEV_KSRENDER;
|
|
}
|
|
else if (csTok.CompareNoCase(L"EMULATEDCAPTURE")==0)
|
|
{
|
|
dwDevices |= DSAPPHACK_DEV_EMULATEDCAPTURE;
|
|
}
|
|
else if (csTok.CompareNoCase(L"KSCAPTURE")==0)
|
|
{
|
|
dwDevices |= DSAPPHACK_DEV_KSCAPTURE;
|
|
}
|
|
else
|
|
{
|
|
DPFN(eDbgLevelError, "[DSCACHEPOSITIONS] Unknown device %s", csTok.GetAnsi());
|
|
}
|
|
}
|
|
|
|
if (dwDevices == 0)
|
|
{
|
|
DPFN(eDbgLevelError, "[DSCACHEPOSITIONS] No devices specified.");
|
|
return;
|
|
}
|
|
|
|
if (AddDSHackCachePositions(dwDevices) == FALSE)
|
|
{
|
|
DPFN(eDbgLevelError, "[DSCACHEPOSITIONS] Unabled to add DirectSound hack");
|
|
}
|
|
}
|
|
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
When the app asks for the play cursor, we give it the
|
|
write cursor instead. The correct way to stream audio
|
|
into a looping dsound buffer is to key off the write cursor,
|
|
but some apps (e.g. QuickTime) use the play cursor instead.
|
|
This apphacks alleviates them.
|
|
|
|
Arguments:
|
|
|
|
szParam - Parameters of the form dev1 | dev2 | . . .
|
|
See BuildDSDevAccel() for valid devices.
|
|
|
|
History:
|
|
|
|
08/10/2001 mikrause Created
|
|
|
|
--*/
|
|
void
|
|
BuildDSReturnWritePos(
|
|
char* szParam)
|
|
{
|
|
// No Try/Catch needed, already in ParseCommandLine
|
|
CStringToken csParam(szParam, "|");
|
|
CString csTok;
|
|
|
|
DWORD dwDevices = 0;
|
|
|
|
while (csParam.GetToken(csTok))
|
|
{
|
|
if (csTok.CompareNoCase(L"EMULATEDRENDER")==0)
|
|
{
|
|
dwDevices |= DSAPPHACK_DEV_EMULATEDRENDER;
|
|
}
|
|
else if (csTok.CompareNoCase(L"KSRENDER")==0)
|
|
{
|
|
dwDevices |= DSAPPHACK_DEV_KSRENDER;
|
|
}
|
|
else if (csTok.CompareNoCase(L"EMULATEDCAPTURE")==0)
|
|
{
|
|
dwDevices |= DSAPPHACK_DEV_EMULATEDCAPTURE;
|
|
}
|
|
else if (csTok.CompareNoCase(L"KSCAPTURE")==0)
|
|
{
|
|
dwDevices |= DSAPPHACK_DEV_KSCAPTURE;
|
|
}
|
|
else
|
|
{
|
|
DPFN(eDbgLevelError, "[DSRETURNWRITEPOSITION] Unknown device %s", csTok.GetAnsi());
|
|
}
|
|
}
|
|
|
|
if (dwDevices == 0)
|
|
{
|
|
DPFN(eDbgLevelError, "[DSRETURNWRITEPOSITION] No devices specified.");
|
|
return;
|
|
}
|
|
|
|
if (AddDSHackReturnWritePos(dwDevices) == FALSE)
|
|
{
|
|
DPFN(eDbgLevelError, "[DSRETURNWRITEPOSITION] Unabled to add DirectSound hack");
|
|
}
|
|
}
|
|
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Makes dsound always return a write position which is X
|
|
milliseconds ahead of the play position, rather than
|
|
the “real” write position.
|
|
|
|
Arguments:
|
|
|
|
szParam - Milliseconds of padding.
|
|
|
|
History:
|
|
|
|
08/10/2001 mikrause Created
|
|
|
|
--*/
|
|
|
|
|
|
void
|
|
BuildDSSmoothWritePos(
|
|
char* szParam)
|
|
{
|
|
// No Try/Catch needed, already in ParseCommandLine
|
|
CString csParam(szParam);
|
|
DWORD dwMilliseconds = 0;
|
|
|
|
dwMilliseconds = atol(csParam.GetAnsi());
|
|
if ( dwMilliseconds == 0)
|
|
{
|
|
DPFN(eDbgLevelWarning, "[DSSMOOTHWRITEPOS] Invalid number of milliseconds");
|
|
return;
|
|
}
|
|
|
|
if (AddDSHackSmoothWritePos(dwMilliseconds) == FALSE)
|
|
{
|
|
DPFN(eDbgLevelError, "[DSSMOOTHWRITEPOS] Unabled to add DirectSound hack");
|
|
}
|
|
else
|
|
{
|
|
DPFN(eDbgLevelInfo, "[DSSMOOTHWRITEPOS] Added DS Hack Smooth Write Pos, %d ms",
|
|
dwMilliseconds);
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
NortonAntiVirus trys to set the registry value to hide the language bar.
|
|
Protecting the registry value.
|
|
|
|
History:
|
|
|
|
01/02/2002 mamathas Created
|
|
|
|
--*/
|
|
|
|
void BuildNortonAntiVirus(char* /*szParam*/)
|
|
{
|
|
VIRTUALKEY *key;
|
|
|
|
key = VRegistry.AddKey(L"HKCU\\Software\\Microsoft\\CTF\\LangBar");
|
|
if (key)
|
|
{
|
|
// Block all writes to ShowStatus
|
|
key->AddProtector(L"ShowStatus");
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Disabled some category of devices altogether, forces
|
|
playback through emulated path.
|
|
|
|
Arguments:
|
|
|
|
szParam - Combination of device that this hack applies to, see BuildDSDevAccel().
|
|
|
|
History:
|
|
|
|
08/10/2001 mikrause Created
|
|
|
|
--*/
|
|
|
|
void
|
|
BuildDSDisableDevice(
|
|
char* szParam)
|
|
{
|
|
// No try/catch needed. Already done in ParseCommandLine
|
|
CStringToken csParam(szParam, "|");
|
|
CString csTok;
|
|
|
|
DWORD dwDevices = 0;
|
|
|
|
while (csParam.GetToken(csTok)==TRUE)
|
|
{
|
|
if (csTok.CompareNoCase(L"EMULATEDRENDER"))
|
|
{
|
|
dwDevices |= DSAPPHACK_DEV_EMULATEDRENDER;
|
|
}
|
|
else if (csTok.CompareNoCase(L"KSRENDER")==0)
|
|
{
|
|
dwDevices |= DSAPPHACK_DEV_KSRENDER;
|
|
}
|
|
else if (csTok.CompareNoCase(L"EMULATEDCAPTURE")==0)
|
|
{
|
|
dwDevices |= DSAPPHACK_DEV_EMULATEDCAPTURE;
|
|
}
|
|
else if (csTok.CompareNoCase(L"KSCAPTURE")==0)
|
|
{
|
|
dwDevices |= DSAPPHACK_DEV_KSCAPTURE;
|
|
}
|
|
else
|
|
{
|
|
DPFN(eDbgLevelError, "[DSDISABLEDEVICE] Unknown device %s", csTok.GetAnsi());
|
|
}
|
|
}
|
|
|
|
if (dwDevices == 0)
|
|
{
|
|
DPFN(eDbgLevelError, "[DSDISABLEDEVICE] No devices specified.");
|
|
return;
|
|
}
|
|
|
|
if (AddDSHackDisableDevice(dwDevices) == FALSE)
|
|
{
|
|
DPFN(eDbgLevelError, "[DSRETURNWRITEPOSITION] Unabled to add DirectSound hack");
|
|
}
|
|
}
|
|
|
|
LONG WINAPI
|
|
Delphi5SetValue(
|
|
OPENKEY *key,
|
|
VIRTUALKEY * /* vkey */,
|
|
VIRTUALVAL *vvalue,
|
|
DWORD dwType,
|
|
const BYTE* pbData,
|
|
DWORD cbData)
|
|
{
|
|
// Only accept attempts to set a valid REG_SZ value.
|
|
if (dwType == REG_SZ && !IsBadStringPtrW((PWSTR)pbData, cbData/sizeof(WCHAR)))
|
|
{
|
|
CSTRING_TRY
|
|
{
|
|
CString csValue = (PWSTR)pbData;
|
|
|
|
int idx = csValue.Find(L"InstReg.exe");
|
|
|
|
if (idx != -1)
|
|
{
|
|
csValue.Insert(idx + lstrlenW(L"InstReg.exe"), L'\"');
|
|
csValue.Insert(0, L'\"');
|
|
|
|
return RegSetValueExW(key->hkOpen, vvalue->wName, 0, dwType, (BYTE*)csValue.Get(),
|
|
(csValue.GetLength()+1)*sizeof(WCHAR));
|
|
}
|
|
}
|
|
CSTRING_CATCH
|
|
{
|
|
DPFN(eDbgLevelError, "CString exception occured in Delphi5SetValue");
|
|
}
|
|
}
|
|
|
|
// Got here, something went wrong. Default o normal RegSetValue
|
|
return RegSetValueExW(key->hkOpen, vvalue->wName, 0, dwType, pbData, cbData);
|
|
}
|
|
|
|
void
|
|
BuildDelphi5Pro(
|
|
char* /* szParam */)
|
|
{
|
|
VIRTUALKEY *key;
|
|
|
|
key = VRegistry.AddKey(L"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce");
|
|
if (key)
|
|
{
|
|
key->AddCustomSet(L"BorlandReboot1", Delphi5SetValue);
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
Word Perfect Office Suite 2002 attempts to delete ODBC key during uninstall.
|
|
Protecting the registry value.
|
|
|
|
History:
|
|
|
|
04/23/2002 garyma Created
|
|
|
|
--*/
|
|
|
|
void BuildWordPerfect2002(char* /*szParam*/)
|
|
{
|
|
VRegistry.AddKeyProtector(L"HKLM\\Software\\ODBC");
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
IMPLEMENT_SHIM_END
|