3 InstDrv.dll - Installs or Removes Device Drivers
\r
5 Copyright © 2003 Jan Kiszka (Jan.Kiszka@web.de)
\r
7 This software is provided 'as-is', without any express or implied
\r
8 warranty. In no event will the authors be held liable for any damages
\r
9 arising from the use of this software.
\r
11 Permission is granted to anyone to use this software for any purpose,
\r
12 including commercial applications, and to alter it and redistribute
\r
13 it freely, subject to the following restrictions:
\r
15 1. The origin of this software must not be misrepresented;
\r
16 you must not claim that you wrote the original software.
\r
17 If you use this software in a product, an acknowledgment in the
\r
18 product documentation would be appreciated but is not required.
\r
19 2. Altered versions must be plainly marked as such,
\r
20 and must not be misrepresented as being the original software.
\r
21 3. This notice may not be removed or altered from any distribution.
\r
26 #include <windows.h>
\r
27 #include <setupapi.h>
\r
29 #include "../exdll/exdll.h"
\r
32 char paramBuf[1024];
\r
35 int initialized = 0;
\r
39 void* memset(void* dst, int val, unsigned int len)
\r
42 *((char *)dst)++ = val;
\r
49 void* memcpy(void* dst, const void* src, unsigned int len)
\r
52 *((char *)dst)++ = *((char *)src)++;
\r
59 int HexCharToInt(char c)
\r
61 if ((c >= '0') && (c <= '9'))
\r
63 else if ((c >= 'a') && (c <= 'f'))
\r
64 return c - 'a' + 10;
\r
65 else if ((c >= 'A') && (c <= 'F'))
\r
66 return c - 'A' + 10;
\r
73 BOOLEAN HexStringToUInt(char* str, int width, void* valBuf)
\r
78 for (i = width - 4; i >= 0; i -= 4)
\r
80 val = HexCharToInt(*str++);
\r
83 *(unsigned int *)valBuf += val << i;
\r
91 BOOLEAN StringToGUID(char* guidStr, GUID* pGuid)
\r
96 memset(pGuid, 0, sizeof(GUID));
\r
98 if (*guidStr++ != '{')
\r
101 if (!HexStringToUInt(guidStr, 32, &pGuid->Data1))
\r
105 if (*guidStr++ != '-')
\r
108 if (!HexStringToUInt(guidStr, 16, &pGuid->Data2))
\r
112 if (*guidStr++ != '-')
\r
115 if (!HexStringToUInt(guidStr, 16, &pGuid->Data3))
\r
119 if (*guidStr++ != '-')
\r
122 for (i = 0; i < 2; i++)
\r
124 if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i]))
\r
129 if (*guidStr++ != '-')
\r
132 for (i = 2; i < 8; i++)
\r
134 if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i]))
\r
139 if (*guidStr++ != '}')
\r
147 DWORD FindNextDevice(HDEVINFO devInfoSet, SP_DEVINFO_DATA* pDevInfoData, DWORD* pIndex)
\r
149 DWORD buffersize = 0;
\r
150 LPTSTR buffer = NULL;
\r
157 if (!SetupDiEnumDeviceInfo(devInfoSet, (*pIndex)++, pDevInfoData))
\r
159 result = GetLastError();
\r
163 GetDeviceRegistryProperty:
\r
164 if (!SetupDiGetDeviceRegistryProperty(devInfoSet, pDevInfoData, SPDRP_HARDWAREID,
\r
165 &dataType, (PBYTE)buffer, buffersize,
\r
168 result = GetLastError();
\r
170 if (result == ERROR_INSUFFICIENT_BUFFER)
\r
172 if (buffer != NULL)
\r
175 buffer = (LPTSTR)LocalAlloc(LPTR, buffersize);
\r
177 if (buffer == NULL)
\r
180 goto GetDeviceRegistryProperty;
\r
182 else if (result == ERROR_INVALID_DATA)
\r
183 continue; // ignore invalid entries
\r
185 break; // break on other errors
\r
188 if (lstrcmpi(buffer, hwIdBuf) == 0)
\r
195 if (buffer != NULL)
\r
203 DWORD FindFirstDevice(HWND hwndParent, const GUID* pDevClass, const LPTSTR hwId,
\r
204 HDEVINFO* pDevInfoSet, SP_DEVINFO_DATA* pDevInfoData,
\r
205 DWORD *pIndex, DWORD flags)
\r
210 *pDevInfoSet = SetupDiGetClassDevs((GUID*)pDevClass, NULL, hwndParent, flags);
\r
211 if (*pDevInfoSet == INVALID_HANDLE_VALUE)
\r
212 return GetLastError();
\r
214 pDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
\r
217 result = FindNextDevice(*pDevInfoSet, pDevInfoData, pIndex);
\r
220 SetupDiDestroyDeviceInfoList(*pDevInfoSet);
\r
228 * InstDrv::InitDriverSetup devClass drvHWID
\r
230 * devClass - GUID of the driver's device setup class
\r
231 * drvHWID - Hardware ID of the supported device
\r
234 * result - error message, empty on success
\r
236 void __declspec(dllexport) InitDriverSetup(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
\r
240 /* convert class GUID */
\r
241 popstring(paramBuf);
\r
243 if (!StringToGUID(paramBuf, &devClass))
\r
245 popstring(paramBuf);
\r
246 pushstring("Invalid GUID!");
\r
250 /* get hardware ID */
\r
251 memset(hwIdBuf, 0, sizeof(hwIdBuf));
\r
252 popstring(hwIdBuf);
\r
261 * InstDrv::CountDevices
\r
264 * result - Number of installed devices the driver supports
\r
266 void __declspec(dllexport) CountDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
\r
268 HDEVINFO devInfoSet;
\r
269 SP_DEVINFO_DATA devInfoData;
\r
280 pushstring("Fatal error!");
\r
284 result = FindFirstDevice(hwndParent, &devClass, hwIdBuf, &devInfoSet, &devInfoData,
\r
285 &index, DIGCF_PRESENT);
\r
295 } while (FindNextDevice(devInfoSet, &devInfoData, &index) == 0);
\r
297 SetupDiDestroyDeviceInfoList(devInfoSet);
\r
299 wsprintf(countBuf, "%d", count);
\r
300 pushstring(countBuf);
\r
306 * InstDrv::CreateDevice
\r
309 * result - Windows error code
\r
311 void __declspec(dllexport) CreateDevice(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
\r
313 HDEVINFO devInfoSet;
\r
314 SP_DEVINFO_DATA devInfoData;
\r
316 char resultBuf[16];
\r
323 pushstring("Fatal error!");
\r
327 devInfoSet = SetupDiCreateDeviceInfoList(&devClass, hwndParent);
\r
328 if (devInfoSet == INVALID_HANDLE_VALUE)
\r
330 wsprintf(resultBuf, "%08X", GetLastError());
\r
331 pushstring(resultBuf);
\r
335 devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
\r
336 if (!SetupDiCreateDeviceInfo(devInfoSet, hwIdBuf, &devClass, NULL,
\r
337 hwndParent, DICD_GENERATE_ID, &devInfoData))
\r
339 result = GetLastError();
\r
340 goto InstallCleanup;
\r
343 if (!SetupDiSetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_HARDWAREID,
\r
344 hwIdBuf, (lstrlen(hwIdBuf)+2)*sizeof(TCHAR)))
\r
346 result = GetLastError();
\r
347 goto InstallCleanup;
\r
350 if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, devInfoSet, &devInfoData))
\r
351 result = GetLastError();
\r
354 SetupDiDestroyDeviceInfoList(devInfoSet);
\r
356 wsprintf(resultBuf, "%08X", result);
\r
357 pushstring(resultBuf);
\r
363 * InstDrv::InstallDriver infPath
\r
366 * result - Windows error code
\r
367 * reboot - non-zero if reboot is required
\r
369 void __declspec(dllexport) InstallDriver(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
\r
371 char resultBuf[16];
\r
376 popstring(paramBuf);
\r
380 pushstring("Fatal error!");
\r
384 if (!UpdateDriverForPlugAndPlayDevices(hwndParent, hwIdBuf, paramBuf,
\r
385 INSTALLFLAG_FORCE, &reboot))
\r
387 wsprintf(resultBuf, "%08X", GetLastError());
\r
388 pushstring(resultBuf);
\r
392 wsprintf(resultBuf, "%d", reboot);
\r
393 pushstring(resultBuf);
\r
394 pushstring("00000000");
\r
401 * InstDrv::DeleteOemInfFiles
\r
404 * result - Windows error code
\r
405 * oeminf - Path of the deleted devices setup file (oemXX.inf)
\r
406 * oempnf - Path of the deleted devices setup file (oemXX.pnf)
\r
408 void __declspec(dllexport) DeleteOemInfFiles(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
\r
411 SP_DEVINFO_DATA devInfoData;
\r
412 SP_DRVINFO_DATA drvInfoData;
\r
413 SP_DRVINFO_DETAIL_DATA drvInfoDetail;
\r
416 char resultBuf[16];
\r
421 pushstring("Fatal error!");
\r
425 result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0);
\r
429 if (!SetupDiBuildDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER))
\r
431 result = GetLastError();
\r
435 drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
\r
436 drvInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
\r
438 if (!SetupDiEnumDriverInfo(devInfo, &devInfoData, SPDIT_COMPATDRIVER, 0, &drvInfoData))
\r
440 result = GetLastError();
\r
444 if (!SetupDiGetDriverInfoDetail(devInfo, &devInfoData, &drvInfoData,
\r
445 &drvInfoDetail, sizeof(drvInfoDetail), NULL))
\r
447 result = GetLastError();
\r
449 if (result != ERROR_INSUFFICIENT_BUFFER)
\r
455 pushstring(drvInfoDetail.InfFileName);
\r
456 if (!DeleteFile(drvInfoDetail.InfFileName))
\r
457 result = GetLastError();
\r
460 index = lstrlen(drvInfoDetail.InfFileName);
\r
463 lstrcpy(drvInfoDetail.InfFileName+index-3, "pnf");
\r
464 pushstring(drvInfoDetail.InfFileName);
\r
465 if (!DeleteFile(drvInfoDetail.InfFileName))
\r
466 result = GetLastError();
\r
471 SetupDiDestroyDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER);
\r
474 SetupDiDestroyDeviceInfoList(devInfo);
\r
477 wsprintf(resultBuf, "%08X", result);
\r
478 pushstring(resultBuf);
\r
484 * InstDrv::RemoveAllDevices
\r
487 * result - Windows error code
\r
488 * reboot - non-zero if reboot is required
\r
490 void __declspec(dllexport) RemoveAllDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
\r
493 SP_DEVINFO_DATA devInfoData;
\r
496 char resultBuf[16];
\r
497 BOOL reboot = FALSE;
\r
498 SP_DEVINSTALL_PARAMS instParams;
\r
505 pushstring("Fatal error!");
\r
509 result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0);
\r
515 if (!SetupDiCallClassInstaller(DIF_REMOVE, devInfo, &devInfoData))
\r
517 result = GetLastError();
\r
521 instParams.cbSize = sizeof(instParams);
\r
523 SetupDiGetDeviceInstallParams(devInfo, &devInfoData, &instParams) &&
\r
524 ((instParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT)) != 0))
\r
529 result = FindNextDevice(devInfo, &devInfoData, &index);
\r
530 } while (result == 0);
\r
532 SetupDiDestroyDeviceInfoList(devInfo);
\r
535 if ((result == 0) || (result == ERROR_NO_MORE_ITEMS))
\r
537 wsprintf(resultBuf, "%d", reboot);
\r
538 pushstring(resultBuf);
\r
539 pushstring("00000000");
\r
543 wsprintf(resultBuf, "%08X", result);
\r
544 pushstring(resultBuf);
\r
551 * InstDrv::StartSystemService serviceName
\r
554 * result - Windows error code
\r
556 void __declspec(dllexport) StartSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
\r
558 SC_HANDLE managerHndl;
\r
560 SERVICE_STATUS svcStatus;
\r
561 DWORD oldCheckPoint;
\r
563 char resultBuf[16];
\r
567 popstring(paramBuf);
\r
569 managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
\r
570 if (managerHndl == NULL)
\r
572 result = GetLastError();
\r
576 svcHndl = OpenService(managerHndl, paramBuf, SERVICE_START | SERVICE_QUERY_STATUS);
\r
577 if (svcHndl == NULL)
\r
579 result = GetLastError();
\r
583 if (!StartService(svcHndl, 0, NULL) || !QueryServiceStatus(svcHndl, &svcStatus))
\r
585 result = GetLastError();
\r
589 while (svcStatus.dwCurrentState == SERVICE_START_PENDING)
\r
591 oldCheckPoint = svcStatus.dwCheckPoint;
\r
593 Sleep(svcStatus.dwWaitHint);
\r
595 if (!QueryServiceStatus(svcHndl, &svcStatus))
\r
597 result = GetLastError();
\r
601 if (oldCheckPoint >= svcStatus.dwCheckPoint)
\r
603 if ((svcStatus.dwCurrentState == SERVICE_STOPPED) &&
\r
604 (svcStatus.dwWin32ExitCode != 0))
\r
605 result = svcStatus.dwWin32ExitCode;
\r
607 result = ERROR_SERVICE_REQUEST_TIMEOUT;
\r
611 if (svcStatus.dwCurrentState == SERVICE_RUNNING)
\r
615 CloseServiceHandle(svcHndl);
\r
618 CloseServiceHandle(managerHndl);
\r
621 wsprintf(resultBuf, "%08X", result);
\r
622 pushstring(resultBuf);
\r
628 * InstDrv::StopSystemService serviceName
\r
631 * result - Windows error code
\r
633 void __declspec(dllexport) StopSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
\r
635 SC_HANDLE managerHndl;
\r
637 SERVICE_STATUS svcStatus;
\r
638 DWORD oldCheckPoint;
\r
640 char resultBuf[16];
\r
644 popstring(paramBuf);
\r
646 managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
\r
647 if (managerHndl == NULL)
\r
649 result = GetLastError();
\r
653 svcHndl = OpenService(managerHndl, paramBuf, SERVICE_STOP | SERVICE_QUERY_STATUS);
\r
654 if (svcHndl == NULL)
\r
656 result = GetLastError();
\r
660 if (!ControlService(svcHndl, SERVICE_CONTROL_STOP, &svcStatus))
\r
662 result = GetLastError();
\r
666 while (svcStatus.dwCurrentState == SERVICE_STOP_PENDING)
\r
668 oldCheckPoint = svcStatus.dwCheckPoint;
\r
670 Sleep(svcStatus.dwWaitHint);
\r
672 if (!QueryServiceStatus(svcHndl, &svcStatus))
\r
674 result = GetLastError();
\r
678 if (oldCheckPoint >= svcStatus.dwCheckPoint)
\r
680 result = ERROR_SERVICE_REQUEST_TIMEOUT;
\r
685 if (svcStatus.dwCurrentState == SERVICE_STOPPED)
\r
689 CloseServiceHandle(svcHndl);
\r
692 CloseServiceHandle(managerHndl);
\r
695 wsprintf(resultBuf, "%08X", result);
\r
696 pushstring(resultBuf);
\r
701 BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
\r