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.

1904 lines
62 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 <regstr.h>
  21. #include <infstr.h>
  22. #include <cphelp.h>
  23. #include <stdlib.h>
  24. #include "drivers.h"
  25. #include "sulib.h"
  26. #include "debug.h"
  27. BOOL GetValidAlias (LPTSTR, LPTSTR);
  28. BOOL SelectInstalled (HWND, PIDRIVER, LPTSTR, HDEVINFO, PSP_DEVINFO_DATA);
  29. void InitDrvConfigInfo (LPDRVCONFIGINFO, PIDRIVER );
  30. BOOL InstallDrivers (HWND, HWND, LPTSTR);
  31. void RemoveAlreadyInstalled (LPTSTR, LPTSTR);
  32. void CheckIniDrivers (LPTSTR, LPTSTR);
  33. void RemoveDriverParams (LPTSTR, LPTSTR);
  34. void InsertNewIDriverNodeInList(PIDRIVER *, PIDRIVER);
  35. void DestroyIDriverNodeList(PIDRIVER, BOOL, BOOL);
  36. /*
  37. ***************************************************************
  38. * Global strings
  39. ***************************************************************
  40. */
  41. CONST TCHAR gszDriversSubkeyName[] = TEXT("Drivers");
  42. CONST TCHAR gszSubClassesValue[] = TEXT("SubClasses");
  43. CONST TCHAR gszDescriptionValue[] = TEXT("Description");
  44. CONST TCHAR gszDriverValue[] = TEXT("Driver");
  45. static CONST TCHAR gszAliasValue[] = TEXT("Alias");
  46. static CONST TCHAR gszAliasWOW64Value[] = TEXT("AliasWOW64");
  47. static CONST TCHAR gszWaveWOW64Value[] = TEXT("WOW64");
  48. /**************************************************************************
  49. *
  50. * InstallDrivers()
  51. *
  52. * Install a driver and set of driver types.
  53. *
  54. * Parameters :
  55. * hwnd - Window handle of the main drivers.cpl windows
  56. * hwndAvail - Handle of the 'available drivers' dialog window
  57. * pstrKey - Key name of the inf section item we are installing
  58. *
  59. * This routine calls itself recursively to install related drivers
  60. * (as listed in the .inf file).
  61. *
  62. **************************************************************************/
  63. BOOL InstallDrivers(HWND hWnd, HWND hWndAvail, LPTSTR pstrKey)
  64. {
  65. IDRIVER IDTemplate; // temporary for installing, removing, etc.
  66. PIDRIVER pIDriver=NULL;
  67. int n;
  68. TCHAR szTypes[MAXSTR];
  69. TCHAR szType[MAXSTR];
  70. TCHAR szParams[MAXSTR];
  71. szTypes[0] = TEXT('\0');
  72. hMesgBoxParent = hWndAvail;
  73. /*
  74. * mmAddNewDriver needs a buffer for all types we've actually installed
  75. * User critical errors will pop up a task modal
  76. */
  77. IDTemplate.bRelated = FALSE;
  78. IDTemplate.szRemove[0] = TEXT('\0');
  79. /*
  80. * Do the copying and extract the list of types (WAVE, MIDI, ...)
  81. * and the other driver data
  82. */
  83. if (!mmAddNewDriver(pstrKey, szTypes, &IDTemplate))
  84. return FALSE;
  85. szTypes[lstrlen(szTypes)-1] = TEXT('\0'); // Remove space left at end
  86. RemoveAlreadyInstalled(IDTemplate.szFile, IDTemplate.szSection);
  87. /*
  88. * At this point we assume the drivers were actually copied.
  89. * Now we need to add them to the installed list.
  90. * For each driver type we create an IDRIVER and add to the listbox
  91. */
  92. for (n = 1; infParseField(szTypes, n, szType); n++)
  93. {
  94. /*
  95. * Find a valid alias for this device (eg Wave2). This is
  96. * used as the key in the [MCI] or [drivers] section.
  97. */
  98. if (GetValidAlias(szType, IDTemplate.szSection) == FALSE)
  99. {
  100. /*
  101. * Exceeded the maximum, tell the user
  102. */
  103. LPTSTR pstrMessage;
  104. TCHAR szApp[MAXSTR];
  105. TCHAR szMessage[MAXSTR];
  106. LoadString(myInstance,
  107. IDS_CONFIGURE_DRIVER,
  108. szApp,
  109. sizeof(szApp)/sizeof(TCHAR));
  110. LoadString(myInstance,
  111. IDS_TOO_MANY_DRIVERS,
  112. szMessage,
  113. sizeof(szMessage)/sizeof(TCHAR));
  114. if (NULL !=
  115. (pstrMessage =
  116. (LPTSTR)LocalAlloc(LPTR,
  117. sizeof(szMessage) + (lstrlen(szType)*sizeof(TCHAR)))))
  118. {
  119. wsprintf(pstrMessage, szMessage, (LPTSTR)szType);
  120. MessageBox(hWndAvail,
  121. pstrMessage,
  122. szApp,
  123. MB_OK | MB_ICONEXCLAMATION|MB_TASKMODAL);
  124. LocalFree((HANDLE)pstrMessage);
  125. }
  126. continue;
  127. }
  128. if ( (pIDriver = (PIDRIVER)LocalAlloc(LPTR, sizeof(IDRIVER))) != NULL)
  129. {
  130. /*
  131. * Copy all fields
  132. */
  133. memcpy(pIDriver, &IDTemplate, sizeof(IDRIVER));
  134. wcsncpy(pIDriver->szAlias, szType, sizeof(pIDriver->szAlias)/sizeof(TCHAR));
  135. pIDriver->szAlias[sizeof(pIDriver->szAlias)/sizeof(TCHAR) - 1] = TEXT('\0');
  136. wcscpy(pIDriver->wszAlias, pIDriver->szAlias);
  137. /*
  138. * Want only one instance of each driver to show up in the list
  139. * of installed drivers. Thus for the remaining drivers just
  140. * place an entry in the drivers section of system.ini
  141. */
  142. if ( n > 1)
  143. {
  144. if (wcslen(szParams) != 0 && !pIDriver->KernelDriver)
  145. {
  146. /*
  147. * Write their parameters to a section bearing their
  148. * file name with an alias reflecting their alias
  149. */
  150. WriteProfileString(pIDriver->szFile,
  151. pIDriver->szAlias,
  152. szParams);
  153. }
  154. WritePrivateProfileString(pIDriver->szSection,
  155. pIDriver->szAlias,
  156. pIDriver->szFile,
  157. szSysIni);
  158. }
  159. else
  160. {
  161. /*
  162. * Reduce to just the driver name
  163. */
  164. RemoveDriverParams(pIDriver->szFile, szParams);
  165. wcscpy(pIDriver->wszFile, pIDriver->szFile);
  166. if (wcslen(szParams) != 0 && !pIDriver->KernelDriver)
  167. {
  168. /*
  169. * Write their parameters to a section bearing their
  170. * file name with an alias reflecting their alias
  171. */
  172. WriteProfileString(pIDriver->szFile,
  173. pIDriver->szAlias,
  174. szParams);
  175. }
  176. WritePrivateProfileString(pIDriver->szSection,
  177. pIDriver->szAlias,
  178. pIDriver->szFile,
  179. szSysIni);
  180. /*
  181. * Call the driver to see if it can be configured
  182. * and configure it if it can be
  183. */
  184. if (!SelectInstalled(hWndAvail, pIDriver, szParams, INVALID_HANDLE_VALUE, NULL))
  185. {
  186. /*
  187. * Error talking to driver
  188. */
  189. WritePrivateProfileString(pIDriver->szSection,
  190. pIDriver->szAlias,
  191. NULL,
  192. szSysIni);
  193. WriteProfileString(pIDriver->szFile,
  194. pIDriver->szAlias,
  195. NULL);
  196. RemoveIDriver (hAdvDlgTree, pIDriver, TRUE);
  197. return FALSE;
  198. }
  199. /*
  200. * for displaying the driver desc. in the restart mesg
  201. */
  202. if (!bRelated || pIDriver->bRelated)
  203. {
  204. wcscpy(szRestartDrv, pIDriver->szDesc);
  205. }
  206. /*
  207. * We need to write out the driver description to the
  208. * control.ini section [Userinstallable.drivers]
  209. * so we can differentiate between user and system drivers
  210. *
  211. * This is tested by the function UserInstalled when
  212. * the user tries to remove a driver and merely
  213. * affects which message the user gets when being
  214. * asked to confirm removal (non user-installed drivers
  215. * are described as being necessary to the system).
  216. */
  217. WritePrivateProfileString(szUserDrivers,
  218. pIDriver->szAlias,
  219. pIDriver->szFile,
  220. szControlIni);
  221. /*
  222. * Update [related.desc] section of control.ini :
  223. *
  224. * ALIAS=driver name list
  225. *
  226. * When the driver whose alias is ALIAS is removed
  227. * the drivers in the name list will also be removed.
  228. * These were the drivers in the related drivers list
  229. * when the driver is installed.
  230. */
  231. WritePrivateProfileString(szRelatedDesc,
  232. pIDriver->szAlias,
  233. pIDriver->szRemove,
  234. szControlIni);
  235. /*
  236. * Cache the description string in control.ini in the
  237. * drivers description section.
  238. *
  239. * The key is the driver file name + extension.
  240. */
  241. WritePrivateProfileString(szDriversDesc,
  242. pIDriver->szFile,
  243. pIDriver->szDesc,
  244. szControlIni);
  245. #ifdef DOBOOT // We don't do the boot section on NT
  246. if (bInstallBootLine)
  247. {
  248. szTemp[MAXSTR];
  249. GetPrivateProfileString(szBoot,
  250. szDrivers,
  251. szTemp,
  252. szTemp,
  253. sizeof(szTemp) / sizeof(TCHAR),
  254. szSysIni);
  255. wcscat(szTemp, TEXT(" "));
  256. wcscat(szTemp, pIDriver->szAlias);
  257. WritePrivateProfileString(szBoot,
  258. szDrivers,
  259. szTemp,
  260. szSysIni);
  261. bInstallBootLine = FALSE;
  262. }
  263. #endif // DOBOOT
  264. }
  265. }
  266. else
  267. return FALSE; //ERROR
  268. }
  269. /*
  270. * If no types were added then fail
  271. */
  272. if (pIDriver == NULL)
  273. {
  274. return FALSE;
  275. }
  276. /*
  277. * If there are related drivers listed in the .inf section to install
  278. * then install them now by calling ourselves. Use IDTemplate which
  279. * is where mmAddNewDriver put the data.
  280. */
  281. if (IDTemplate.bRelated == TRUE)
  282. {
  283. int i;
  284. TCHAR szTemp[MAXSTR];
  285. /*
  286. * Tell file copying to abort rather than put up errors
  287. */
  288. bCopyingRelated = TRUE;
  289. for (i = 1; infParseField(IDTemplate.szRelated, i, szTemp);i++)
  290. {
  291. InstallDrivers(hWnd, hWndAvail, szTemp);
  292. }
  293. }
  294. return TRUE;
  295. }
  296. BOOL SelectInstalledKernelDriver(PIDRIVER pIDriver, LPTSTR pszParams)
  297. {
  298. SC_HANDLE SCManagerHandle;
  299. SC_HANDLE ServiceHandle;
  300. TCHAR ServiceName[MAX_PATH];
  301. TCHAR BinaryPath[MAX_PATH];
  302. BOOL Success;
  303. SC_LOCK ServicesDatabaseLock;
  304. DWORD dwTagId;
  305. /*
  306. * These drivers are not configurable
  307. */
  308. pIDriver->fQueryable = 0;
  309. /*
  310. * The services controller will create the registry node to
  311. * which we can add the device parameters value
  312. */
  313. wcscpy(BinaryPath, TEXT("\\SystemRoot\\system32\\drivers\\"));
  314. wcscat(BinaryPath, pIDriver->szFile);
  315. /*
  316. * First try and obtain a handle to the service controller
  317. */
  318. SCManagerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  319. if (SCManagerHandle == NULL)
  320. return FALSE;
  321. /*
  322. * Lock the service controller database to avoid deadlocks
  323. * we have to loop because we can't wait
  324. */
  325. for (ServicesDatabaseLock = NULL;
  326. (ServicesDatabaseLock =
  327. LockServiceDatabase(SCManagerHandle))
  328. == NULL;
  329. Sleep(100))
  330. {
  331. }
  332. {
  333. TCHAR drive[MAX_PATH], directory[MAX_PATH], ext[MAX_PATH];
  334. lsplitpath(pIDriver->szFile, drive, directory, ServiceName, ext);
  335. }
  336. ServiceHandle = CreateService(SCManagerHandle,
  337. ServiceName,
  338. NULL,
  339. SERVICE_ALL_ACCESS,
  340. SERVICE_KERNEL_DRIVER,
  341. SERVICE_DEMAND_START,
  342. SERVICE_ERROR_NORMAL,
  343. BinaryPath,
  344. TEXT("Base"),
  345. &dwTagId,
  346. TEXT("\0"),
  347. NULL,
  348. NULL);
  349. UnlockServiceDatabase(ServicesDatabaseLock);
  350. if (ServiceHandle == NULL)
  351. {
  352. CloseServiceHandle(SCManagerHandle);
  353. return FALSE;
  354. }
  355. /*
  356. * Try to write the parameters to the registry if there
  357. * are any
  358. */
  359. if (wcslen(pszParams))
  360. {
  361. HKEY ParmsKey;
  362. TCHAR RegPath[MAX_PATH];
  363. wcscpy(RegPath, TEXT("\\SYSTEM\\CurrentControlSet\\Services\\"));
  364. wcscat(RegPath, ServiceName);
  365. wcscat(RegPath, TEXT("\\Parameters"));
  366. Success = RegCreateKey(HKEY_LOCAL_MACHINE,
  367. RegPath,
  368. &ParmsKey) == ERROR_SUCCESS &&
  369. RegSetValue(ParmsKey,
  370. TEXT(""),
  371. REG_SZ,
  372. pszParams,
  373. wcslen(pszParams)*sizeof(TCHAR)) == ERROR_SUCCESS &&
  374. RegCloseKey(ParmsKey) == ERROR_SUCCESS;
  375. }
  376. else
  377. {
  378. Success = TRUE;
  379. }
  380. /*
  381. * Service created so try and start it
  382. */
  383. if (Success)
  384. {
  385. // We tell them to restart just in case
  386. bRestart = TRUE;
  387. /*
  388. * Load the kernel driver by starting the service.
  389. * If this is successful it should be safe to let
  390. * the system load the driver at system start so
  391. * we change the start type.
  392. */
  393. Success =
  394. StartService(ServiceHandle, 0, NULL) &&
  395. ChangeServiceConfig(ServiceHandle,
  396. SERVICE_NO_CHANGE,
  397. SERVICE_SYSTEM_START,
  398. SERVICE_NO_CHANGE,
  399. NULL,
  400. NULL,
  401. NULL,
  402. NULL,
  403. NULL,
  404. NULL,
  405. NULL);
  406. if (!Success)
  407. {
  408. TCHAR szMesg[MAXSTR];
  409. TCHAR szMesg2[MAXSTR];
  410. TCHAR szTitle[50];
  411. /*
  412. * Uninstall driver if we couldn't load it
  413. */
  414. for (ServicesDatabaseLock = NULL;
  415. (ServicesDatabaseLock =
  416. LockServiceDatabase(SCManagerHandle))
  417. == NULL;
  418. Sleep(100))
  419. {
  420. }
  421. DeleteService(ServiceHandle);
  422. UnlockServiceDatabase(ServicesDatabaseLock);
  423. /*
  424. * Tell the user there was a configuration error
  425. * (our best guess).
  426. */
  427. LoadString(myInstance, IDS_DRIVER_CONFIG_ERROR, szMesg, sizeof(szMesg)/sizeof(TCHAR));
  428. LoadString(myInstance, IDS_CONFIGURE_DRIVER, szTitle, sizeof(szTitle)/sizeof(TCHAR));
  429. wsprintf(szMesg2, szMesg, FileName(pIDriver->szFile));
  430. MessageBox(hMesgBoxParent, szMesg2, szTitle, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
  431. }
  432. }
  433. CloseServiceHandle(ServiceHandle);
  434. CloseServiceHandle(SCManagerHandle);
  435. return Success;
  436. }
  437. /************************************************************************
  438. *
  439. * SelectInstalled()
  440. *
  441. * Check if the driver can be configured and configure it if it can be.
  442. *
  443. * hwnd - Our window - parent for driver to make its config window
  444. * pIDriver - info about the driver
  445. * params - the drivers parameters from the .inf file.
  446. * DeviceInfoSet - Optionally, specifies the set containing the PnP device
  447. * being installed. Specify INVALID_HANDLE_VALUE is this
  448. * parameter is not present.
  449. * DeviceInfoData - Optionally, specifies the PnP device being installed
  450. * (ignored if DeviceInfoSet is not specified).
  451. *
  452. * Returns FALSE if an error occurred, otherwise TRUE. GetLastError() may
  453. * be called to determine the cause of the failure.
  454. *
  455. ************************************************************************/
  456. BOOL SelectInstalled(HWND hwnd, PIDRIVER pIDriver, LPTSTR pszParams, HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData)
  457. {
  458. BOOL bSuccess = TRUE; // Assume we succeed
  459. BOOL bPutUpMessage = FALSE; // Assume we don't have to put up a message
  460. HANDLE hDriver = 0;
  461. DRVCONFIGINFO DrvConfigInfo;
  462. DWORD_PTR DrvMsgResult;
  463. DWORD ConfigFlags;
  464. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  465. HKEY hkDrv = NULL;
  466. // Open device reg key
  467. hkDrv = SetupDiOpenDevRegKey(DeviceInfoSet,
  468. DeviceInfoData,
  469. DICS_FLAG_GLOBAL,
  470. 0,
  471. DIREG_DRV,
  472. KEY_ALL_ACCESS);
  473. if (!hkDrv)
  474. {
  475. return GetLastError();
  476. }
  477. wsStartWait();
  478. /*
  479. * If it's a kernel driver call the services controller to
  480. * install the driver (unless it's a PnP device, in which case
  481. * SetupDiInstallDevice would've already handled any necessary
  482. * service installation).
  483. */
  484. if (pIDriver->KernelDriver)
  485. {
  486. // If DeviceInfoSet is a valid handle, then this is a PnP device
  487. // and there's nothing we need to do. Otherwise, config the kernel driver.
  488. if (DeviceInfoSet == INVALID_HANDLE_VALUE)
  489. bSuccess = SelectInstalledKernelDriver(pIDriver,pszParams);
  490. goto SelectInstalled_exit;
  491. }
  492. // See if we can open the driver
  493. hDriver = OpenDriver(pIDriver->wszFile, NULL, 0L);
  494. if (!hDriver)
  495. {
  496. bSuccess = FALSE;
  497. bPutUpMessage = TRUE;
  498. goto SelectInstalled_exit;
  499. }
  500. // Driver opened, prepare to send config messages to driver
  501. InitDrvConfigInfo(&DrvConfigInfo, pIDriver);
  502. // On ISAPNP devices, we need to set the CONFIGFLAG_NEEDS_FORCED_CONFIG before
  503. // we call into the driver to setup resources.
  504. if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
  505. DeviceInfoData,
  506. SPDRP_CONFIGFLAGS,
  507. NULL,
  508. (PBYTE)&ConfigFlags,
  509. sizeof(ConfigFlags),
  510. NULL))
  511. {
  512. ConfigFlags = 0;
  513. }
  514. ConfigFlags |= CONFIGFLAG_NEEDS_FORCED_CONFIG;
  515. SetupDiSetDeviceRegistryProperty(DeviceInfoSet,
  516. DeviceInfoData,
  517. SPDRP_CONFIGFLAGS,
  518. (PBYTE)&ConfigFlags,
  519. sizeof(ConfigFlags)
  520. );
  521. // See if this is a PnP device by trying to send it a PnP install message.
  522. // Call driver with DRV_PNPINSTALL
  523. DrvMsgResult = SendDriverMessage(hDriver,
  524. DRV_PNPINSTALL,
  525. (LONG_PTR)DeviceInfoSet,
  526. (LONG_PTR)DeviceInfoData);
  527. DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
  528. SetupDiGetDeviceInstallParams(DeviceInfoSet, DeviceInfoData, &DeviceInstallParams);
  529. // Look at result of DRV_PNPINSTALL
  530. switch (DrvMsgResult)
  531. {
  532. case DRVCNF_RESTART :
  533. // The installation was successful, but a reboot is required.
  534. // Ensure that the 'need reboot' flag in the device's installation parameters.
  535. DeviceInstallParams.Flags |= DI_NEEDREBOOT;
  536. // Let fall through to processing of successful installation.
  537. case DRVCNF_OK :
  538. // Remember that this is a PNPISA device driver
  539. RegSetValueEx(hkDrv,TEXT("DriverType"),0,REG_SZ,(LPBYTE)(TEXT("PNPISA")),14);
  540. break;
  541. default:
  542. // The driver did not want to install.
  543. // This may be because
  544. // 1) The user wanted to cancel
  545. // 2) Installation failed for some other reason
  546. // 3) This is not an ISAPNP driver (it's either a legacy driver or a WDM driver)
  547. // and it doesn't support the DRV_PNPINSTALLis messsage.
  548. // Unfortunately, we don't have fine enough granularity in the return codes to
  549. // distinguish between these cases.
  550. // Assume it's a legacy or WDM driver that doesn't support DRV_PNPINSTALL.
  551. // Try calling DRV_INSTALL instead.
  552. // Remember to clear CONFIGFLAG_NEEDS_FORCED_CONFIG flag, which shouldn't be set
  553. // for legacy or WDM drivers.
  554. ConfigFlags &= ~CONFIGFLAG_NEEDS_FORCED_CONFIG;
  555. SetupDiSetDeviceRegistryProperty(DeviceInfoSet,
  556. DeviceInfoData,
  557. SPDRP_CONFIGFLAGS,
  558. (PBYTE)&ConfigFlags,
  559. sizeof(ConfigFlags)
  560. );
  561. // Call driver with DRV_INSTALL
  562. DrvMsgResult = SendDriverMessage(hDriver,
  563. DRV_INSTALL,
  564. 0L,
  565. (LONG_PTR)(LPDRVCONFIGINFO)&DrvConfigInfo);
  566. // Look at result of DRV_INSTALL
  567. switch (DrvMsgResult)
  568. {
  569. case DRVCNF_RESTART:
  570. // Remember to restart, then fall through to OK case
  571. DeviceInstallParams.Flags |= DI_NEEDREBOOT;
  572. bRestart = TRUE;
  573. case DRVCNF_OK:
  574. // Remember whether the driver is configurable
  575. // If it's a WDM driver, it will return FALSE.
  576. pIDriver->fQueryable =
  577. (int)SendDriverMessage(hDriver,
  578. DRV_QUERYCONFIGURE,
  579. 0L,
  580. 0L);
  581. // If the driver is configurable then configure it.
  582. // Configuring the driver may result in a need to restart
  583. // the system. The user may also cancel install.
  584. if (pIDriver->fQueryable)
  585. {
  586. RegSetValueEx(hkDrv,TEXT("DriverType"),0,REG_SZ,(LPBYTE)(TEXT("Legacy")),14);
  587. switch (SendDriverMessage(hDriver,
  588. DRV_CONFIGURE,
  589. (LONG_PTR)hwnd,
  590. (LONG_PTR)(LPDRVCONFIGINFO)&DrvConfigInfo))
  591. {
  592. case DRVCNF_RESTART:
  593. DeviceInstallParams.Flags |= DI_NEEDREBOOT;
  594. bRestart = TRUE;
  595. case DRVCNF_OK:
  596. break;
  597. case DRVCNF_CANCEL:
  598. // Don't put up the error box if the user cancelled
  599. bSuccess = FALSE;
  600. break;
  601. }
  602. }
  603. break;
  604. case DRVCNF_CANCEL:
  605. // The driver did not want to install
  606. SetLastError(ERROR_CANCELLED);
  607. bPutUpMessage = TRUE;
  608. bSuccess = FALSE;
  609. break;
  610. }
  611. }
  612. SetupDiSetDeviceInstallParams(DeviceInfoSet, DeviceInfoData, &DeviceInstallParams);
  613. SelectInstalled_exit:
  614. if (hkDrv)
  615. {
  616. RegCloseKey(hkDrv);
  617. }
  618. if (hDriver)
  619. {
  620. CloseDriver(hDriver, 0L, 0L);
  621. }
  622. // If dealing with the driver resulted in error then put up a message
  623. if (bPutUpMessage)
  624. {
  625. OpenDriverError(hwnd, pIDriver->szDesc, pIDriver->szFile);
  626. }
  627. wsEndWait();
  628. return bSuccess;
  629. }
  630. /***********************************************************************
  631. *
  632. * InitDrvConfigInfo()
  633. *
  634. * Initialize Driver Configuration Information.
  635. *
  636. ***********************************************************************/
  637. void InitDrvConfigInfo( LPDRVCONFIGINFO lpDrvConfigInfo, PIDRIVER pIDriver )
  638. {
  639. lpDrvConfigInfo->dwDCISize = sizeof(DRVCONFIGINFO);
  640. lpDrvConfigInfo->lpszDCISectionName = pIDriver->wszSection;
  641. lpDrvConfigInfo->lpszDCIAliasName = pIDriver->wszAlias;
  642. }
  643. /***********************************************************************
  644. *
  645. * GetValidAlias()
  646. *
  647. * pstrType - Input - the type
  648. * Output - New alias for that type
  649. *
  650. * pstrSection - The system.ini section we're dealing with
  651. *
  652. * Create a valid alias name for a type. Searches the system.ini file
  653. * in the drivers section for aliases of the type already defined and
  654. * returns a new alias (eg WAVE1).
  655. *
  656. ***********************************************************************/
  657. BOOL GetValidAlias(LPTSTR pstrType, LPTSTR pstrSection)
  658. {
  659. TCHAR keystr[32];
  660. TCHAR *pstrTypeEnd;
  661. int AppendVal;
  662. DWORD CharsFound;
  663. pstrTypeEnd = pstrType + wcslen(pstrType);
  664. for (AppendVal=0; AppendVal<=9; AppendVal++)
  665. {
  666. if (AppendVal!=0)
  667. {
  668. _itow(AppendVal,pstrTypeEnd,10);
  669. }
  670. CharsFound = GetPrivateProfileString( pstrSection,
  671. pstrType,
  672. TEXT(""),
  673. keystr,
  674. sizeof(keystr) / sizeof(TCHAR),
  675. szSysIni);
  676. if (!CharsFound)
  677. {
  678. return TRUE;
  679. }
  680. }
  681. return FALSE;
  682. }
  683. /*******************************************************************
  684. *
  685. * IsConfigurable
  686. *
  687. * Find if a driver supports configuration
  688. *
  689. *******************************************************************/
  690. BOOL IsConfigurable(PIDRIVER pIDriver, HWND hwnd)
  691. {
  692. HANDLE hDriver;
  693. wsStartWait();
  694. /*
  695. * have we ever checked if this driver is queryable?
  696. */
  697. if ( pIDriver->fQueryable == -1 )
  698. {
  699. /*
  700. * Check it's not a kernel driver
  701. */
  702. if (pIDriver->KernelDriver)
  703. {
  704. pIDriver->fQueryable = 0;
  705. }
  706. else
  707. {
  708. /*
  709. * Open the driver and ask it if it is configurable
  710. */
  711. hDriver = OpenDriver(pIDriver->wszAlias, pIDriver->wszSection, 0L);
  712. if (hDriver)
  713. {
  714. pIDriver->fQueryable =
  715. (int)SendDriverMessage(hDriver,
  716. DRV_QUERYCONFIGURE,
  717. 0L,
  718. 0L);
  719. CloseDriver(hDriver, 0L, 0L);
  720. }
  721. else
  722. {
  723. pIDriver->fQueryable = 0;
  724. OpenDriverError(hwnd, pIDriver->szDesc, pIDriver->szFile);
  725. wsEndWait();
  726. return(FALSE);
  727. }
  728. }
  729. }
  730. wsEndWait();
  731. return((BOOL)pIDriver->fQueryable);
  732. }
  733. /******************************************************************
  734. *
  735. * Find any driver with the same name currently installed and
  736. * remove it
  737. *
  738. * szFile - File name of driver
  739. * szSection - system.ini section ([MCI] or [drivers]).
  740. *
  741. ******************************************************************/
  742. void RemoveAlreadyInstalled(LPTSTR szFile, LPTSTR szSection)
  743. {
  744. PIDRIVER pIDriver;
  745. pIDriver = FindIDriverByName (szFile);
  746. if (pIDriver != NULL)
  747. {
  748. PostRemove(pIDriver, FALSE);
  749. return;
  750. }
  751. CheckIniDrivers(szFile, szSection);
  752. }
  753. /******************************************************************
  754. *
  755. * Remove system.ini file entries for our driver
  756. *
  757. * szFile - driver file name
  758. * szSection - [drivers] or [MCI]
  759. *
  760. ******************************************************************/
  761. void CheckIniDrivers(LPTSTR szFile, LPTSTR szSection)
  762. {
  763. TCHAR allkeystr[MAXSTR * 2];
  764. TCHAR szRemovefile[20];
  765. TCHAR *keystr;
  766. GetPrivateProfileString(szSection,
  767. NULL,
  768. NULL,
  769. allkeystr,
  770. sizeof(allkeystr) / sizeof(TCHAR),
  771. szSysIni);
  772. keystr = allkeystr;
  773. while (wcslen(keystr) > 0)
  774. {
  775. GetPrivateProfileString(szSection,
  776. keystr,
  777. NULL,
  778. szRemovefile,
  779. sizeof(szRemovefile) / sizeof(TCHAR),
  780. szSysIni);
  781. if (!FileNameCmp(szFile, szRemovefile))
  782. RemoveDriverEntry(keystr, szFile, szSection, FALSE);
  783. keystr = &keystr[wcslen(keystr) + 1];
  784. }
  785. }
  786. /******************************************************************
  787. *
  788. * RemoveDriverParams
  789. *
  790. * Remove anything after the next token
  791. *
  792. ******************************************************************/
  793. void RemoveDriverParams(LPTSTR szFile, LPTSTR Params)
  794. {
  795. for (;*szFile == TEXT(' '); szFile++);
  796. for (;*szFile != TEXT(' ') && *szFile != TEXT('\0'); szFile++);
  797. if (*szFile == TEXT(' '))
  798. {
  799. *szFile = TEXT('\0');
  800. for (;*++szFile == TEXT(' '););
  801. wcscpy(Params, szFile);
  802. }
  803. else
  804. {
  805. *Params = TEXT('\0');
  806. }
  807. }
  808. DWORD
  809. InstallDriversForPnPDevice(
  810. IN HWND hWnd,
  811. IN HDEVINFO DeviceInfoSet,
  812. IN PSP_DEVINFO_DATA DeviceInfoData
  813. )
  814. /*++
  815. Routine Description:
  816. This routine traverses the "Drivers" tree under the specified device's software
  817. key, adding each multimedia type entry present to the Drivers32 key of the registry.
  818. The driver is then invoked to perform any configuration necessary for that type.
  819. Arguments:
  820. hWnd - Supplies the handle of the window to be used as the parent for any UI.
  821. DeviceInfoSet - Supplies a handle to the device information set containing the
  822. multimedia device being installed.
  823. DeviceInfoData - Supplies the address of the SP_DEVINFO_DATA structure representing
  824. the multimedia device being installed.
  825. Return Value:
  826. If successful, the return value is NO_ERROR, otherwise it is a Win32 error code.
  827. --*/
  828. {
  829. HKEY hKey, hDriversKey, hTypeInstanceKey;
  830. TCHAR szTypes[MAXSTR];
  831. TCHAR szType[MAXSTR];
  832. DWORD Err;
  833. DWORD RegDataType, cbRegDataSize, RegKeyIndex;
  834. int i;
  835. PIDRIVER pIDriver, pPrevIDriver;
  836. PIDRIVER IDriverList = NULL, IDriverListToCleanUp = NULL;
  837. TCHAR CharBuffer[MAX_PATH + sizeof(TCHAR)];
  838. LPCTSTR CurrentFilename;
  839. BOOL bNoMoreAliases = FALSE;
  840. LPCTSTR szAliasStringToUse; // Pointer to the Alias value name to use
  841. BOOL bIsWOW64Process = FALSE; // TRUE if we're running under WOW64
  842. //
  843. // If we're running in WOW64, we need to use a different Alias string so that
  844. // we don't overwrite the 64-bit alias string
  845. //
  846. if( IsWow64Process(GetCurrentProcess(), &bIsWOW64Process)
  847. && bIsWOW64Process )
  848. {
  849. szAliasStringToUse = gszAliasWOW64Value;
  850. }
  851. else
  852. {
  853. szAliasStringToUse = gszAliasValue;
  854. }
  855. if ((hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
  856. DeviceInfoData,
  857. DICS_FLAG_GLOBAL,
  858. 0,
  859. DIREG_DRV,
  860. KEY_ALL_ACCESS)) == INVALID_HANDLE_VALUE)
  861. {
  862. return GetLastError();
  863. }
  864. //
  865. // What we're really interested in is the "Drivers" subkey.
  866. //
  867. Err = (DWORD)RegOpenKeyEx(hKey, gszDriversSubkeyName, 0, KEY_ALL_ACCESS, &hDriversKey);
  868. RegCloseKey(hKey); // don't need this key anymore.
  869. if (Err != ERROR_SUCCESS)
  870. {
  871. //
  872. // If the key is not present, then there is no work to do.
  873. //
  874. return NO_ERROR;
  875. }
  876. //
  877. // Retrieve the "SubClasses" value from this key. This contains a comma-delimited
  878. // list of all multimedia type entries associated with this device.
  879. //
  880. cbRegDataSize = sizeof(szTypes);
  881. if ((Err = RegQueryValueEx(hDriversKey,
  882. gszSubClassesValue,
  883. NULL,
  884. &RegDataType,
  885. (PBYTE)szTypes,
  886. &cbRegDataSize)) != ERROR_SUCCESS)
  887. {
  888. goto clean0;
  889. }
  890. if ((RegDataType != REG_SZ) || !cbRegDataSize)
  891. {
  892. Err = ERROR_INVALID_DATA;
  893. goto clean0;
  894. }
  895. //
  896. // OK, we have the list of types, now process each one.
  897. //
  898. for (i = 1; ((Err == NO_ERROR) && infParseField(szTypes, i, szType)); i++)
  899. {
  900. #ifdef _WIN64
  901. //
  902. // Check for magic WaveWOW64 value
  903. if( 0 == _wcsnicmp( szType, gszWaveWOW64Value, wcslen(gszWaveWOW64Value) ) )
  904. {
  905. // Thunk the installation to the 32-bit mmsys.cpl installer
  906. mmWOW64ThunkMediaClassInstaller(DIF_INSTALLDEVICE, DeviceInfoSet, DeviceInfoData);
  907. continue;
  908. }
  909. #endif //_WIN64
  910. if (RegOpenKeyEx(hDriversKey, szType, 0, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS)
  911. {
  912. //
  913. // Couldn't find a subkey for this entry--move on to the next one.
  914. //
  915. continue;
  916. }
  917. for (RegKeyIndex = 0;
  918. ((Err == NO_ERROR) &&
  919. (RegEnumKey(hKey, RegKeyIndex, CharBuffer, sizeof(CharBuffer)/sizeof(TCHAR)) == ERROR_SUCCESS));
  920. RegKeyIndex++)
  921. {
  922. if (RegOpenKeyEx(hKey, CharBuffer, 0, KEY_ALL_ACCESS, &hTypeInstanceKey) != ERROR_SUCCESS)
  923. {
  924. //
  925. // For some reason, we couldn't open the key we just enumerated. Oh well, move on
  926. // to the next one.
  927. //
  928. continue;
  929. }
  930. if (!(pIDriver = (PIDRIVER)LocalAlloc(LPTR, sizeof(IDRIVER))))
  931. {
  932. //
  933. // Not enough memory! Abort the whole thing.
  934. //
  935. Err = ERROR_NOT_ENOUGH_MEMORY;
  936. goto CloseInstanceAndContinue;
  937. }
  938. //
  939. // Retrieve the description and driver filename from this key.
  940. //
  941. cbRegDataSize = sizeof(pIDriver->szDesc);
  942. if ((RegQueryValueEx(hTypeInstanceKey,
  943. gszDescriptionValue,
  944. NULL,
  945. &RegDataType,
  946. (LPBYTE)pIDriver->szDesc,
  947. &cbRegDataSize) != ERROR_SUCCESS)
  948. || (RegDataType != REG_SZ) || !cbRegDataSize)
  949. {
  950. LocalFree((HANDLE)pIDriver);
  951. goto CloseInstanceAndContinue;
  952. }
  953. wcsncpy(pIDriver->szSection,
  954. wcsstr(pIDriver->szDesc, TEXT("MCI")) ? szMCI : szDrivers,
  955. sizeof(pIDriver->szSection) / sizeof(TCHAR)
  956. );
  957. cbRegDataSize = sizeof(pIDriver->szFile);
  958. if ((RegQueryValueEx(hTypeInstanceKey,
  959. gszDriverValue,
  960. NULL,
  961. &RegDataType,
  962. (LPBYTE)pIDriver->szFile,
  963. &cbRegDataSize) != ERROR_SUCCESS)
  964. || (RegDataType != REG_SZ) || !cbRegDataSize)
  965. {
  966. LocalFree((HANDLE)pIDriver);
  967. goto CloseInstanceAndContinue;
  968. }
  969. pIDriver->KernelDriver = IsFileKernelDriver(pIDriver->szFile);
  970. //
  971. // Find a valid alias for this device (eg Wave2). This is
  972. // used as the key in the [MCI] or [Drivers32] section.
  973. //
  974. wcsncpy(pIDriver->szAlias, szType, sizeof(pIDriver->szAlias) / sizeof(TCHAR));
  975. if (!GetValidAlias(pIDriver->szAlias, pIDriver->szSection))
  976. {
  977. //
  978. // Exceeded the maximum--but can't tell the user. We can't bring up a dialog
  979. // in the services.exe process
  980. //
  981. bNoMoreAliases = TRUE;
  982. LocalFree((HANDLE)pIDriver);
  983. goto CloseInstanceAndContinue;
  984. }
  985. //
  986. // Fill in the Unicode fields from the ANSI ones.
  987. //
  988. wcscpy(pIDriver->wszSection, pIDriver->szSection);
  989. wcscpy(pIDriver->wszAlias, pIDriver->szAlias);
  990. wcscpy(pIDriver->wszFile, pIDriver->szFile);
  991. //
  992. // We must write the alias out now, because we may need to generate
  993. // other aliases for this same type, and we can't generate a unique
  994. // alias unless all existing aliases are present in the relevant
  995. // registry key.
  996. //
  997. WritePrivateProfileString(pIDriver->szSection,
  998. pIDriver->szAlias,
  999. pIDriver->szFile,
  1000. szSysIni
  1001. );
  1002. //
  1003. // We also must write the alias out to the key we're currently in (under
  1004. // the device's software key), because during uninstall, we need to be
  1005. // able to figure out what devices get removed.
  1006. //
  1007. RegSetValueEx(hTypeInstanceKey,
  1008. szAliasStringToUse,
  1009. 0,
  1010. REG_SZ,
  1011. (PBYTE)(pIDriver->szAlias),
  1012. (wcslen(pIDriver->szAlias)*sizeof(TCHAR)) + sizeof(TCHAR)
  1013. );
  1014. //
  1015. // Add this new IDriver node to our linked list. The list is sorted by
  1016. // driver filename, and this node should be inserted at the end of the
  1017. // the group of nodes that have the same driver filename.
  1018. //
  1019. InsertNewIDriverNodeInList(&IDriverList, pIDriver);
  1020. CloseInstanceAndContinue:
  1021. RegCloseKey(hTypeInstanceKey);
  1022. }
  1023. RegCloseKey(hKey);
  1024. }
  1025. if ((Err == NO_ERROR) && !IDriverList)
  1026. {
  1027. // We actually don't want to present the ugly "Data is invalid" error if we ran out of aliases
  1028. if (bNoMoreAliases)
  1029. {
  1030. DestroyIDriverNodeList(IDriverList, TRUE, FALSE);
  1031. goto clean0;
  1032. }
  1033. else
  1034. {
  1035. //
  1036. // We didn't find anything to install!
  1037. //
  1038. Err = ERROR_INVALID_DATA;
  1039. }
  1040. }
  1041. if (Err != NO_ERROR)
  1042. {
  1043. //
  1044. // Clean up anything we put in the multimedia sections of the registry.
  1045. //
  1046. DestroyIDriverNodeList(IDriverList, TRUE, FALSE);
  1047. goto clean0;
  1048. }
  1049. //
  1050. // If we get to here, then we've successfully built up a list of all driver entries
  1051. // we need to install. Now, traverse the list, and install each one.
  1052. //
  1053. CurrentFilename = NULL;
  1054. *CharBuffer = TEXT('\0'); // use this character buffer to contain (empty) parameter string.
  1055. pIDriver = IDriverList;
  1056. pPrevIDriver = NULL;
  1057. while (pIDriver)
  1058. {
  1059. if (!CurrentFilename || _wcsicmp(CurrentFilename, pIDriver->szFile))
  1060. {
  1061. //
  1062. // This is the first entry we've encountered for this driver. We need
  1063. // to call the driver to see if it can be configured, and configure it
  1064. // if it can be.
  1065. //
  1066. if (SelectInstalled(hWnd, pIDriver, CharBuffer, DeviceInfoSet, DeviceInfoData))
  1067. {
  1068. //
  1069. // Move this IDriver node to our list of clean-up items. This is used in
  1070. // case we hit an error with some other driver, and we need to notify this
  1071. // driver that even though it was successful, someone else messed up and
  1072. // complete removal of the device must occur.
  1073. //
  1074. if (pPrevIDriver)
  1075. {
  1076. pPrevIDriver->related = pIDriver->related;
  1077. }
  1078. else
  1079. {
  1080. IDriverList = pIDriver->related;
  1081. }
  1082. pIDriver->related = IDriverListToCleanUp;
  1083. IDriverListToCleanUp = pIDriver;
  1084. }
  1085. else
  1086. {
  1087. //
  1088. // Error talking to driver
  1089. //
  1090. Err = GetLastError();
  1091. goto clean1;
  1092. }
  1093. #if 0 // We don't need this piece of code in the Plug&Play install case.
  1094. /*
  1095. * for displaying the driver desc. in the restart mesg
  1096. */
  1097. if (!bRelated || pIDriver->bRelated)
  1098. {
  1099. wcscpy(szRestartDrv, pIDriver->szDesc);
  1100. }
  1101. #endif
  1102. //
  1103. // We need to write out the driver description to the
  1104. // control.ini section [Userinstallable.drivers]
  1105. // so we can differentiate between user and system drivers
  1106. //
  1107. // This is tested by the function UserInstalled when
  1108. // the user tries to remove a driver and merely
  1109. // affects which message the user gets when being
  1110. // asked to confirm removal (non user-installed drivers
  1111. // are described as being necessary to the system).
  1112. //
  1113. WritePrivateProfileString(szUserDrivers,
  1114. pIDriver->szAlias,
  1115. pIDriver->szFile,
  1116. szControlIni
  1117. );
  1118. //
  1119. // Update [related.desc] section of control.ini :
  1120. //
  1121. // ALIAS=driver name list
  1122. //
  1123. // When the driver whose alias is ALIAS is removed
  1124. // the drivers in the name list will also be removed.
  1125. // These were the drivers in the related drivers list
  1126. // when the driver is installed.
  1127. //
  1128. WritePrivateProfileString(szRelatedDesc,
  1129. pIDriver->szAlias,
  1130. pIDriver->szRemove,
  1131. szControlIni
  1132. );
  1133. //
  1134. // Cache the description string in control.ini in the
  1135. // drivers description section.
  1136. //
  1137. // The key is the driver file name + extension.
  1138. //
  1139. WritePrivateProfileString(szDriversDesc,
  1140. pIDriver->szFile,
  1141. pIDriver->szDesc,
  1142. szControlIni
  1143. );
  1144. #ifdef DOBOOT // We don't do the boot section on NT
  1145. if (bInstallBootLine)
  1146. {
  1147. szTemp[MAXSTR];
  1148. GetPrivateProfileString(szBoot,
  1149. szDrivers,
  1150. szTemp,
  1151. szTemp,
  1152. sizeof(szTemp) / sizeof(TCHAR),
  1153. szSysIni);
  1154. wcscat(szTemp, TEXT(" "));
  1155. wcscat(szTemp, pIDriver->szAlias);
  1156. WritePrivateProfileString(szBoot,
  1157. szDrivers,
  1158. szTemp,
  1159. szSysIni);
  1160. bInstallBootLine = FALSE;
  1161. }
  1162. #endif // DOBOOT
  1163. //
  1164. // Update our "CurrentFilename" pointer, so that we'll know when we
  1165. // move from one driver filename to another.
  1166. //
  1167. CurrentFilename = pIDriver->szFile;
  1168. //
  1169. // Move on to the next IDriver node IN THE ORIGINAL LIST. We can't simply
  1170. // move on the 'related' pointer in our node anymore, since we moved it
  1171. // into our clean-up list.
  1172. //
  1173. if (pPrevIDriver)
  1174. {
  1175. pIDriver = pPrevIDriver->related;
  1176. }
  1177. else
  1178. {
  1179. pIDriver = IDriverList;
  1180. }
  1181. }
  1182. else
  1183. {
  1184. //
  1185. // We've already configured this driver. Leave it in its original list,
  1186. // and move on to the next node.
  1187. //
  1188. pPrevIDriver = pIDriver;
  1189. pIDriver = pIDriver->related;
  1190. }
  1191. }
  1192. clean1:
  1193. DestroyIDriverNodeList(IDriverListToCleanUp, (Err != NO_ERROR), TRUE);
  1194. DestroyIDriverNodeList(IDriverList, (Err != NO_ERROR), FALSE);
  1195. clean0:
  1196. RegCloseKey(hDriversKey);
  1197. return Err;
  1198. }
  1199. void
  1200. InsertNewIDriverNodeInList(
  1201. IN OUT PIDRIVER *IDriverList,
  1202. IN PIDRIVER NewIDriverNode
  1203. )
  1204. /*++
  1205. Routine Description:
  1206. This routine inserts a new IDriver node into the specified linked list of IDriver
  1207. nodes. The list is sorted by driver filename, and this node will be placed after
  1208. any existing nodes having this same driver filename.
  1209. Arguments:
  1210. IDriverList - Supplies the address of the variable that points to the head of the
  1211. linked list. If the new node is inserted at the head of the list, this variable
  1212. will be updated upon return to reflect the new head of the list.
  1213. NewIDriverNode - Supplies the address of the new driver node to be inserted into the
  1214. list.
  1215. Return Value:
  1216. None.
  1217. --*/
  1218. {
  1219. PIDRIVER CurNode, PrevNode;
  1220. for (CurNode = *IDriverList, PrevNode = NULL;
  1221. CurNode;
  1222. PrevNode = CurNode, CurNode = CurNode->related)
  1223. {
  1224. if (_wcsicmp(CurNode->szFile, NewIDriverNode->szFile) > 0)
  1225. {
  1226. break;
  1227. }
  1228. }
  1229. //
  1230. // Insert the new IDriver node in front of the current one.
  1231. //
  1232. NewIDriverNode->related = CurNode;
  1233. if (PrevNode)
  1234. {
  1235. PrevNode->related = NewIDriverNode;
  1236. }
  1237. else
  1238. {
  1239. *IDriverList = NewIDriverNode;
  1240. }
  1241. }
  1242. void
  1243. DestroyIDriverNodeList(
  1244. IN PIDRIVER IDriverList,
  1245. IN BOOL CleanRegistryValues,
  1246. IN BOOL NotifyDriverOfCleanUp
  1247. )
  1248. /*++
  1249. Routine Description:
  1250. This routine frees all memory associated with the nodes in the specified IDriver
  1251. linked list. It also optionally cleans up any modifications that were previously
  1252. made as a result of an attempted install.
  1253. Arguments:
  1254. IDriverList - Points to the head of the linked list of IDriver nodes.
  1255. CleanRegistryValues - If TRUE, then the multimedia registry values previously
  1256. created (e.g., Drivers32 aliases) will be deleted.
  1257. NotifyDriverOfCleanUp - If TRUE, then the driver will be notified of its removal.
  1258. This only applies to non-kernel (i.e., installable) drivers, and this flag is
  1259. ignored if CleanRegistryValues is FALSE.
  1260. Return Value:
  1261. None.
  1262. --*/
  1263. {
  1264. PIDRIVER NextNode;
  1265. HANDLE hDriver;
  1266. while (IDriverList)
  1267. {
  1268. NextNode = IDriverList->related;
  1269. if (CleanRegistryValues)
  1270. {
  1271. if (NotifyDriverOfCleanUp && !IDriverList->KernelDriver)
  1272. {
  1273. if (hDriver = OpenDriver(IDriverList->wszAlias, IDriverList->wszSection, 0L))
  1274. {
  1275. SendDriverMessage(hDriver, DRV_REMOVE, 0L, 0L);
  1276. CloseDriver(hDriver, 0L, 0L);
  1277. }
  1278. }
  1279. WritePrivateProfileString(IDriverList->szSection,
  1280. IDriverList->szAlias,
  1281. NULL,
  1282. szSysIni
  1283. );
  1284. WriteProfileString(IDriverList->szFile, IDriverList->szAlias, NULL);
  1285. }
  1286. LocalFree((HANDLE)IDriverList);
  1287. IDriverList = NextNode;
  1288. }
  1289. }
  1290. BOOL DriverNodeSupportsNt(IN HDEVINFO DeviceInfoSet,
  1291. IN PSP_DEVINFO_DATA DeviceInfoData,
  1292. IN PSP_DRVINFO_DATA DriverInfoData
  1293. )
  1294. /*++
  1295. Routine Description:
  1296. This routine determines whether the driver node specified is capable of
  1297. installing on Windows NT (as opposed to being a Win95-only driver node).
  1298. This determination is made based upon whether or not there is a corresponding
  1299. service install section for this device install section.
  1300. Return Value:
  1301. If the driver node supports Windows NT, the return value is TRUE, otherwise
  1302. it is FALSE.
  1303. --*/
  1304. {
  1305. SP_DRVINFO_DETAIL_DATA DriverInfoDetailData;
  1306. HINF hInf;
  1307. DWORD Err;
  1308. TCHAR ActualSectionName[255];
  1309. DWORD ActualSectionNameLen;
  1310. LONG LineCount;
  1311. CONST TCHAR szServiceInstallSuffix[] = TEXT(".") INFSTR_SUBKEY_SERVICES;
  1312. // Get name and section to install from
  1313. DriverInfoDetailData.cbSize = sizeof(DriverInfoDetailData);
  1314. if (!SetupDiGetDriverInfoDetail(DeviceInfoSet,
  1315. DeviceInfoData,
  1316. DriverInfoData,
  1317. &DriverInfoDetailData,
  1318. sizeof(DriverInfoDetailData),
  1319. NULL) &&
  1320. ((Err = GetLastError()) != ERROR_INSUFFICIENT_BUFFER))
  1321. {
  1322. return FALSE;
  1323. }
  1324. //
  1325. // Open the associated INF file.
  1326. //
  1327. if ((hInf = SetupOpenInfFile(DriverInfoDetailData.InfFileName, NULL, INF_STYLE_WIN4, NULL)) == INVALID_HANDLE_VALUE)
  1328. {
  1329. return FALSE;
  1330. }
  1331. //
  1332. // Retrieve the actual name of the install section to be used for this
  1333. // driver node.
  1334. //
  1335. SetupDiGetActualSectionToInstall(hInf,
  1336. DriverInfoDetailData.SectionName,
  1337. ActualSectionName,
  1338. sizeof(ActualSectionName) / sizeof(TCHAR),
  1339. &ActualSectionNameLen,
  1340. NULL
  1341. );
  1342. //
  1343. // Generate the service install section name, and see if it exists.
  1344. //
  1345. CopyMemory(&(ActualSectionName[ActualSectionNameLen - 1]),
  1346. szServiceInstallSuffix,
  1347. sizeof(szServiceInstallSuffix)
  1348. );
  1349. LineCount = SetupGetLineCount(hInf, ActualSectionName);
  1350. SetupCloseInfFile(hInf);
  1351. return (LineCount != -1);
  1352. }
  1353. // Go through the list of drivers and try to keep from installing or displaying any non-NT drivers
  1354. // Warning: If you call this function with DeviceInfoData NULL, it will have to enumerate and open
  1355. // every media inf there is, which may take awhile.
  1356. BOOL FilterOutNonNTInfs(IN HDEVINFO DeviceInfoSet,
  1357. IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
  1358. DWORD DriverType
  1359. )
  1360. {
  1361. DWORD MemberIndex;
  1362. SP_DRVINFO_DATA DriverInfoData;
  1363. SP_DRVINFO_DETAIL_DATA DriverInfoDetailData;
  1364. SP_DRVINSTALL_PARAMS DriverInstallParams;
  1365. MemberIndex = 0;
  1366. DriverInfoData.cbSize = sizeof(DriverInfoData);
  1367. while (SetupDiEnumDriverInfo(DeviceInfoSet,DeviceInfoData,DriverType,MemberIndex,&DriverInfoData))
  1368. {
  1369. if (!DriverNodeSupportsNt(DeviceInfoSet, DeviceInfoData, &DriverInfoData))
  1370. {
  1371. // If driver doesn't support NT, try to exclude from list & max out rank
  1372. DriverInstallParams.cbSize=sizeof(DriverInstallParams);
  1373. if (SetupDiGetDriverInstallParams(DeviceInfoSet, DeviceInfoData, &DriverInfoData, &DriverInstallParams))
  1374. {
  1375. DriverInstallParams.Flags |= DNF_EXCLUDEFROMLIST | DNF_BAD_DRIVER;
  1376. DriverInstallParams.Rank = 10000;
  1377. SetupDiSetDriverInstallParams(DeviceInfoSet, DeviceInfoData, &DriverInfoData, &DriverInstallParams);
  1378. }
  1379. }
  1380. MemberIndex++;
  1381. }
  1382. return TRUE;
  1383. }
  1384. DWORD Media_SelectBestCompatDrv(IN HDEVINFO DeviceInfoSet,
  1385. IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
  1386. )
  1387. {
  1388. DWORD DriverType = (DeviceInfoData ? SPDIT_COMPATDRIVER : SPDIT_CLASSDRIVER);
  1389. FilterOutNonNTInfs(DeviceInfoSet, DeviceInfoData, DriverType);
  1390. return ERROR_DI_DO_DEFAULT;
  1391. }
  1392. DWORD Media_AllowInstall(IN HDEVINFO DeviceInfoSet,
  1393. IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
  1394. )
  1395. {
  1396. DWORD Err;
  1397. SP_DRVINFO_DATA DriverInfoData;
  1398. // Verify that the driver node selected for this device supports NT.
  1399. // It will probably be a pretty common scenario for users to try to
  1400. // give us their Win95 INFs.
  1401. DriverInfoData.cbSize = sizeof(DriverInfoData);
  1402. if (!SetupDiGetSelectedDriver(DeviceInfoSet, DeviceInfoData, &DriverInfoData))
  1403. {
  1404. // NULL driver?
  1405. return ERROR_DI_DO_DEFAULT;
  1406. }
  1407. if (!DriverNodeSupportsNt(DeviceInfoSet,
  1408. DeviceInfoData,
  1409. &DriverInfoData))
  1410. {
  1411. dlog("Media_AllowInstall: Not an NT driver");
  1412. return ERROR_DI_DONT_INSTALL;
  1413. }
  1414. return ERROR_DI_DO_DEFAULT;
  1415. }
  1416. DWORD Media_InstallDevice(IN HDEVINFO DeviceInfoSet,
  1417. IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
  1418. )
  1419. {
  1420. DWORD Err, ConfigFlags;
  1421. SP_DRVINFO_DATA DriverInfoData;
  1422. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  1423. HWND hWnd;
  1424. SC_HANDLE schScm;
  1425. //
  1426. // if we are in setup then let's ensure the
  1427. // SetupPreferredAudioDevicesCount value is in the driver registry for
  1428. // devices that already have MME drivers installed. This is so audiosrv's
  1429. // MigrateAutoSetupPreferredAudio logic does not interpret this as a new
  1430. // device installation.
  1431. //
  1432. DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
  1433. if (SetupDiGetDeviceInstallParams(DeviceInfoSet, DeviceInfoData, &DeviceInstallParams))
  1434. {
  1435. if (DI_FLAGSEX_IN_SYSTEM_SETUP & DeviceInstallParams.FlagsEx)
  1436. {
  1437. HKEY hkDriver;
  1438. hkDriver = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_SET_VALUE);
  1439. if (INVALID_HANDLE_VALUE != hkDriver)
  1440. {
  1441. HKEY hkMmeDrivers;
  1442. LONG l;
  1443. l = RegOpenKeyEx(hkDriver, TEXT("Drivers"), 0, KEY_QUERY_VALUE, &hkMmeDrivers);
  1444. if (ERROR_FILE_NOT_FOUND != l)
  1445. {
  1446. l = RegQueryValueEx(hkDriver, TEXT("SetupPreferredAudioDevicesCount"), NULL, NULL, NULL, NULL);
  1447. if (ERROR_FILE_NOT_FOUND == l)
  1448. {
  1449. DWORD dw = 0;
  1450. RegSetValueEx(hkDriver, TEXT("SetupPreferredAudioDevicesCount"), 0, REG_DWORD, (PBYTE)&dw, sizeof(dw));
  1451. }
  1452. RegCloseKey(hkMmeDrivers);
  1453. }
  1454. RegCloseKey(hkDriver);
  1455. }
  1456. }
  1457. }
  1458. // First remove any driver that was already installed
  1459. Media_RemoveDevice(DeviceInfoSet,DeviceInfoData);
  1460. DriverInfoData.cbSize = sizeof(DriverInfoData);
  1461. if (!SetupDiGetSelectedDriver(DeviceInfoSet, DeviceInfoData, &DriverInfoData))
  1462. {
  1463. //
  1464. // The NULL driver is to be installed for this device. We don't need to
  1465. // do anything special in that case.
  1466. //
  1467. dlog("Media_InstallDevice: Null driver");
  1468. return ERROR_DI_DO_DEFAULT;
  1469. }
  1470. dlog("Media_InstallDevice: Calling SetupDiInstallDevice");
  1471. if (!SetupDiInstallDevice(DeviceInfoSet, DeviceInfoData))
  1472. {
  1473. Err = GetLastError();
  1474. dlog("Media_InstallDevice: SetupDiInstallDevice failed");
  1475. //
  1476. // In certain circumstances, we have INFs that control some of the functions on the
  1477. // card, but not all (e.g., our sndblst driver controls wave, midi, aux, mixer but
  1478. // not the fancy 3D stuff). In order to give the user a descriptive name that lets
  1479. // them know what we're trying to install, the INF contains driver nodes for devices
  1480. // it can't support. If this is the case, then SetupDiInstallDevice will fail with
  1481. // ERROR_NO_ASSOCIATED_SERVICE. If this happens, we want to clear the
  1482. // CONFIGFLAG_REINSTALL that got set, so we don't keep hounding the user about this.
  1483. // While we're at it, we go ahead and store the driver node's device description as
  1484. // the device instance's description, so that we know what the device instances are
  1485. // later on (for diagnostic purposes, mainly).
  1486. //
  1487. if (Err == ERROR_NO_ASSOCIATED_SERVICE)
  1488. {
  1489. // Clear reinstall flag
  1490. if (SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
  1491. DeviceInfoData,
  1492. SPDRP_CONFIGFLAGS,
  1493. NULL,
  1494. (PBYTE)&ConfigFlags,
  1495. sizeof(ConfigFlags),
  1496. NULL))
  1497. {
  1498. ConfigFlags &= ~CONFIGFLAG_REINSTALL;
  1499. SetupDiSetDeviceRegistryProperty(DeviceInfoSet,
  1500. DeviceInfoData,
  1501. SPDRP_CONFIGFLAGS,
  1502. (PBYTE)&ConfigFlags,
  1503. sizeof(ConfigFlags)
  1504. );
  1505. }
  1506. // Save description of device
  1507. SetupDiSetDeviceRegistryProperty(DeviceInfoSet,
  1508. DeviceInfoData,
  1509. SPDRP_DEVICEDESC,
  1510. (PBYTE)DriverInfoData.Description,
  1511. (lstrlen(DriverInfoData.Description) + 1) * sizeof(TCHAR)
  1512. );
  1513. }
  1514. goto Media_InstallDevice_exit;
  1515. }
  1516. //
  1517. // Get the device install parameters, so we'll know what parent window to use for any
  1518. // UI that occurs during configuration of this device.
  1519. //
  1520. DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
  1521. if (SetupDiGetDeviceInstallParams(DeviceInfoSet, DeviceInfoData, &DeviceInstallParams))
  1522. {
  1523. hWnd = DeviceInstallParams.hwndParent;
  1524. }
  1525. else
  1526. {
  1527. hWnd = NULL;
  1528. }
  1529. //
  1530. // The INF will have created a "Drivers" subkey under the device's software key.
  1531. // This tree, in turn, contains subtrees for each type of driver (aux, midi, etc.)
  1532. // applicable for this device. We must now traverse this tree, and create entries
  1533. // in Drivers32 for each function alias.
  1534. //
  1535. dlog("Media_InstallDevice: Calling InstallDriversForPnPDevice");
  1536. if ((Err = InstallDriversForPnPDevice(hWnd, DeviceInfoSet, DeviceInfoData)) != NO_ERROR)
  1537. {
  1538. //
  1539. // The device is in an unknown state. Disable it by setting the
  1540. // CONFIGFLAG_DISABLED config flag, and mark it as needing a reinstall.
  1541. //
  1542. if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
  1543. DeviceInfoData,
  1544. SPDRP_CONFIGFLAGS,
  1545. NULL,
  1546. (PBYTE)&ConfigFlags,
  1547. sizeof(ConfigFlags),
  1548. NULL))
  1549. {
  1550. ConfigFlags = 0;
  1551. }
  1552. ConfigFlags |= (CONFIGFLAG_DISABLED | CONFIGFLAG_REINSTALL);
  1553. SetupDiSetDeviceRegistryProperty(DeviceInfoSet,
  1554. DeviceInfoData,
  1555. SPDRP_CONFIGFLAGS,
  1556. (PBYTE)&ConfigFlags,
  1557. sizeof(ConfigFlags)
  1558. );
  1559. //
  1560. // Delete the Driver= entry from the Dev Reg Key and delete the
  1561. // DrvRegKey.
  1562. //
  1563. SetupDiDeleteDevRegKey(DeviceInfoSet,
  1564. DeviceInfoData,
  1565. DICS_FLAG_GLOBAL | DICS_FLAG_CONFIGGENERAL,
  1566. 0,
  1567. DIREG_DRV
  1568. );
  1569. SetupDiSetDeviceRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_DRIVER, NULL, 0);
  1570. //
  1571. // Also, delete the service property, so we'll know this device instance needs to be
  1572. // cleaned up if we later reboot and don't find the device.
  1573. //
  1574. SetupDiSetDeviceRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_SERVICE, NULL, 0);
  1575. goto Media_InstallDevice_exit;
  1576. }
  1577. //
  1578. // Attempt to start the AudioSrv Win32 service
  1579. //
  1580. schScm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  1581. if (schScm) {
  1582. SC_HANDLE schAudioSrv;
  1583. schAudioSrv = OpenService(schScm, TEXT("AudioSrv"), SERVICE_QUERY_STATUS | SERVICE_START);
  1584. if (schAudioSrv) {
  1585. SERVICE_STATUS AudioSrvStatus;
  1586. if (QueryServiceStatus(schAudioSrv, &AudioSrvStatus)) {
  1587. if (SERVICE_STOPPED == AudioSrvStatus.dwCurrentState) {
  1588. if (!StartService(schAudioSrv, 0, NULL)) {
  1589. dlog("Media_InstallDevice: StartService on AudioSrv failed");
  1590. }
  1591. }
  1592. } else {
  1593. dlog("Media_InstallDevice: QueryServiceStatus on AudioSrv failed");
  1594. }
  1595. CloseServiceHandle(schAudioSrv);
  1596. } else {
  1597. dlog("Media_InstallDevice: OpenService on AudioSrv failed");
  1598. }
  1599. CloseServiceHandle(schScm);
  1600. } else {
  1601. dlog("Media_InstallDevice: OpenSCManager failed");
  1602. }
  1603. Err = NO_ERROR;
  1604. Media_InstallDevice_exit:
  1605. dlog("Media_InstallDevice: Returning");
  1606. return Err;
  1607. }