/***************************************************************************** * * DIAddHw.c * * Copyright (c) 1996 Microsoft Corporation. All Rights Reserved. * * Abstract: * * Add New Hardware * * Contents: * * AddNewHardware * *****************************************************************************/ #include "dinputpr.h" #include "dithunk.h" #pragma BEGIN_CONST_DATA /***************************************************************************** * * The sqiffle for this file. * *****************************************************************************/ #define sqfl sqflJoyCfg #ifdef IDirectInputJoyConfig_QueryInterface #define case95(n) case n: #define caseNT(n) case n: HRESULT INTERNAL hresFromDiErr_NT(DWORD et); HRESULT INTERNAL hresFromDiErr_95(int et); /***************************************************************************** * * These are the functions we have to steal from SYSDM... * *****************************************************************************/ LPCSTR rgpszSysdm[] = { "InstallDevice_RunDLL", /* InstallDevice_RunDLL */ }; typedef struct SYSDM { /* sysdm */ FARPROC InstallDevice_RunDLL; } SYSDM, *PSYSDM; /***************************************************************************** * * @doc INTERNAL * * @func int | DiDestroyDeviceInfoList | * * Thunk down to SETUPX.DiCallClassInstaller. * *****************************************************************************/ void INLINE InstallDevice_RunDLL(PSYSDM psysdm, HWND hwnd, HINSTANCE hinst, LPCSTR psz, UINT show) { TemplateThunk(psysdm->InstallDevice_RunDLL, "ssps", hwnd, hinst, psz, show); } /***************************************************************************** * * @doc INTERNAL * * @struct CLASSMAP | * * Structure that establishes the relationship between * for device classes and the name of the class. * * This code needs to hang around because Windows 95 * doesn't have SETUPAPI.DLL, so we need to fake it. * * @parm HWND | hwndOwner | * * Window to act as owner window for UI. * * @parm REFGUID | rguidClass | * * which specifies the class of the hardware device. * *****************************************************************************/ typedef struct CLASSMAP { REFGUID pguidClass; LPCSTR ptszClass; } CLASSMAP, *PCLASSMAP; const CLASSMAP c_rgcmap[] = { { &GUID_KeyboardClass, ("keyboard"), }, { &GUID_MediaClass, ("media"), }, { &GUID_MouseClass, ("mouse"), }, { &GUID_HIDClass, ("HID"), }, }; /***************************************************************************** * * @doc INTERNAL * * @func RESULT | AddNewHardware | * * Display the "Add new hardware" dialog. * * We pull a gross hack because Device Manager is completely * unmanageable. We simply call the RunDll entry point and * let it do its thing. Note that this means we have no way * of knowing what the result was. Oh well. * * @parm HWND | hwndOwner | * * Window to act as owner window for UI. * * @parm REFGUID | rguidClass | * * which specifies the class of the hardware device. * *****************************************************************************/ HRESULT INTERNAL AddNewHardware_95(HWND hwnd, REFGUID rguid) { SYSDM sysdm; HINSTANCE hinst; HRESULT hres; EnterProcR(AddNewHardware, (_ "xG", hwnd, rguid)); if (Thunk_GetKernelProcAddresses() && (hinst = Thunk_GetProcAddresses((PV)&sysdm, rgpszSysdm, cA(rgpszSysdm), ("SYSDM.CPL")))) { int icmap; for (icmap = 0; icmap < cA(c_rgcmap); icmap++) { if (IsEqualGUID(rguid, c_rgcmap[icmap].pguidClass)) { goto found; } } RPF("%s: Unknown device class", s_szProc); hres = DIERR_INVALIDCLASSINSTALLER; goto done; found:; InstallDevice_RunDLL(&sysdm, hwnd, hinst, c_rgcmap[icmap].ptszClass, SW_NORMAL); g_kpa.FreeLibrary16(hinst); hres = S_FALSE; } else { RPF("%s: Problems thunking to configuration manager", s_szProc); hres = E_FAIL; } done:; ExitOleProc(); return hres; } /***************************************************************************** * * @doc INTERNAL * * @func RESULT | AddNewHardware | * * Display the "Add new hardware" dialog. * * @parm HWND | hwndOwner | * * Window to act as owner window for UI. * * @parm REFGUID | rguidClass | * * which specifies the class of the hardware device. * *****************************************************************************/ HRESULT INTERNAL AddNewHardware_NT(HWND hwnd, REFGUID rguid) { HRESULT hres; HINSTANCE hInst; BOOL b; FARPROC proc; DWORD le; hres = E_NOTIMPL; /* Load AddNewHardware proc from newdev.dll part of AddNewHardware wizard. */ hInst = LoadLibrary(TEXT("newdev.dll")); if (hInst) { proc = GetProcAddress(hInst, (LPCSTR)"InstallNewDevice"); if (proc) { le = ERROR_SUCCESS; b = (BOOL)(*proc)(hwnd, rguid, 0); // 0 means newdev decides about reboot if (!b) { le = GetLastError(); } hres = hresFromDiErr_NT(le); } FreeLibrary(hInst); } return hres; } HRESULT EXTERNAL AddNewHardware(HWND hwnd, REFGUID rguid) { return ((fWinnt)? AddNewHardware_NT(hwnd, rguid) : AddNewHardware_95(hwnd, rguid)); } /***************************************************************************** * * @doc INTERNAL * * @func HRESULT | hresFromDiErr | * * Convert a device installer error code into an HRESULT. * *****************************************************************************/ HRESULT INTERNAL hresFromDiErr_NT(DWORD et) { HRESULT hres; switch (et) { case ERROR_SUCCESS: hres = S_OK; break; /* * Do the default action for the requested operation. */ caseNT(ERROR_DI_DO_DEFAULT); hres = S_OK; break; /* * No need to copy files (in install). */ caseNT(ERROR_DI_NOFILECOPY); hres = S_OK; break; /* * Registry entry or DLL for class installer invalid. */ caseNT(ERROR_INVALID_CLASS_INSTALLER); hres = DIERR_INVALIDCLASSINSTALLER; break; /* * Insufficient memory. */ caseNT(ERROR_NOT_ENOUGH_MEMORY); caseNT(ERROR_OUTOFMEMORY); hres = E_OUTOFMEMORY; break; /* * The user cancelled the operation. */ caseNT(ERROR_CANCELLED); caseNT(ERROR_NO_DRIVER_SELECTED); hres = DIERR_CANCELLED; break; /* * Various impossible things. */ caseNT(ERROR_NO_ASSOCIATED_CLASS); caseNT(ERROR_CLASS_MISMATCH); caseNT(ERROR_DUPLICATE_FOUND); caseNT(ERROR_KEY_DOES_NOT_EXIST); caseNT(ERROR_INVALID_DEVINST_NAME); caseNT(ERROR_INVALID_CLASS); caseNT(ERROR_DEVINFO_NOT_REGISTERED); caseNT(ERROR_DEVINST_ALREADY_EXISTS); caseNT(ERROR_INVALID_REG_PROPERTY); caseNT(ERROR_NO_SUCH_DEVINST); caseNT(ERROR_CANT_LOAD_CLASS_ICON); caseNT(ERROR_INVALID_HWPROFILE); caseNT(ERROR_DEVINFO_LIST_LOCKED); caseNT(ERROR_DEVINFO_DATA_LOCKED); caseNT(ERROR_NO_CLASSINSTALL_PARAMS); caseNT(ERROR_FILEQUEUE_LOCKED); caseNT(ERROR_BAD_SERVICE_INSTALLSECT); caseNT(ERROR_NO_CLASS_DRIVER_LIST); caseNT(ERROR_NO_ASSOCIATED_SERVICE); caseNT(ERROR_NO_DEFAULT_DEVICE_INTERFACE); default:; hres = E_FAIL; break; caseNT(ERROR_DI_BAD_PATH); caseNT(ERROR_NO_INF); hres = DIERR_BADINF; break; } return hres; } #ifndef DI_ERROR #define DI_ERROR (500) // Device Installer #endif enum _ERR_DEVICE_INSTALL { ERR_DI_INVALID_DEVICE_ID = DI_ERROR, // Incorrectly formed device IDF ERR_DI_INVALID_COMPATIBLE_DEVICE_LIST, // Invalid compatible device list ERR_DI_REG_API, // Error returned by Reg API. ERR_DI_LOW_MEM, // Insufficient memory to complete ERR_DI_BAD_DEV_INFO, // Device Info struct invalid ERR_DI_INVALID_CLASS_INSTALLER, // Registry entry / DLL invalid ERR_DI_DO_DEFAULT, // Take default action ERR_DI_USER_CANCEL, // the user cancelled the operation ERR_DI_NOFILECOPY, // No need to copy files (in install) ERR_DI_BAD_CLASS_INFO, // Class Info Struct invalid ERR_DI_BAD_INF, // Bad INF file encountered ERR_DI_BAD_MOVEDEV_PARAMS, // Bad Move Device Params struct ERR_DI_NO_INF, // No INF found on OEM disk ERR_DI_BAD_PROPCHANGE_PARAMS, // Bad property change param struct ERR_DI_BAD_SELECTDEVICE_PARAMS, // Bad Select Device Parameters ERR_DI_BAD_REMOVEDEVICE_PARAMS, // Bad Remove Device Parameters ERR_DI_BAD_ENABLECLASS_PARAMS, // Bad Enable Class Parameters ERR_DI_FAIL_QUERY, // Fail the Enable Class query ERR_DI_API_ERROR, // DI API called incorrectly ERR_DI_BAD_PATH, // An OEM path was specified incorrectly ERR_DI_BAD_UNREMOVEDEVICE_PARAMS, // Bad Unremove Device Parameters ERR_DI_NOUPDATE, // No Drivers Were updated ERR_DI_NODATE, // The driver does not have a Date stamp in the INF ERR_DI_NOVERSION, // There is not version string in the INF ERR_DI_DONT_INSTALL, // Don't upgrade the current driver ERR_DI_NO_DIGITAL_SIGNATURE_CATALOG, // Catalog is not digitally signed ERR_DI_NO_DIGITAL_SIGNATURE_INF, // Inf is not digitally signed ERR_DI_NO_DIGITAL_SIGNATURE_FILE, // A file is not digitally signed }; HRESULT INTERNAL hresFromDiErr_95(int et) { HRESULT hres; switch (et) { case ERROR_SUCCESS: hres = S_OK; break; /* * Do the default action for the requested operation. */ case95(ERR_DI_DO_DEFAULT); hres = S_OK; break; /* * No need to copy files (in install). */ case95(ERR_DI_NOFILECOPY); hres = S_OK; break; /* * No Drivers Were updated. */ // case95(ERR_DI_NOUPDATE); // hres = S_OK; break; /* * Don't upgrade the current driver. */ // case95(ERR_DI_DONT_UPGRADE); // hres = S_OK; break; /* * No Drivers Were updated. */ case95(ERR_DI_NOUPDATE); hres = S_OK; break; /* * Registry entry or DLL for class installer invalid. */ case95(ERR_DI_INVALID_CLASS_INSTALLER); hres = DIERR_INVALIDCLASSINSTALLER; break; /* * Insufficient memory. */ case95(ERR_DI_LOW_MEM); hres = E_OUTOFMEMORY; break; /* * The user cancelled the operation. */ case95(ERR_DI_USER_CANCEL); hres = DIERR_CANCELLED; break; /* * Various impossible things. */ case95(ERR_DI_BAD_DEV_INFO); /* Device Info struct invalid */ case95(ERR_DI_BAD_CLASS_INFO); /* Class Info Struct invalid */ case95(ERR_DI_API_ERROR); /* DI API called incorrectly */ case95(ERR_DI_BAD_PROPCHANGE_PARAMS); /* Bad property chg param struct */ case95(ERR_DI_BAD_SELECTDEVICE_PARAMS); /* Bad Select Device Parameters */ case95(ERR_DI_BAD_REMOVEDEVICE_PARAMS); /* Bad Remove Device Parameters */ case95(ERR_DI_BAD_ENABLECLASS_PARAMS); /* Bad Enable Class Parameters */ case95(ERR_DI_BAD_MOVEDEV_PARAMS); /* Bad Move Device Params struct */ case95(ERR_DI_FAIL_QUERY); /* Fail the Enable Class query */ case95(ERR_DI_INVALID_COMPATIBLE_DEVICE_LIST); /* Invalid compatible device list*/ case95(ERR_DI_BAD_UNREMOVEDEVICE_PARAMS); /* Bad Unremove Device Parameters*/ case95(ERR_DI_INVALID_DEVICE_ID); /* Incorrectly formed device IDF */ case95(ERR_DI_REG_API); /* Error returned by Reg API. */ default:; hres = E_FAIL; break; case95(ERR_DI_BAD_PATH); /* OEM path specified incorrectly*/ case95(ERR_DI_BAD_INF); /* Bad INF file encountered */ case95(ERR_DI_NO_INF); /* No INF found on OEM disk */ case95(ERR_DI_NOVERSION); /* No version string in the INF */ case95(ERR_DI_NODATE); /* No Date stamp in the INF */ hres = DIERR_BADINF; break; } return hres; } #endif /* defined(IDirectInputJoyConfigVtbl) */