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.

901 lines
27 KiB

  1. /*************************************************************************
  2. *
  3. * INSTALL.C
  4. *
  5. * Copyright (C) Microsoft, 1991, All Rights Reserved.
  6. *
  7. * History:
  8. *
  9. * Thu Oct 17 1991 -by- Sanjaya
  10. * Created. Culled out of drivers.c
  11. *
  12. *************************************************************************/
  13. #include <windows.h>
  14. #include <mmsystem.h>
  15. #include <mmddk.h>
  16. #include <winsvc.h>
  17. #include <memory.h>
  18. #include <string.h>
  19. #include <cpl.h>
  20. #include <cphelp.h>
  21. #include <stdlib.h>
  22. #include "drivers.h"
  23. #include "sulib.h"
  24. BOOL GetValidAlias (HWND, PSTR, PSTR);
  25. BOOL SelectInstalled (HWND, PIDRIVER, LPSTR);
  26. void InitDrvConfigInfo (LPDRVCONFIGINFO, PIDRIVER );
  27. BOOL InstallDrivers (HWND, HWND, PSTR);
  28. void RemoveAlreadyInstalled (PSTR, PSTR);
  29. void CheckIniDrivers (PSTR, PSTR);
  30. void RemoveDriverParams (LPSTR, LPSTR);
  31. /**************************************************************************
  32. *
  33. * InstallDrivers()
  34. *
  35. * Install a driver and set of driver types.
  36. *
  37. * Parameters :
  38. * hwnd - Window handle of the main drivers.cpl windows
  39. * hwndAvail - Handle of the 'available drivers' dialog window
  40. * pstrKey - Key name of the inf section item we are installing
  41. *
  42. * This routine calls itself recursively to install related drivers
  43. * (as listed in the .inf file).
  44. *
  45. **************************************************************************/
  46. BOOL InstallDrivers(HWND hWnd, HWND hWndAvail, PSTR pstrKey)
  47. {
  48. IDRIVER IDTemplate; // temporary for installing, removing, etc.
  49. PIDRIVER pIDriver=NULL;
  50. int n,iIndex;
  51. HWND hWndI;
  52. char szTypes[MAXSTR];
  53. char szType[MAXSTR];
  54. char szParams[MAXSTR];
  55. szTypes[0] = '\0';
  56. hMesgBoxParent = hWndAvail;
  57. /*
  58. * mmAddNewDriver needs a buffer for all types we've actually installed
  59. * User critical errors will pop up a task modal
  60. */
  61. IDTemplate.bRelated = FALSE;
  62. IDTemplate.szRemove[0] = TEXT('\0');
  63. /*
  64. * Do the copying and extract the list of types (WAVE, MIDI, ...)
  65. * and the other driver data
  66. */
  67. if (!mmAddNewDriver(pstrKey, szTypes, &IDTemplate))
  68. return FALSE;
  69. szTypes[lstrlen(szTypes)-1] = '\0'; // Remove space left at end
  70. RemoveAlreadyInstalled(IDTemplate.szFile, IDTemplate.szSection);
  71. /*
  72. * At this point we assume the drivers were actually copied.
  73. * Now we need to add them to the installed list.
  74. * For each driver type we create an IDRIVER and add to the listbox
  75. */
  76. hWndI = GetDlgItem(hWnd, LB_INSTALLED);
  77. for (n = 1; infParseField(szTypes, n, szType); n++)
  78. {
  79. /*
  80. * Find a valid alias for this device (eg Wave2). This is
  81. * used as the key in the [MCI] or [drivers] section.
  82. */
  83. if (GetValidAlias(hWndI, szType, IDTemplate.szSection) == FALSE)
  84. {
  85. /*
  86. * Exceeded the maximum, tell the user
  87. */
  88. PSTR pstrMessage;
  89. char szApp[MAXSTR];
  90. char szMessage[MAXSTR];
  91. LoadString(myInstance,
  92. IDS_CONFIGURE_DRIVER,
  93. szApp,
  94. sizeof(szApp));
  95. LoadString(myInstance,
  96. IDS_TOO_MANY_DRIVERS,
  97. szMessage,
  98. sizeof(szMessage));
  99. if (NULL !=
  100. (pstrMessage =
  101. (PSTR)LocalAlloc(LPTR,
  102. sizeof(szMessage) + lstrlen(szType))))
  103. {
  104. wsprintf(pstrMessage, szMessage, (LPSTR)szType);
  105. MessageBox(hWndAvail,
  106. pstrMessage,
  107. szApp,
  108. MB_OK | MB_ICONEXCLAMATION|MB_TASKMODAL);
  109. LocalFree((HANDLE)pstrMessage);
  110. }
  111. continue;
  112. }
  113. if ( (pIDriver = (PIDRIVER)LocalAlloc(LPTR, sizeof(IDRIVER))) != NULL)
  114. {
  115. /*
  116. * Copy all fields
  117. */
  118. memcpy(pIDriver, &IDTemplate, sizeof(IDRIVER));
  119. strncpy(pIDriver->szAlias, szType, sizeof(pIDriver->szAlias));
  120. pIDriver->szAlias[sizeof(pIDriver->szAlias) - 1] = '\0';
  121. mbstowcs(pIDriver->wszAlias, pIDriver->szAlias, MAX_PATH);
  122. /*
  123. * Want only one instance of each driver to show up in the list
  124. * of installed drivers. Thus for the remaining drivers just
  125. * place an entry in the drivers section of system.ini
  126. */
  127. if ( n > 1) {
  128. if (strlen(szParams) != 0 && !pIDriver->KernelDriver) {
  129. /*
  130. * Write their parameters to a section bearing their
  131. * file name with an alias reflecting their alias
  132. */
  133. WriteProfileString(pIDriver->szFile,
  134. pIDriver->szAlias,
  135. szParams);
  136. }
  137. WritePrivateProfileString(pIDriver->szSection,
  138. pIDriver->szAlias,
  139. pIDriver->szFile,
  140. szSysIni);
  141. } else {
  142. /*
  143. * Add the driver description to our listbox
  144. */
  145. iIndex = (int)SendMessage(hWndI,
  146. LB_ADDSTRING,
  147. 0,
  148. (LONG)pIDriver->szDesc);
  149. if (iIndex >= LB_OKAY) {
  150. /*
  151. * Our PIDRIVER data is our listbox item
  152. */
  153. SendMessage(hWndI, LB_SETITEMDATA, iIndex, (LONG)pIDriver);
  154. /*
  155. * Reduce to just the driver name
  156. */
  157. RemoveDriverParams(pIDriver->szFile, szParams);
  158. mbstowcs(pIDriver->wszFile, pIDriver->szFile, MAX_PATH);
  159. if (strlen(szParams) != 0 && !pIDriver->KernelDriver) {
  160. /*
  161. * Write their parameters to a section bearing their
  162. * file name with an alias reflecting their alias
  163. */
  164. WriteProfileString(pIDriver->szFile,
  165. pIDriver->szAlias,
  166. szParams);
  167. }
  168. WritePrivateProfileString(pIDriver->szSection,
  169. pIDriver->szAlias,
  170. pIDriver->szFile,
  171. szSysIni);
  172. /*
  173. * Call the driver to see if it can be configured
  174. * and configure it if it can be
  175. */
  176. if (!SelectInstalled(hWndAvail, pIDriver, szParams))
  177. {
  178. /*
  179. * Error talking to driver
  180. */
  181. WritePrivateProfileString(pIDriver->szSection,
  182. pIDriver->szAlias,
  183. NULL,
  184. szSysIni);
  185. WriteProfileString(pIDriver->szFile,
  186. pIDriver->szAlias,
  187. NULL);
  188. SendMessage(hWndI, LB_DELETESTRING, iIndex, 0L);
  189. return FALSE;
  190. }
  191. /*
  192. * for displaying the driver desc. in the restart mesg
  193. */
  194. if (!bRelated || pIDriver->bRelated) {
  195. strcpy(szRestartDrv, pIDriver->szDesc);
  196. }
  197. /*
  198. * We need to write out the driver description to the
  199. * control.ini section [Userinstallable.drivers]
  200. * so we can differentiate between user and system drivers
  201. *
  202. * This is tested by the function UserInstalled when
  203. * the user tries to remove a driver and merely
  204. * affects which message the user gets when being
  205. * asked to confirm removal (non user-installed drivers
  206. * are described as being necessary to the system).
  207. */
  208. WritePrivateProfileString(szUserDrivers,
  209. pIDriver->szAlias,
  210. pIDriver->szFile,
  211. szControlIni);
  212. /*
  213. * Update [related.desc] section of control.ini :
  214. *
  215. * ALIAS=driver name list
  216. *
  217. * When the driver whose alias is ALIAS is removed
  218. * the drivers in the name list will also be removed.
  219. * These were the drivers in the related drivers list
  220. * when the driver is installed.
  221. */
  222. WritePrivateProfileString(szRelatedDesc,
  223. pIDriver->szAlias,
  224. pIDriver->szRemove,
  225. szControlIni);
  226. /*
  227. * Cache the description string in control.ini in the
  228. * drivers description section.
  229. *
  230. * The key is the driver file name + extension.
  231. */
  232. WritePrivateProfileString(szDriversDesc,
  233. pIDriver->szFile,
  234. pIDriver->szDesc,
  235. szControlIni);
  236. #ifdef DOBOOT // We don't do the boot section on NT
  237. if (bInstallBootLine) {
  238. szTemp[MAXSTR];
  239. GetPrivateProfileString(szBoot,
  240. szDrivers,
  241. szTemp,
  242. szTemp,
  243. sizeof(szTemp),
  244. szSysIni);
  245. strcat(szTemp, " ");
  246. strcat(szTemp, pIDriver->szAlias);
  247. WritePrivateProfileString(szBoot,
  248. szDrivers,
  249. szTemp,
  250. szSysIni);
  251. bInstallBootLine = FALSE;
  252. }
  253. #endif // DOBOOT
  254. } else {
  255. /*
  256. * Problem getting an alias or adding a driver to the listbox
  257. */
  258. LocalFree((HANDLE)pIDriver);
  259. pIDriver = NULL;
  260. return FALSE; //ERROR
  261. }
  262. }
  263. }
  264. else
  265. return FALSE; //ERROR
  266. }
  267. /*
  268. * If no types were added then fail
  269. */
  270. if (pIDriver == NULL) {
  271. return FALSE;
  272. }
  273. /*
  274. * If there are related drivers listed in the .inf section to install
  275. * then install them now by calling ourselves. Use IDTemplate which
  276. * is where mmAddNewDriver put the data.
  277. */
  278. if (IDTemplate.bRelated == TRUE) {
  279. int i;
  280. char szTemp[MAXSTR];
  281. /*
  282. * Tell file copying to abort rather than put up errors
  283. */
  284. bCopyingRelated = TRUE;
  285. for (i = 1; infParseField(IDTemplate.szRelated, i, szTemp);i++) {
  286. InstallDrivers(hWnd, hWndAvail, szTemp);
  287. }
  288. }
  289. return TRUE;
  290. }
  291. /************************************************************************
  292. *
  293. * SelectInstalled()
  294. *
  295. * Check if the driver can be configured and configure it if it can be.
  296. *
  297. * hwnd - Our window - parent for driver to make its config window
  298. * pIDriver - info about the driver
  299. * params - the drivers parameters from the .inf file.
  300. *
  301. * Returns FALSE if an error occurred, otherwise TRUE
  302. *
  303. ************************************************************************/
  304. BOOL SelectInstalled(HWND hwnd, PIDRIVER pIDriver, LPSTR pszParams)
  305. {
  306. DRVCONFIGINFO DrvConfigInfo;
  307. HANDLE hDriver;
  308. BOOL Success = FALSE;
  309. DWORD dwTagId;
  310. wsStartWait();
  311. /*
  312. * If it's a kernel driver call the services controller to
  313. * install the driver
  314. */
  315. if (pIDriver->KernelDriver) {
  316. SC_HANDLE SCManagerHandle;
  317. SC_HANDLE ServiceHandle;
  318. char ServiceName[MAX_PATH];
  319. char BinaryPath[MAX_PATH];
  320. /*
  321. * These drivers are not configurable
  322. */
  323. pIDriver->fQueryable = 0;
  324. /*
  325. * The services controller will create the registry node to
  326. * which we can add the device parameters value
  327. */
  328. strcpy(BinaryPath, "\\SystemRoot\\system32\\drivers\\");
  329. strcat(BinaryPath, pIDriver->szFile);
  330. /*
  331. * First try and obtain a handle to the service controller
  332. */
  333. SCManagerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  334. if (SCManagerHandle != NULL) {
  335. SC_LOCK ServicesDatabaseLock;
  336. /*
  337. * Lock the service controller database to avoid deadlocks
  338. * we have to loop because we can't wait
  339. */
  340. for (ServicesDatabaseLock = NULL;
  341. (ServicesDatabaseLock =
  342. LockServiceDatabase(SCManagerHandle))
  343. == NULL;
  344. Sleep(100)) {
  345. }
  346. {
  347. char drive[MAX_PATH], directory[MAX_PATH], ext[MAX_PATH];
  348. _splitpath(pIDriver->szFile, drive, directory, ServiceName, ext);
  349. }
  350. ServiceHandle = CreateService(SCManagerHandle,
  351. ServiceName,
  352. NULL,
  353. SERVICE_ALL_ACCESS,
  354. SERVICE_KERNEL_DRIVER,
  355. SERVICE_DEMAND_START,
  356. SERVICE_ERROR_NORMAL,
  357. BinaryPath,
  358. "Base",
  359. &dwTagId,
  360. "\0",
  361. NULL,
  362. NULL);
  363. UnlockServiceDatabase(ServicesDatabaseLock);
  364. if (ServiceHandle != NULL) {
  365. /*
  366. * Try to write the parameters to the registry if there
  367. * are any
  368. */
  369. if (strlen(pszParams)) {
  370. HKEY ParmsKey;
  371. char RegPath[MAX_PATH];
  372. strcpy(RegPath, "\\SYSTEM\\CurrentControlSet\\Services\\");
  373. strcat(RegPath, ServiceName);
  374. strcat(RegPath, "\\Parameters");
  375. Success = RegCreateKey(HKEY_LOCAL_MACHINE,
  376. RegPath,
  377. &ParmsKey) == ERROR_SUCCESS &&
  378. RegSetValue(ParmsKey,
  379. "",
  380. REG_SZ,
  381. pszParams,
  382. strlen(pszParams)) == ERROR_SUCCESS &&
  383. RegCloseKey(ParmsKey) == ERROR_SUCCESS;
  384. } else {
  385. Success = TRUE;
  386. }
  387. /*
  388. * Service created so try and start it
  389. */
  390. if (Success) {
  391. /*
  392. * We tell them to restart just in case
  393. */
  394. bRestart = TRUE;
  395. /*
  396. * Load the kernel driver by starting the service.
  397. * If this is successful it should be safe to let
  398. * the system load the driver at system start so
  399. * we change the start type.
  400. */
  401. Success =
  402. StartService(ServiceHandle, 0, NULL) &&
  403. ChangeServiceConfig(ServiceHandle,
  404. SERVICE_NO_CHANGE,
  405. SERVICE_SYSTEM_START,
  406. SERVICE_NO_CHANGE,
  407. NULL,
  408. NULL,
  409. NULL,
  410. NULL,
  411. NULL,
  412. NULL,
  413. NULL);
  414. if (!Success) {
  415. char szMesg[MAXSTR];
  416. char szMesg2[MAXSTR];
  417. char szTitle[50];
  418. /*
  419. * Uninstall driver if we couldn't load it
  420. */
  421. for (ServicesDatabaseLock = NULL;
  422. (ServicesDatabaseLock =
  423. LockServiceDatabase(SCManagerHandle))
  424. == NULL;
  425. Sleep(100)) {
  426. }
  427. DeleteService(ServiceHandle);
  428. UnlockServiceDatabase(ServicesDatabaseLock);
  429. /*
  430. * Tell the user there was a configuration error
  431. * (our best guess).
  432. */
  433. LoadString(myInstance, IDS_DRIVER_CONFIG_ERROR, szMesg, sizeof(szMesg));
  434. LoadString(myInstance, IDS_CONFIGURE_DRIVER, szTitle, sizeof(szTitle));
  435. wsprintf(szMesg2, szMesg, FileName(pIDriver->szFile));
  436. MessageBox(hMesgBoxParent, szMesg2, szTitle, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
  437. }
  438. }
  439. CloseServiceHandle(ServiceHandle);
  440. }
  441. CloseServiceHandle(SCManagerHandle);
  442. }
  443. } else {
  444. /*
  445. * Put up a message if the driver can't be loaded or doesn't
  446. * respond favourably to the DRV_INSTALL message.
  447. */
  448. BOOL bPutUpMessage;
  449. bPutUpMessage = FALSE;
  450. /*
  451. * See if we can open the driver
  452. */
  453. hDriver = OpenDriver(pIDriver->wszFile, NULL, 0L);
  454. if (hDriver)
  455. {
  456. Success = TRUE;
  457. InitDrvConfigInfo(&DrvConfigInfo, pIDriver);
  458. /*
  459. * See if activating the driver will require restarting the
  460. * system.
  461. *
  462. * Also check the driver wants to install (it may not
  463. * have the right privilege level).
  464. */
  465. switch (SendDriverMessage(hDriver,
  466. DRV_INSTALL,
  467. 0L,
  468. (LONG)(LPDRVCONFIGINFO)&DrvConfigInfo))
  469. {
  470. case DRVCNF_RESTART:
  471. bRestart = TRUE;
  472. break;
  473. case DRVCNF_CANCEL:
  474. /*
  475. * The driver did not want to install
  476. */
  477. bPutUpMessage = TRUE;
  478. Success = FALSE;
  479. break;
  480. }
  481. /*
  482. * Remember whether the driver is configurable
  483. */
  484. pIDriver->fQueryable =
  485. (int)SendDriverMessage(hDriver,
  486. DRV_QUERYCONFIGURE,
  487. 0L,
  488. 0L);
  489. /*
  490. * If the driver is configurable then configure it.
  491. * Configuring the driver may result in a need to restart
  492. * the system. The user may also cancel install.
  493. */
  494. if (pIDriver->fQueryable) {
  495. switch (SendDriverMessage(
  496. hDriver,
  497. DRV_CONFIGURE,
  498. (LONG)hwnd,
  499. (LONG)(LPDRVCONFIGINFO)&DrvConfigInfo)) {
  500. case DRVCNF_RESTART:
  501. bRestart = TRUE;
  502. break;
  503. case DRVCNF_CANCEL:
  504. /*
  505. * Don't put up the error box if the user cancelled
  506. */
  507. Success = FALSE;
  508. break;
  509. }
  510. }
  511. CloseDriver(hDriver, 0L, 0L);
  512. } else {
  513. bPutUpMessage = TRUE;
  514. Success = FALSE;
  515. }
  516. if (bPutUpMessage) {
  517. /*
  518. * If dealing with the driver resulted in error then put
  519. * up a message
  520. */
  521. OpenDriverError(hwnd, pIDriver->szDesc, pIDriver->szFile);
  522. }
  523. }
  524. wsEndWait();
  525. return Success;
  526. }
  527. /***********************************************************************
  528. *
  529. * InitDrvConfigInfo()
  530. *
  531. * Initialize Driver Configuration Information.
  532. *
  533. ***********************************************************************/
  534. void InitDrvConfigInfo( LPDRVCONFIGINFO lpDrvConfigInfo, PIDRIVER pIDriver )
  535. {
  536. lpDrvConfigInfo->dwDCISize = sizeof(DRVCONFIGINFO);
  537. lpDrvConfigInfo->lpszDCISectionName = pIDriver->wszSection;
  538. lpDrvConfigInfo->lpszDCIAliasName = pIDriver->wszAlias;
  539. }
  540. /***********************************************************************
  541. *
  542. * GetValidAlias()
  543. *
  544. * hwnd - Window handle - not used
  545. * pstrType - Input - the type
  546. * Output - New alias for that type
  547. *
  548. * pstrSection - The system.ini section we're dealing with
  549. *
  550. * Create a valid alias name for a type. Searches the system.ini file
  551. * in the drivers section for aliases of the type already defined and
  552. * returns a new alias (eg WAVE1).
  553. *
  554. ***********************************************************************/
  555. BOOL GetValidAlias(HWND hwnd, PSTR pstrType, PSTR pstrSection)
  556. {
  557. #define MAXDRVTYPES 10
  558. char *keystr;
  559. char allkeystr[MAXSTR];
  560. BOOL found = FALSE;
  561. int val, maxval = 0, typelen;
  562. typelen = strlen(pstrType);
  563. GetPrivateProfileString(pstrSection, NULL, NULL, allkeystr,
  564. sizeof(allkeystr), szSysIni);
  565. keystr = allkeystr;
  566. /*
  567. * See if we have driver if this type already installed by searching
  568. * our the [drivers] section.
  569. */
  570. while (*keystr != '\0')
  571. {
  572. if (!_strnicmp(keystr, pstrType, typelen) && ((keystr[typelen] > '0' &&
  573. keystr[typelen] <= '9') ||
  574. keystr[typelen] == TEXT('\0') ))
  575. {
  576. found = TRUE;
  577. val = atoi(&keystr[typelen]);
  578. if (val > maxval)
  579. maxval = val;
  580. }
  581. keystr = &keystr[strlen(keystr) + 1];
  582. }
  583. if (found)
  584. {
  585. if (maxval == MAXDRVTYPES)
  586. return FALSE; // too many of my type!
  587. pstrType[typelen] = (char)(maxval + '1');
  588. pstrType[typelen+1] = '\0';
  589. }
  590. return TRUE;
  591. }
  592. /*******************************************************************
  593. *
  594. * IsConfigurable
  595. *
  596. * Find if a driver supports configuration
  597. *
  598. *******************************************************************/
  599. BOOL IsConfigurable(PIDRIVER pIDriver, HWND hwnd)
  600. {
  601. HANDLE hDriver;
  602. wsStartWait();
  603. /*
  604. * have we ever checked if this driver is queryable?
  605. */
  606. if ( pIDriver->fQueryable == -1 )
  607. {
  608. /*
  609. * Check it's not a kernel driver
  610. */
  611. if (pIDriver->KernelDriver) {
  612. pIDriver->fQueryable = 0;
  613. } else {
  614. /*
  615. * Open the driver and ask it if it is configurable
  616. */
  617. hDriver = OpenDriver(pIDriver->wszAlias, pIDriver->wszSection, 0L);
  618. if (hDriver)
  619. {
  620. pIDriver->fQueryable =
  621. (int)SendDriverMessage(hDriver,
  622. DRV_QUERYCONFIGURE,
  623. 0L,
  624. 0L);
  625. CloseDriver(hDriver, 0L, 0L);
  626. }
  627. else
  628. {
  629. pIDriver->fQueryable = 0;
  630. OpenDriverError(hwnd, pIDriver->szDesc, pIDriver->szFile);
  631. wsEndWait();
  632. return(FALSE);
  633. }
  634. }
  635. }
  636. wsEndWait();
  637. return((BOOL)pIDriver->fQueryable);
  638. }
  639. /******************************************************************
  640. *
  641. * Find any driver with the same name currently installed and
  642. * remove it
  643. *
  644. * szFile - File name of driver
  645. * szSection - system.ini section ([MCI] or [drivers]).
  646. *
  647. ******************************************************************/
  648. void RemoveAlreadyInstalled(PSTR szFile, PSTR szSection)
  649. {
  650. int iIndex;
  651. PIDRIVER pIDriver;
  652. iIndex = (int)SendMessage(hlistbox, LB_GETCOUNT, 0, 0L);
  653. while ( iIndex-- > 0) {
  654. pIDriver = (PIDRIVER)SendMessage(hlistbox, LB_GETITEMDATA, iIndex, 0L);
  655. if ( (int)pIDriver != LB_ERR) {
  656. if (!FileNameCmp(pIDriver->szFile, szFile)) {
  657. PostRemove(hlistbox, pIDriver, FALSE, iIndex);
  658. return;
  659. }
  660. }
  661. }
  662. CheckIniDrivers(szFile, szSection);
  663. }
  664. /******************************************************************
  665. *
  666. * Remove system.ini file entries for our driver
  667. *
  668. * szFile - driver file name
  669. * szSection - [drivers] or [MCI]
  670. *
  671. ******************************************************************/
  672. void CheckIniDrivers(PSTR szFile, PSTR szSection)
  673. {
  674. char allkeystr[MAXSTR * 2];
  675. char szRemovefile[20];
  676. char *keystr;
  677. GetPrivateProfileString(szSection,
  678. NULL,
  679. NULL,
  680. allkeystr,
  681. sizeof(allkeystr),
  682. szSysIni);
  683. keystr = allkeystr;
  684. while (strlen(keystr) > 0)
  685. {
  686. GetPrivateProfileString(szSection,
  687. keystr,
  688. NULL,
  689. szRemovefile,
  690. sizeof(szRemovefile),
  691. szSysIni);
  692. if (!FileNameCmp(szFile, szRemovefile))
  693. RemoveDriverEntry(keystr, szFile, szSection, FALSE);
  694. keystr = &keystr[strlen(keystr) + 1];
  695. }
  696. }
  697. /******************************************************************
  698. *
  699. * RemoveDriverParams
  700. *
  701. * Remove anything after the next token
  702. *
  703. ******************************************************************/
  704. void RemoveDriverParams(LPSTR szFile, LPSTR Params)
  705. {
  706. for(;*szFile == ' '; szFile++);
  707. for(;*szFile != ' ' && *szFile != '\0'; szFile++);
  708. if (*szFile == ' ') {
  709. *szFile = '\0';
  710. for (;*++szFile == ' ';);
  711. strcpy(Params, szFile);
  712. } else {
  713. *Params = '\0';
  714. }
  715. }