Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

515 lines
14 KiB

  1. /* REMOVE.C
  2. **
  3. ** Copyright (C) Microsoft, 1990, All Rights Reserved.
  4. **
  5. ** Multimedia Control Panel Applet for removing
  6. ** device drivers. See the ispec doc DRIVERS.DOC for more information.
  7. **
  8. ** History:
  9. **
  10. ** Thu Oct 17 1991 -by- Sanjaya
  11. ** Created. Originally part of drivers.c
  12. */
  13. #include <windows.h>
  14. #include <mmsystem.h>
  15. #include <winsvc.h>
  16. #include <memory.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <cpl.h>
  20. #include <cphelp.h>
  21. #include "drivers.h"
  22. #include "sulib.h"
  23. BOOL SetValidAlias (PSTR, PSTR);
  24. #ifdef DOBOOT
  25. BOOL FindBootDriver (char *);
  26. PSTR strstri (PSTR, PSTR);
  27. #endif // DOBOOT
  28. /*
  29. * RemoveService(szFile)
  30. *
  31. * Remove the service corresponding to the file szFile
  32. *
  33. * returns TRUE if successful, FALSE otherwise
  34. */
  35. BOOL RemoveService(LPSTR szFile)
  36. {
  37. SC_HANDLE SCManagerHandle;
  38. SC_HANDLE ServiceHandle;
  39. char ServiceName[MAX_PATH];
  40. BOOL Status = FALSE;
  41. /*
  42. * Extract the service name from the file name
  43. */
  44. {
  45. char drive[MAX_PATH], directory[MAX_PATH], ext[MAX_PATH];
  46. _splitpath(szFile, drive, directory, ServiceName, ext);
  47. }
  48. /*
  49. * First try and obtain a handle to the service controller
  50. */
  51. SCManagerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  52. if (SCManagerHandle == NULL) {
  53. char szMesg[MAXSTR];
  54. char szMesg2[MAXSTR];
  55. LoadString(myInstance, IDS_INSUFFICIENT_PRIVILEGE, szMesg, sizeof(szMesg));
  56. wsprintf(szMesg2, szMesg, szFile);
  57. MessageBox(hMesgBoxParent, szMesg2, szRemove, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
  58. return FALSE;
  59. }
  60. ServiceHandle = OpenService(SCManagerHandle,
  61. ServiceName,
  62. SERVICE_ALL_ACCESS);
  63. if (ServiceHandle != NULL) {
  64. SERVICE_STATUS ServiceStatus;
  65. SC_LOCK ServicesDatabaseLock;
  66. /*
  67. * Stop the service if possible.
  68. */
  69. ControlService(ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus);
  70. /*
  71. * Delete the service.
  72. * We aren't detecting if we can just carry on.
  73. */
  74. /*
  75. * Lock the service controller database to avoid deadlocks
  76. * we have to loop because we can't wait
  77. */
  78. for (ServicesDatabaseLock = NULL;
  79. (ServicesDatabaseLock =
  80. LockServiceDatabase(SCManagerHandle))
  81. == NULL;
  82. Sleep(100)) {
  83. }
  84. Status = DeleteService(ServiceHandle);
  85. UnlockServiceDatabase(ServicesDatabaseLock);
  86. CloseServiceHandle(ServiceHandle);
  87. } else {
  88. /*
  89. * It's possible there was no services entry so the driver
  90. * wasn't really installed after all.
  91. */
  92. LONG Error = GetLastError();
  93. if (Error == ERROR_FILE_NOT_FOUND ||
  94. Error == ERROR_PATH_NOT_FOUND ||
  95. Error == ERROR_SERVICE_DOES_NOT_EXIST) {
  96. Status = TRUE;
  97. }
  98. }
  99. CloseServiceHandle(SCManagerHandle);
  100. return Status;
  101. }
  102. /*
  103. ** PostRemove()
  104. **
  105. ** Mark an installed driver for removal later AND remove the driver's entry
  106. ** in SYSTEM.INI to avoid conflicts when we add or remove later.
  107. */
  108. LONG PostRemove(HWND hWnd, PIDRIVER pIDriver, BOOL bLookAtRelated,
  109. int iIndexMain)
  110. {
  111. char *keystr;
  112. char allkeystr[MAXSTR];
  113. char szfile[MAX_PATH];
  114. HANDLE hDriver;
  115. LONG Status = DRVCNF_CANCEL;
  116. PSTR pstr;
  117. GetPrivateProfileString(pIDriver->szSection,
  118. pIDriver->szAlias,
  119. pIDriver->szFile,
  120. pIDriver->szFile,
  121. MAX_PATH,
  122. szSysIni);
  123. /*
  124. * Remove parameters from file name
  125. */
  126. for ( pstr=pIDriver->szFile; *pstr && (*pstr!=COMMA) &&
  127. (*pstr!=SPACE); pstr++ )
  128. ;
  129. *pstr = '\0';
  130. if (bLookAtRelated && (!bRelated || pIDriver->bRelated))
  131. strcpy(szRestartDrv, pIDriver->szDesc);
  132. /*
  133. * If it's a kernel driver remove it from the config registry
  134. * and services controller
  135. */
  136. if (pIDriver->KernelDriver) {
  137. Status = RemoveService(pIDriver->szFile) ? DRVCNF_RESTART : DRVCNF_CANCEL;
  138. if (Status == DRVCNF_CANCEL) {
  139. return DRVCNF_CANCEL;
  140. }
  141. } else {
  142. hDriver = OpenDriver(pIDriver->wszAlias, pIDriver->wszSection, 0L);
  143. if (hDriver)
  144. {
  145. /*
  146. * Removal can fail so don't mark as deleted in this case
  147. */
  148. Status = SendDriverMessage(hDriver, DRV_REMOVE, 0L, 0L);
  149. CloseDriver(hDriver, 0L, 0L);
  150. if (Status == DRVCNF_CANCEL) {
  151. return DRVCNF_CANCEL;
  152. }
  153. }
  154. }
  155. SendMessage(hWnd, LB_DELETESTRING, iIndexMain, 0L);
  156. if (bLookAtRelated)
  157. {
  158. char allkeystr[MAXSTR];
  159. if (GetPrivateProfileString(szRelatedDesc, pIDriver->szAlias,
  160. allkeystr, allkeystr, sizeof(allkeystr), szControlIni))
  161. {
  162. int i, iIndex;
  163. BOOL bFound;
  164. PIDRIVER pIDriver;
  165. char szTemp[MAXSTR];
  166. for (i = 1; infParseField(allkeystr, i, szTemp);i++)
  167. {
  168. bFound = FALSE;
  169. iIndex = (int)SendMessage(hWnd, LB_GETCOUNT, 0, 0L);
  170. while ( iIndex-- > 0 && !bFound)
  171. if ( (int)(pIDriver = (PIDRIVER)SendMessage(hWnd, LB_GETITEMDATA, iIndex, 0L)) != LB_ERR) {
  172. if (!FileNameCmp(pIDriver->szFile, szTemp))
  173. {
  174. if (PostRemove(hWnd, pIDriver, FALSE, iIndex)
  175. == DRVCNF_RESTART) {
  176. Status = DRVCNF_RESTART;
  177. }
  178. bFound = TRUE;
  179. }
  180. }
  181. }
  182. }
  183. }
  184. // Remove the driver entry from SYSTEM.INI so you don't
  185. // conflict with other drivers.
  186. GetPrivateProfileString(pIDriver->szSection, NULL, NULL,
  187. allkeystr, sizeof(allkeystr), szSysIni);
  188. keystr = allkeystr;
  189. while (strlen(keystr) > 0)
  190. {
  191. GetPrivateProfileString(pIDriver->szSection, keystr, NULL, szfile, sizeof(szfile), szSysIni);
  192. if (!FileNameCmp(pIDriver->szFile, szfile))
  193. RemoveDriverEntry(keystr, pIDriver->szFile, pIDriver->szSection, bLookAtRelated);
  194. keystr = &keystr[strlen(keystr) + 1];
  195. }
  196. return Status;
  197. }
  198. void RemoveDriverEntry (PSTR szKey, PSTR szFile, PSTR szSection, BOOL bLookAtRelated)
  199. {
  200. /*
  201. * Remove entry for loading driver
  202. */
  203. WritePrivateProfileString(szSection, szKey, NULL, szSysIni);
  204. /*
  205. * Delete entry for parameters for this driver
  206. */
  207. WriteProfileString(szFile, szKey, NULL);
  208. /*
  209. * Remove entry which says this is a user driver (as opposed to
  210. * a pre-installed one).
  211. */
  212. WritePrivateProfileString(szUserDrivers, szKey, NULL, szControlIni);
  213. /*
  214. * Remove description
  215. */
  216. WritePrivateProfileString(szDriversDesc, szFile, NULL, szControlIni);
  217. /*
  218. * Remove links to related drivers
  219. */
  220. WritePrivateProfileString(szRelatedDesc, szKey, NULL, szControlIni);
  221. #ifdef DOBOOT
  222. FindBootDriver(szKey);
  223. #endif // DOBOOT
  224. if (bLookAtRelated)
  225. SetValidAlias(szKey, szSection);
  226. }
  227. /*
  228. * SetValidAlias()
  229. *
  230. * Check to see if the alias removed would create a hole in the device
  231. * numbering scheme. If so switch the last device number with the deleted one.
  232. */
  233. BOOL SetValidAlias(PSTR pstrType, PSTR pstrSection)
  234. {
  235. char *keystr;
  236. static char allkeystr[MAXSTR];
  237. static char szExKey[MAXSTR], szExFile[MAXSTR], szExDesc[MAXSTR];
  238. BOOL bfound = FALSE, bExchange = FALSE;
  239. int val, maxval = 0, typelen, len;
  240. /*
  241. * Getting length of alias
  242. */
  243. len = typelen = strlen(pstrType);
  244. // If the last char on the type is a number don't consider it
  245. if (pstrType[typelen -1] > '0' && pstrType[typelen - 1] <= '9')
  246. typelen--;
  247. // Get all the aliases in the drivers section
  248. GetPrivateProfileString(pstrSection, NULL, NULL, allkeystr,
  249. sizeof(allkeystr), szSysIni);
  250. keystr = allkeystr;
  251. while (*keystr != TEXT('\0'))
  252. {
  253. // Compare the root of the aliases
  254. if (!_strnicmp(keystr, pstrType, typelen) && ((keystr[typelen] <= '9' && keystr[typelen] > '0') || keystr[typelen] == TEXT('\0')))
  255. {
  256. //We found a common alias
  257. bfound = TRUE;
  258. val = atoi(&keystr[typelen]);
  259. if (val > maxval)
  260. {
  261. maxval = val;
  262. strcpy(szExKey, keystr);
  263. }
  264. }
  265. //Pointer to next alias
  266. keystr = &keystr[strlen(keystr) + 1];
  267. }
  268. //If we found one
  269. if (bfound)
  270. {
  271. if (len == typelen)
  272. bExchange = TRUE;
  273. else
  274. if (atoi(&pstrType[typelen]) < maxval)
  275. bExchange = TRUE;
  276. // We need to exchange it with the one we found
  277. if (bExchange)
  278. {
  279. //Exchanging the one in the drivers section in system.ini
  280. GetPrivateProfileString(pstrSection, szExKey, NULL, szExFile,
  281. sizeof(szExFile), szSysIni);
  282. WritePrivateProfileString(pstrSection, szExKey, NULL, szSysIni);
  283. WritePrivateProfileString(pstrSection, pstrType, szExFile, szSysIni);
  284. #ifdef TRASHDRIVERDESC
  285. //Exchanging the one in the drivers description section of control.ini
  286. GetPrivateProfileString(szDriversDesc, szExKey, NULL, szExDesc, sizeof(szExFile), szControlIni);
  287. WritePrivateProfileString(szDriversDesc, szExKey, NULL, szControlIni);
  288. WritePrivateProfileString(szDriversDesc, pstrType, szExDesc, szControlIni);
  289. #endif
  290. //If any related drivers were present under old alias switch them
  291. GetPrivateProfileString(szRelatedDesc, szExKey, NULL, szExDesc, sizeof(szExFile), szControlIni);
  292. if (strlen(szExDesc))
  293. {
  294. WritePrivateProfileString(szRelatedDesc, szExKey, NULL, szControlIni);
  295. WritePrivateProfileString(szRelatedDesc, pstrType, szExDesc, szControlIni);
  296. }
  297. //If user installed driver under old alias switch them
  298. GetPrivateProfileString(szUserDrivers, szExKey, NULL, szExDesc, sizeof(szExFile), szControlIni);
  299. if (strlen(szExDesc))
  300. {
  301. WritePrivateProfileString(szUserDrivers, szExKey, NULL, szControlIni);
  302. WritePrivateProfileString(szUserDrivers, pstrType, szExDesc, szControlIni);
  303. }
  304. #ifdef DOBOOT
  305. if (FindBootDriver(szExKey))
  306. {
  307. static char szTemp[MAXSTR];
  308. GetPrivateProfileString(szBoot, szDrivers, szTemp, szTemp,
  309. sizeof(szTemp), szSysIni);
  310. strcat(szTemp, " ");
  311. strcat(szTemp, pstrType);
  312. WritePrivateProfileString(szBoot, szDrivers, szTemp, szSysIni);
  313. }
  314. #endif // DOBOOT
  315. }
  316. }
  317. return(bExchange);
  318. }
  319. #if 0 // Dead code !
  320. /*
  321. * IsOnlyInstance()
  322. *
  323. * Check to see if this is the only occurance of an open driver, so we can
  324. * tell if a DRV_INSTALL message has been sent to the driver yet OR
  325. * if it is the last instance of the driver so we can send a
  326. * DRV_REMOVE message.
  327. */
  328. BOOL IsOnlyInstance( HWND hwndLB, PIDRIVER pIDriver )
  329. {
  330. int iEntries;
  331. PIDRIVER pIDTest;
  332. if (pIDriver == NULL)
  333. return FALSE;
  334. /*
  335. * Check Installed ListBox
  336. */
  337. if ((iEntries = (int)SendMessage(hwndLB, LB_GETCOUNT, 0, 0L)) == LB_ERR)
  338. iEntries = 0;
  339. else
  340. while (iEntries-- > 0)
  341. {
  342. pIDTest = (PIDRIVER)SendMessage(hwndLB,
  343. LB_GETITEMDATA,
  344. iEntries,
  345. 0L);
  346. if (pIDTest == NULL)
  347. continue;
  348. if (pIDriver == pIDTest)
  349. continue;
  350. if (FileNameCmp(pIDTest->szFile,pIDriver->szFile) == 0)
  351. {
  352. return FALSE;
  353. }
  354. }
  355. return TRUE;
  356. }
  357. #endif
  358. int FileNameCmp(char far *pch1, char far *pch2)
  359. {
  360. LPSTR pchEOS;
  361. while (*pch1 == ' ') pch1++; // eat spaces
  362. while (*pch2 == ' ') pch2++; // eat spaces
  363. for (pchEOS = pch1; *pchEOS && *pchEOS != ' '; pchEOS++);
  364. return _strnicmp(pch1, pch2, pchEOS - pch1);
  365. }
  366. #ifdef DOBOOT
  367. PSTR strstri(PSTR pszStr, PSTR pszKey)
  368. {
  369. while (pszStr)
  370. if (!_strnicmp(pszStr, pszKey, lstrlen(pszKey)))
  371. return(pszStr);
  372. else
  373. pszStr++;
  374. return(NULL);
  375. }
  376. /*
  377. * FindBootDriver()
  378. * Checks to see if the driver alias is on the drivers line of the
  379. * boot section. If so the alias is removed from the line.
  380. */
  381. BOOL FindBootDriver(char *szKey)
  382. {
  383. char *ptr;
  384. int wKeyLen = (int)strlen(szKey);
  385. char *endkey;
  386. static char szDriverline[MAXSTR];
  387. GetPrivateProfileString("boot", "drivers", szDriverline, szDriverline,
  388. MAX_PATH, szSysIni);
  389. ptr = strstri(szDriverline, szKey);
  390. if (ptr)
  391. {
  392. if ((((ptr != szDriverline) && (*(ptr - 1) == ' ' )) ||
  393. (ptr == szDriverline)) &&
  394. (*(ptr + wKeyLen) == ' ' || *(ptr + wKeyLen) == NULL))
  395. {
  396. endkey = ptr + wKeyLen;
  397. while (*endkey)
  398. *ptr++ = *endkey++;
  399. *ptr = NULL;
  400. WritePrivateProfileString("boot", "drivers", szDriverline,
  401. szSysIni);
  402. return(TRUE);
  403. }
  404. }
  405. return(FALSE);
  406. }
  407. #endif // DOBOOT