|
|
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <tchar.h>
#include <regstr.h>
// this will change when the .h is moved to a public location
#include "comp.h"
HINSTANCE hInstance;
PCOMPAIBILITYCALLBACK CompatCallback; LPVOID CompatContext;
#define szServicesPath REGSTR_PATH_SERVICES TEXT("\\")
#define szDeviceMap TEXT("HARDWARE\\DEVICEMAP")
typedef struct _INPUT_DRIVER_DATA { LPTSTR Service;
BOOL DisableReplacements;
LPTSTR DeviceMapSubKey;
} INPUT_DRIVER_DATA;
INPUT_DRIVER_DATA DriverData[] = { { TEXT("sermouse"), FALSE, NULL }, { TEXT("i8042prt"), TRUE, TEXT("KeyboardPort") }, { TEXT("mouclass"), TRUE, TEXT("PointerClass") }, { TEXT("kbdclass"), TRUE, TEXT("KeyboardClass") }, };
#define NUM_DRIVER_DATA (sizeof(DriverData) / sizeof(INPUT_DRIVER_DATA))
LPENUM_SERVICE_STATUS AllocEnumServiceStatus(SC_HANDLE hSCManager, LPDWORD Count) { LPENUM_SERVICE_STATUS ess; DWORD size; DWORD resume;
EnumServicesStatus(hSCManager, SERVICE_DRIVER, SERVICE_ACTIVE, NULL, 0, &size, Count, &resume);
if (size == 0) { return NULL; }
ess = (LPENUM_SERVICE_STATUS) LocalAlloc(LPTR, size); if (!ess) { return NULL; }
EnumServicesStatus(hSCManager, SERVICE_DRIVER, SERVICE_ACTIVE, ess, size, &size, Count, &resume);
return ess; }
LPQUERY_SERVICE_CONFIG GetServiceConfig(SC_HANDLE hService) { LPQUERY_SERVICE_CONFIG pConfig; DWORD configSize;
QueryServiceConfig(hService, NULL, 0, &configSize);
pConfig = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, configSize); if (pConfig == NULL) { return NULL; }
if (!QueryServiceConfig(hService, pConfig, configSize, &configSize)) { LocalFree(pConfig); pConfig = NULL; }
return pConfig; }
BOOL ValidImagePath(LPTSTR Service, LPTSTR ImagePath, LPTSTR *ImageName) { LPTSTR pszDriver, pszDriverEnd, pszDriverBegin;
if (!ImagePath) { return FALSE; }
if (lstrlen(ImagePath) == 0) { return TRUE; }
if (_tcschr(ImagePath, TEXT('\\')) == 0) { return FALSE; }
pszDriver = ImagePath; pszDriverEnd = pszDriver + lstrlen(pszDriver);
while(pszDriverEnd != pszDriver && *pszDriverEnd != TEXT('.')) { pszDriverEnd--; }
// pszDriverEnd points to either the beginning of the string or '.'
pszDriverBegin = pszDriverEnd;
while(pszDriverBegin != pszDriver && *pszDriverBegin != TEXT('\\')) { pszDriverBegin--; }
pszDriverBegin++;
//
// If pszDriver and pszDriverEnd are different, we now
// have the driver name.
//
if (pszDriverBegin > pszDriver && pszDriverEnd > pszDriverBegin) {
LONG len, res; LPTSTR image;
len = ((LONG) (pszDriverEnd - pszDriverBegin)) + 1;
image = (LPTSTR) LocalAlloc(LPTR, len * sizeof(TCHAR)); if (!image) { return FALSE; } // want to copy up to, but not including, the ','
lstrcpyn(image, pszDriverBegin, len); res = lstrcmpi(image, Service);
if (ImageName != NULL) { *ImageName = image; } else { LocalFree(image); }
return res == 0; } else { return FALSE; }
}
VOID SetServiceStartValue(LPTSTR Service, DWORD StartValue) { COMPATIBILITY_ENTRY ce; TCHAR szStart[] = TEXT("Start"); LPTSTR regPath; DWORD len;
len = lstrlen(Service) + lstrlen(szServicesPath) + 1; len *= sizeof(TCHAR);
regPath = (LPTSTR) LocalAlloc(LPTR, len); if (!regPath) { return; }
lstrcpy(regPath, szServicesPath); lstrcat(regPath, Service);
ZeroMemory(&ce, sizeof(COMPATIBILITY_ENTRY)); // Description and TextName are need even though this is hidden
ce.Description = Service; ce.TextName = Service; ce.RegKeyName = regPath; ce.RegValName = szStart; ce.RegValDataSize = sizeof(DWORD); ce.RegValData = (LPVOID) &StartValue; ce.Flags |= COMPFLAG_HIDE;
CompatCallback(&ce, CompatContext);
LocalFree(regPath); }
VOID SetServiceImagePath(LPTSTR Service) { COMPATIBILITY_ENTRY ce; TCHAR szImagePath[] = TEXT("ImagePath"); TCHAR szPath[] = TEXT("System32\\Drivers\\"); LPTSTR imagePath, regPath; DWORD len;
len = lstrlen(Service) + lstrlen(szServicesPath) + 1; len *= sizeof(TCHAR);
regPath = (LPTSTR) LocalAlloc(LPTR, len); if (!regPath) { return; }
len = lstrlen(szPath) + lstrlen(Service) + lstrlen(TEXT(".sys")) + 1; len *= sizeof(TCHAR);
imagePath = (LPTSTR) LocalAlloc(LPTR, len); if (!imagePath) { LocalFree(regPath); return; }
lstrcpy(regPath, szServicesPath); lstrcat(regPath, Service);
lstrcpy(imagePath, szPath); lstrcat(imagePath, Service); lstrcat(imagePath, TEXT(".sys"));
ZeroMemory(&ce, sizeof(COMPATIBILITY_ENTRY)); // Description and TextName are need even though this is hidden
ce.Description = Service; ce.TextName = Service; ce.RegKeyName = regPath; ce.RegValName = szImagePath; ce.RegValDataSize = len; ce.RegValData = (LPVOID) imagePath; ce.Flags |= COMPFLAG_HIDE;
CompatCallback(&ce, CompatContext);
LocalFree(regPath); LocalFree(imagePath); }
SC_HANDLE CheckService(SC_HANDLE hSCManager, LPTSTR Service, BOOL *Disabled) { SC_HANDLE hService; LPQUERY_SERVICE_CONFIG pConfig;
hService = OpenService(hSCManager, Service, SERVICE_QUERY_CONFIG); if (hService) { pConfig = GetServiceConfig(hService); if (pConfig) {
if (pConfig->dwStartType == SERVICE_DISABLED && pConfig->lpBinaryPathName && lstrlen(pConfig->lpBinaryPathName) == 0) { //
// The service has been preinstalled in the registry, but never
// installed on the machine (indicated byno image path,
// disabled). Setting its start value to demand start will not
// cause any conflicts at all in the PNP world of input drivers.
//
SetServiceStartValue(Service, SERVICE_DEMAND_START); } else { if (pConfig->dwStartType != SERVICE_SYSTEM_START && pConfig->dwStartType != SERVICE_DEMAND_START) { if (Disabled) { *Disabled = TRUE; } SetServiceStartValue(Service, SERVICE_DEMAND_START); } if (!ValidImagePath(Service, pConfig->lpBinaryPathName, NULL)) { SetServiceImagePath(Service); } }
LocalFree(pConfig); pConfig = NULL; } }
return hService; }
BOOL KnownInputDriver(LPTSTR Service) { int i = 0;
for ( ; i < NUM_DRIVER_DATA; i++) { if (lstrcmpi(Service, DriverData[i].Service) == 0) { return TRUE; } }
return FALSE; }
VOID EnumAndDisableFromDeviceMap(SC_HANDLE hSCManager, LPTSTR Key) { HKEY hMap, hSubKey; DWORD dwIndex = 0, dwType, err, dwValueNameSize, dwDataSize; TCHAR szValueName[255], szData[255];
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szDeviceMap, 0, KEY_READ, &hMap) != ERROR_SUCCESS) { return; } if (RegOpenKeyEx(hMap, Key, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS) { RegCloseKey(hMap); return; }
RegCloseKey(hMap);
do { dwValueNameSize = sizeof(szValueName) / sizeof(TCHAR); dwDataSize = sizeof(szData);
err = RegEnumValue(hSubKey, dwIndex++, szValueName, &dwValueNameSize, 0, &dwType, (LPBYTE) szData, &dwDataSize);
if (err == ERROR_SUCCESS) { LPTSTR service = _tcsrchr(szData, TEXT('\\'));
if (service) { service++; if (!KnownInputDriver(service)) { SetServiceStartValue(service, SERVICE_DISABLED); } } } } while (err == ERROR_SUCCESS);
RegCloseKey(hSubKey); }
BOOL InputUpgradeCheck(PCOMPAIBILITYCALLBACK CompatibilityCallback, LPVOID Context) { SC_HANDLE hSCManager, hService; BOOL disabled; int i;
LPENUM_SERVICE_STATUS ess = NULL; DWORD count, resume;
CompatCallback = CompatibilityCallback; CompatContext = Context;
hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (hSCManager == NULL) { return TRUE; }
for (i = 0; i < NUM_DRIVER_DATA; i++) { disabled = FALSE; hService = CheckService(hSCManager, DriverData[i].Service, &disabled); if (hService) { if (disabled && DriverData[i].DisableReplacements) { // search and destroy
EnumAndDisableFromDeviceMap(hSCManager, DriverData[i].DeviceMapSubKey); } CloseServiceHandle(hService); } }
CloseServiceHandle(hSCManager); return TRUE; }
BOOL APIENTRY DllMain(HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved) { switch (dwReason) { case DLL_PROCESS_ATTACH: hInstance = hDll; break;
case DLL_PROCESS_DETACH: break;
case DLL_THREAD_DETACH: break;
case DLL_THREAD_ATTACH: break;
default: break; }
return TRUE; }
|