Leaked source code of windows server 2003
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.

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