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