X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=altosui%2FInstdrv%2FNSIS%2FContrib%2FInstDrv%2FInstDrv.c;fp=altosui%2FInstdrv%2FNSIS%2FContrib%2FInstDrv%2FInstDrv.c;h=efe866e988f1aa3194f71d4dcf0ab7cf18076d6a;hp=0000000000000000000000000000000000000000;hb=3fbefb3eea981d34a09496cf8abf0119de2e35bf;hpb=7a50837ea0d92db3f469f197ec8210aee22aa143 diff --git a/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c b/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c new file mode 100644 index 00000000..efe866e9 --- /dev/null +++ b/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c @@ -0,0 +1,704 @@ +/* + +InstDrv.dll - Installs or Removes Device Drivers + +Copyright © 2003 Jan Kiszka (Jan.Kiszka@web.de) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute +it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment in the + product documentation would be appreciated but is not required. +2. Altered versions must be plainly marked as such, + and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any distribution. + +*/ + + +#include +#include +#include +#include "../exdll/exdll.h" + + +char paramBuf[1024]; +GUID devClass; +char hwIdBuf[1024]; +int initialized = 0; + + + +void* memset(void* dst, int val, unsigned int len) +{ + while (len-- > 0) + *((char *)dst)++ = val; + + return NULL; +} + + + +void* memcpy(void* dst, const void* src, unsigned int len) +{ + while (len-- > 0) + *((char *)dst)++ = *((char *)src)++; + + return NULL; +} + + + +int HexCharToInt(char c) +{ + if ((c >= '0') && (c <= '9')) + return c - '0'; + else if ((c >= 'a') && (c <= 'f')) + return c - 'a' + 10; + else if ((c >= 'A') && (c <= 'F')) + return c - 'A' + 10; + else + return -1; +} + + + +BOOLEAN HexStringToUInt(char* str, int width, void* valBuf) +{ + int i, val; + + + for (i = width - 4; i >= 0; i -= 4) + { + val = HexCharToInt(*str++); + if (val < 0) + return FALSE; + *(unsigned int *)valBuf += val << i; + } + + return TRUE; +} + + + +BOOLEAN StringToGUID(char* guidStr, GUID* pGuid) +{ + int i; + + + memset(pGuid, 0, sizeof(GUID)); + + if (*guidStr++ != '{') + return FALSE; + + if (!HexStringToUInt(guidStr, 32, &pGuid->Data1)) + return FALSE; + guidStr += 8; + + if (*guidStr++ != '-') + return FALSE; + + if (!HexStringToUInt(guidStr, 16, &pGuid->Data2)) + return FALSE; + guidStr += 4; + + if (*guidStr++ != '-') + return FALSE; + + if (!HexStringToUInt(guidStr, 16, &pGuid->Data3)) + return FALSE; + guidStr += 4; + + if (*guidStr++ != '-') + return FALSE; + + for (i = 0; i < 2; i++) + { + if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i])) + return FALSE; + guidStr += 2; + } + + if (*guidStr++ != '-') + return FALSE; + + for (i = 2; i < 8; i++) + { + if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i])) + return FALSE; + guidStr += 2; + } + + if (*guidStr++ != '}') + return FALSE; + + return TRUE; +} + + + +DWORD FindNextDevice(HDEVINFO devInfoSet, SP_DEVINFO_DATA* pDevInfoData, DWORD* pIndex) +{ + DWORD buffersize = 0; + LPTSTR buffer = NULL; + DWORD dataType; + DWORD result; + + + while (1) + { + if (!SetupDiEnumDeviceInfo(devInfoSet, (*pIndex)++, pDevInfoData)) + { + result = GetLastError(); + break; + } + + GetDeviceRegistryProperty: + if (!SetupDiGetDeviceRegistryProperty(devInfoSet, pDevInfoData, SPDRP_HARDWAREID, + &dataType, (PBYTE)buffer, buffersize, + &buffersize)) + { + result = GetLastError(); + + if (result == ERROR_INSUFFICIENT_BUFFER) + { + if (buffer != NULL) + LocalFree(buffer); + + buffer = (LPTSTR)LocalAlloc(LPTR, buffersize); + + if (buffer == NULL) + break; + + goto GetDeviceRegistryProperty; + } + else if (result == ERROR_INVALID_DATA) + continue; // ignore invalid entries + else + break; // break on other errors + } + + if (lstrcmpi(buffer, hwIdBuf) == 0) + { + result = 0; + break; + } + } + + if (buffer != NULL) + LocalFree(buffer); + + return result; +} + + + +DWORD FindFirstDevice(HWND hwndParent, const GUID* pDevClass, const LPTSTR hwId, + HDEVINFO* pDevInfoSet, SP_DEVINFO_DATA* pDevInfoData, + DWORD *pIndex, DWORD flags) +{ + DWORD result; + + + *pDevInfoSet = SetupDiGetClassDevs((GUID*)pDevClass, NULL, hwndParent, flags); + if (*pDevInfoSet == INVALID_HANDLE_VALUE) + return GetLastError(); + + pDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA); + *pIndex = 0; + + result = FindNextDevice(*pDevInfoSet, pDevInfoData, pIndex); + + if (result != 0) + SetupDiDestroyDeviceInfoList(*pDevInfoSet); + + return result; +} + + + +/* + * InstDrv::InitDriverSetup devClass drvHWID + * + * devClass - GUID of the driver's device setup class + * drvHWID - Hardware ID of the supported device + * + * Return: + * result - error message, empty on success + */ +void __declspec(dllexport) InitDriverSetup(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + EXDLL_INIT(); + + /* convert class GUID */ + popstring(paramBuf); + + if (!StringToGUID(paramBuf, &devClass)) + { + popstring(paramBuf); + pushstring("Invalid GUID!"); + return; + } + + /* get hardware ID */ + memset(hwIdBuf, 0, sizeof(hwIdBuf)); + popstring(hwIdBuf); + + initialized = 1; + pushstring(""); +} + + + +/* + * InstDrv::CountDevices + * + * Return: + * result - Number of installed devices the driver supports + */ +void __declspec(dllexport) CountDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + HDEVINFO devInfoSet; + SP_DEVINFO_DATA devInfoData; + int count = 0; + char countBuf[16]; + DWORD index; + DWORD result; + + + EXDLL_INIT(); + + if (!initialized) + { + pushstring("Fatal error!"); + return; + } + + result = FindFirstDevice(hwndParent, &devClass, hwIdBuf, &devInfoSet, &devInfoData, + &index, DIGCF_PRESENT); + if (result != 0) + { + pushstring("0"); + return; + } + + do + { + count++; + } while (FindNextDevice(devInfoSet, &devInfoData, &index) == 0); + + SetupDiDestroyDeviceInfoList(devInfoSet); + + wsprintf(countBuf, "%d", count); + pushstring(countBuf); +} + + + +/* + * InstDrv::CreateDevice + * + * Return: + * result - Windows error code + */ +void __declspec(dllexport) CreateDevice(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + HDEVINFO devInfoSet; + SP_DEVINFO_DATA devInfoData; + DWORD result = 0; + char resultBuf[16]; + + + EXDLL_INIT(); + + if (!initialized) + { + pushstring("Fatal error!"); + return; + } + + devInfoSet = SetupDiCreateDeviceInfoList(&devClass, hwndParent); + if (devInfoSet == INVALID_HANDLE_VALUE) + { + wsprintf(resultBuf, "%08X", GetLastError()); + pushstring(resultBuf); + return; + } + + devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + if (!SetupDiCreateDeviceInfo(devInfoSet, hwIdBuf, &devClass, NULL, + hwndParent, DICD_GENERATE_ID, &devInfoData)) + { + result = GetLastError(); + goto InstallCleanup; + } + + if (!SetupDiSetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_HARDWAREID, + hwIdBuf, (lstrlen(hwIdBuf)+2)*sizeof(TCHAR))) + { + result = GetLastError(); + goto InstallCleanup; + } + + if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, devInfoSet, &devInfoData)) + result = GetLastError(); + + InstallCleanup: + SetupDiDestroyDeviceInfoList(devInfoSet); + + wsprintf(resultBuf, "%08X", result); + pushstring(resultBuf); +} + + + +/* + * InstDrv::InstallDriver infPath + * + * Return: + * result - Windows error code + * reboot - non-zero if reboot is required + */ +void __declspec(dllexport) InstallDriver(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + char resultBuf[16]; + BOOL reboot; + + + EXDLL_INIT(); + popstring(paramBuf); + + if (!initialized) + { + pushstring("Fatal error!"); + return; + } + + if (!UpdateDriverForPlugAndPlayDevices(hwndParent, hwIdBuf, paramBuf, + INSTALLFLAG_FORCE, &reboot)) + { + wsprintf(resultBuf, "%08X", GetLastError()); + pushstring(resultBuf); + } + else + { + wsprintf(resultBuf, "%d", reboot); + pushstring(resultBuf); + pushstring("00000000"); + } +} + + + +/* + * InstDrv::DeleteOemInfFiles + * + * Return: + * result - Windows error code + * oeminf - Path of the deleted devices setup file (oemXX.inf) + * oempnf - Path of the deleted devices setup file (oemXX.pnf) + */ +void __declspec(dllexport) DeleteOemInfFiles(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + HDEVINFO devInfo; + SP_DEVINFO_DATA devInfoData; + SP_DRVINFO_DATA drvInfoData; + SP_DRVINFO_DETAIL_DATA drvInfoDetail; + DWORD index; + DWORD result; + char resultBuf[16]; + + + if (!initialized) + { + pushstring("Fatal error!"); + return; + } + + result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0); + if (result != 0) + goto Cleanup1; + + if (!SetupDiBuildDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER)) + { + result = GetLastError(); + goto Cleanup2; + } + + drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA); + drvInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); + + if (!SetupDiEnumDriverInfo(devInfo, &devInfoData, SPDIT_COMPATDRIVER, 0, &drvInfoData)) + { + result = GetLastError(); + goto Cleanup3; + } + + if (!SetupDiGetDriverInfoDetail(devInfo, &devInfoData, &drvInfoData, + &drvInfoDetail, sizeof(drvInfoDetail), NULL)) + { + result = GetLastError(); + + if (result != ERROR_INSUFFICIENT_BUFFER) + goto Cleanup3; + + result = 0; + } + + pushstring(drvInfoDetail.InfFileName); + if (!DeleteFile(drvInfoDetail.InfFileName)) + result = GetLastError(); + else + { + index = lstrlen(drvInfoDetail.InfFileName); + if (index > 3) + { + lstrcpy(drvInfoDetail.InfFileName+index-3, "pnf"); + pushstring(drvInfoDetail.InfFileName); + if (!DeleteFile(drvInfoDetail.InfFileName)) + result = GetLastError(); + } + } + + Cleanup3: + SetupDiDestroyDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER); + + Cleanup2: + SetupDiDestroyDeviceInfoList(devInfo); + + Cleanup1: + wsprintf(resultBuf, "%08X", result); + pushstring(resultBuf); +} + + + +/* + * InstDrv::RemoveAllDevices + * + * Return: + * result - Windows error code + * reboot - non-zero if reboot is required + */ +void __declspec(dllexport) RemoveAllDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + HDEVINFO devInfo; + SP_DEVINFO_DATA devInfoData; + DWORD index; + DWORD result; + char resultBuf[16]; + BOOL reboot = FALSE; + SP_DEVINSTALL_PARAMS instParams; + + + EXDLL_INIT(); + + if (!initialized) + { + pushstring("Fatal error!"); + return; + } + + result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0); + if (result != 0) + goto Cleanup1; + + do + { + if (!SetupDiCallClassInstaller(DIF_REMOVE, devInfo, &devInfoData)) + { + result = GetLastError(); + break; + } + + instParams.cbSize = sizeof(instParams); + if (!reboot && + SetupDiGetDeviceInstallParams(devInfo, &devInfoData, &instParams) && + ((instParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT)) != 0)) + { + reboot = TRUE; + } + + result = FindNextDevice(devInfo, &devInfoData, &index); + } while (result == 0); + + SetupDiDestroyDeviceInfoList(devInfo); + + Cleanup1: + if ((result == 0) || (result == ERROR_NO_MORE_ITEMS)) + { + wsprintf(resultBuf, "%d", reboot); + pushstring(resultBuf); + pushstring("00000000"); + } + else + { + wsprintf(resultBuf, "%08X", result); + pushstring(resultBuf); + } +} + + + +/* + * InstDrv::StartSystemService serviceName + * + * Return: + * result - Windows error code + */ +void __declspec(dllexport) StartSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + SC_HANDLE managerHndl; + SC_HANDLE svcHndl; + SERVICE_STATUS svcStatus; + DWORD oldCheckPoint; + DWORD result; + char resultBuf[16]; + + + EXDLL_INIT(); + popstring(paramBuf); + + managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (managerHndl == NULL) + { + result = GetLastError(); + goto Cleanup1; + } + + svcHndl = OpenService(managerHndl, paramBuf, SERVICE_START | SERVICE_QUERY_STATUS); + if (svcHndl == NULL) + { + result = GetLastError(); + goto Cleanup2; + } + + if (!StartService(svcHndl, 0, NULL) || !QueryServiceStatus(svcHndl, &svcStatus)) + { + result = GetLastError(); + goto Cleanup3; + } + + while (svcStatus.dwCurrentState == SERVICE_START_PENDING) + { + oldCheckPoint = svcStatus.dwCheckPoint; + + Sleep(svcStatus.dwWaitHint); + + if (!QueryServiceStatus(svcHndl, &svcStatus)) + { + result = GetLastError(); + break; + } + + if (oldCheckPoint >= svcStatus.dwCheckPoint) + { + if ((svcStatus.dwCurrentState == SERVICE_STOPPED) && + (svcStatus.dwWin32ExitCode != 0)) + result = svcStatus.dwWin32ExitCode; + else + result = ERROR_SERVICE_REQUEST_TIMEOUT; + } + } + + if (svcStatus.dwCurrentState == SERVICE_RUNNING) + result = 0; + + Cleanup3: + CloseServiceHandle(svcHndl); + + Cleanup2: + CloseServiceHandle(managerHndl); + + Cleanup1: + wsprintf(resultBuf, "%08X", result); + pushstring(resultBuf); +} + + + +/* + * InstDrv::StopSystemService serviceName + * + * Return: + * result - Windows error code + */ +void __declspec(dllexport) StopSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + SC_HANDLE managerHndl; + SC_HANDLE svcHndl; + SERVICE_STATUS svcStatus; + DWORD oldCheckPoint; + DWORD result; + char resultBuf[16]; + + + EXDLL_INIT(); + popstring(paramBuf); + + managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (managerHndl == NULL) + { + result = GetLastError(); + goto Cleanup1; + } + + svcHndl = OpenService(managerHndl, paramBuf, SERVICE_STOP | SERVICE_QUERY_STATUS); + if (svcHndl == NULL) + { + result = GetLastError(); + goto Cleanup2; + } + + if (!ControlService(svcHndl, SERVICE_CONTROL_STOP, &svcStatus)) + { + result = GetLastError(); + goto Cleanup3; + } + + while (svcStatus.dwCurrentState == SERVICE_STOP_PENDING) + { + oldCheckPoint = svcStatus.dwCheckPoint; + + Sleep(svcStatus.dwWaitHint); + + if (!QueryServiceStatus(svcHndl, &svcStatus)) + { + result = GetLastError(); + break; + } + + if (oldCheckPoint >= svcStatus.dwCheckPoint) + { + result = ERROR_SERVICE_REQUEST_TIMEOUT; + break; + } + } + + if (svcStatus.dwCurrentState == SERVICE_STOPPED) + result = 0; + + Cleanup3: + CloseServiceHandle(svcHndl); + + Cleanup2: + CloseServiceHandle(managerHndl); + + Cleanup1: + wsprintf(resultBuf, "%08X", result); + pushstring(resultBuf); +} + + + +BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) +{ + return TRUE; +}