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.

1438 lines
46 KiB

  1. /* REMOVE.C
  2. **
  3. ** Copyright (C) Microsoft, 1990, All Rights Reserved.
  4. **
  5. ** Multimedia Control Panel Applet for removing
  6. ** device drivers. See the ispec doc DRIVERS.DOC for more information.
  7. **
  8. ** History:
  9. **
  10. ** Thu Oct 17 1991 -by- Sanjaya
  11. ** Created. Originally part of drivers.c
  12. */
  13. #include <windows.h>
  14. #include <mmsystem.h>
  15. #include <winsvc.h>
  16. #include <memory.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <cpl.h>
  20. #include <cphelp.h>
  21. #include <regstr.h>
  22. #include "drivers.h"
  23. #include "sulib.h"
  24. BOOL SetValidAlias (LPTSTR, LPTSTR);
  25. static CONST TCHAR gszRunDLL32Path[] = TEXT("\"%s\\RUNDLL32.EXE\" \"%s\\MMSYS.CPL\",mmWOW64MediaClassInstallerA \"%s\"%d");
  26. static CONST TCHAR gszAliasValue[] = TEXT("Alias");
  27. static CONST TCHAR gszAliasWOW64Value[] = TEXT("AliasWOW64");
  28. static CONST TCHAR gszWaveWOW64Value[] = TEXT("WOW64");
  29. #ifdef DOBOOT
  30. BOOL FindBootDriver (TCHAR *);
  31. PSTR strstri (LPTSTR, LPTSTR);
  32. #endif // DOBOOT
  33. /*
  34. * RemoveService(szFile)
  35. *
  36. * Remove the service corresponding to the file szFile
  37. *
  38. * returns TRUE if successful, FALSE otherwise
  39. */
  40. BOOL RemoveService(LPTSTR szFile)
  41. {
  42. SC_HANDLE SCManagerHandle;
  43. SC_HANDLE ServiceHandle;
  44. TCHAR ServiceName[MAX_PATH];
  45. BOOL Status = FALSE;
  46. /*
  47. * Extract the service name from the file name
  48. */
  49. {
  50. TCHAR drive[MAX_PATH], directory[MAX_PATH], ext[MAX_PATH];
  51. lsplitpath(szFile, drive, directory, ServiceName, ext);
  52. }
  53. /*
  54. * First try and obtain a handle to the service controller
  55. */
  56. SCManagerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  57. if (SCManagerHandle == NULL)
  58. {
  59. TCHAR szMesg[MAXSTR];
  60. TCHAR szMesg2[MAXSTR];
  61. LoadString(myInstance, IDS_INSUFFICIENT_PRIVILEGE, szMesg, sizeof(szMesg)/sizeof(TCHAR));
  62. wsprintf(szMesg2, szMesg, szFile);
  63. MessageBox(hMesgBoxParent, szMesg2, szRemove, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
  64. return FALSE;
  65. }
  66. ServiceHandle = OpenService(SCManagerHandle,
  67. ServiceName,
  68. SERVICE_ALL_ACCESS);
  69. if (ServiceHandle != NULL)
  70. {
  71. SERVICE_STATUS ServiceStatus;
  72. SC_LOCK ServicesDatabaseLock;
  73. /*
  74. * Stop the service if possible.
  75. */
  76. ControlService(ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus);
  77. /*
  78. * Delete the service.
  79. * We aren't detecting if we can just carry on.
  80. */
  81. /*
  82. * Lock the service controller database to avoid deadlocks
  83. * we have to loop because we can't wait
  84. */
  85. for (ServicesDatabaseLock = NULL;
  86. (ServicesDatabaseLock =
  87. LockServiceDatabase(SCManagerHandle))
  88. == NULL;
  89. Sleep(100))
  90. {
  91. }
  92. Status = DeleteService(ServiceHandle);
  93. UnlockServiceDatabase(ServicesDatabaseLock);
  94. CloseServiceHandle(ServiceHandle);
  95. }
  96. else
  97. {
  98. /*
  99. * It's possible there was no services entry so the driver
  100. * wasn't really installed after all.
  101. */
  102. LONG Error = GetLastError();
  103. if (Error == ERROR_FILE_NOT_FOUND ||
  104. Error == ERROR_PATH_NOT_FOUND ||
  105. Error == ERROR_SERVICE_DOES_NOT_EXIST)
  106. {
  107. Status = TRUE;
  108. }
  109. }
  110. CloseServiceHandle(SCManagerHandle);
  111. return Status;
  112. }
  113. /*
  114. ** PostRemove()
  115. **
  116. ** Mark an installed driver for removal later AND remove the driver's entry
  117. ** in SYSTEM.INI to avoid conflicts when we add or remove later.
  118. */
  119. LONG_PTR PostRemove(PIDRIVER pIDriver, BOOL bLookAtRelated)
  120. {
  121. TCHAR *keystr;
  122. TCHAR allkeystr[MAXSTR];
  123. TCHAR szfile[MAX_PATH];
  124. HANDLE hDriver;
  125. LONG_PTR Status = DRVCNF_CANCEL;
  126. LPTSTR pstr;
  127. GetPrivateProfileString(pIDriver->szSection,
  128. pIDriver->szAlias,
  129. pIDriver->szFile,
  130. pIDriver->szFile,
  131. MAX_PATH,
  132. szSysIni);
  133. /*
  134. * Remove parameters from file name
  135. */
  136. if (pIDriver->szFile)
  137. {
  138. for ( pstr=pIDriver->szFile; *pstr && (*pstr!=COMMA) &&
  139. (*pstr!=SPACE); pstr++ )
  140. ;
  141. *pstr = TEXT('\0');
  142. }
  143. if (bLookAtRelated && (!bRelated || pIDriver->bRelated))
  144. wcscpy(szRestartDrv, pIDriver->szDesc);
  145. /*
  146. * If it's a kernel driver remove it from the config registry
  147. * and services controller
  148. */
  149. if (pIDriver->KernelDriver)
  150. {
  151. Status = RemoveService(pIDriver->szFile) ? DRVCNF_RESTART : DRVCNF_CANCEL;
  152. if (Status == DRVCNF_CANCEL)
  153. {
  154. return DRVCNF_CANCEL;
  155. }
  156. }
  157. else
  158. {
  159. hDriver = OpenDriver(pIDriver->wszAlias, pIDriver->wszSection, 0L);
  160. if (hDriver)
  161. {
  162. /*
  163. * Removal can fail so don't mark as deleted in this case
  164. */
  165. Status = SendDriverMessage(hDriver, DRV_REMOVE, 0L, 0L);
  166. CloseDriver(hDriver, 0L, 0L);
  167. if (Status == DRVCNF_CANCEL)
  168. {
  169. return DRVCNF_CANCEL;
  170. }
  171. }
  172. }
  173. // Remove the driver from the treeview,
  174. // but don't free its structure
  175. //
  176. RemoveIDriver (hAdvDlgTree, pIDriver, FALSE);
  177. if (bLookAtRelated)
  178. {
  179. TCHAR allkeystr[MAXSTR];
  180. if (GetPrivateProfileString(szRelatedDesc, pIDriver->szAlias,
  181. allkeystr, allkeystr, sizeof(allkeystr) / sizeof(TCHAR), szControlIni))
  182. {
  183. int i;
  184. TCHAR szTemp[MAXSTR];
  185. for (i = 1; infParseField(allkeystr, i, szTemp);i++)
  186. {
  187. PIDRIVER pid;
  188. if ((pid = FindIDriverByName (szTemp)) != NULL)
  189. {
  190. if (PostRemove (pid, FALSE) == DRVCNF_RESTART)
  191. {
  192. Status = DRVCNF_RESTART;
  193. }
  194. }
  195. }
  196. }
  197. }
  198. // Remove the driver entry from SYSTEM.INI so you don't
  199. // conflict with other drivers.
  200. GetPrivateProfileString(pIDriver->szSection, NULL, NULL,
  201. allkeystr, sizeof(allkeystr) / sizeof(TCHAR), szSysIni);
  202. keystr = allkeystr;
  203. while (wcslen(keystr) > 0)
  204. {
  205. GetPrivateProfileString(pIDriver->szSection, keystr, NULL, szfile, sizeof(szfile) / sizeof(TCHAR), szSysIni);
  206. if (!FileNameCmp(pIDriver->szFile, szfile))
  207. RemoveDriverEntry(keystr, pIDriver->szFile, pIDriver->szSection, bLookAtRelated);
  208. keystr = &keystr[wcslen(keystr) + sizeof(TCHAR)];
  209. }
  210. return Status;
  211. }
  212. void RemoveDriverEntry (LPTSTR szKey, LPTSTR szFile, LPTSTR szSection, BOOL bLookAtRelated)
  213. {
  214. /*
  215. * Remove entry for loading driver
  216. */
  217. WritePrivateProfileString(szSection, szKey, NULL, szSysIni);
  218. /*
  219. * Delete entry for parameters for this driver
  220. */
  221. WriteProfileString(szFile, szKey, NULL);
  222. /*
  223. * Remove entry which says this is a user driver (as opposed to
  224. * a pre-installed one).
  225. */
  226. WritePrivateProfileString(szUserDrivers, szKey, NULL, szControlIni);
  227. /*
  228. * Remove description
  229. */
  230. WritePrivateProfileString(szDriversDesc, szFile, NULL, szControlIni);
  231. /*
  232. * Remove links to related drivers
  233. */
  234. WritePrivateProfileString(szRelatedDesc, szKey, NULL, szControlIni);
  235. #ifdef DOBOOT
  236. FindBootDriver(szKey);
  237. #endif // DOBOOT
  238. if (bLookAtRelated)
  239. SetValidAlias(szKey, szSection);
  240. }
  241. /*
  242. * SetValidAlias()
  243. *
  244. * Check to see if the alias removed would create a hole in the device
  245. * numbering scheme. If so switch the last device number with the deleted one.
  246. */
  247. BOOL SetValidAlias(LPTSTR pstrType, LPTSTR pstrSection)
  248. {
  249. TCHAR *keystr;
  250. static TCHAR allkeystr[MAXSTR];
  251. static TCHAR szExKey[MAXSTR], szExFile[MAXSTR], szExDesc[MAXSTR];
  252. BOOL bfound = FALSE, bExchange = FALSE;
  253. int val, maxval = 0, typelen, len;
  254. /*
  255. * Getting length of alias
  256. */
  257. len = typelen = wcslen(pstrType);
  258. // If the last TCHAR on the type is a number don't consider it
  259. if (pstrType[typelen - 1] > TEXT('0') && pstrType[typelen - 1] <= TEXT('9'))
  260. typelen--;
  261. // Get all the aliases in the drivers section
  262. GetPrivateProfileString(pstrSection, NULL, NULL, allkeystr,
  263. sizeof(allkeystr) / sizeof(TCHAR), szSysIni);
  264. keystr = allkeystr;
  265. while (*keystr != TEXT('\0'))
  266. {
  267. // Compare the root of the aliases
  268. if (!_wcsnicmp(keystr, pstrType, typelen) && ((keystr[typelen] <= TEXT('9') && keystr[typelen] > TEXT('0')) || keystr[typelen] == TEXT('\0')))
  269. {
  270. //We found a common alias
  271. bfound = TRUE;
  272. val = _wtoi(&keystr[typelen]);
  273. if (val > maxval)
  274. {
  275. maxval = val;
  276. wcscpy(szExKey, keystr);
  277. }
  278. }
  279. //Pointer to next alias
  280. keystr = &keystr[wcslen(keystr) + sizeof(TCHAR)];
  281. }
  282. //If we found one
  283. if (bfound)
  284. {
  285. if (len == typelen)
  286. bExchange = TRUE;
  287. else
  288. if (_wtoi(&pstrType[typelen]) < maxval)
  289. bExchange = TRUE;
  290. // We need to exchange it with the one we found
  291. if (bExchange)
  292. {
  293. //Exchanging the one in the drivers section in system.ini
  294. GetPrivateProfileString(pstrSection, szExKey, NULL, szExFile,
  295. sizeof(szExFile) / sizeof(TCHAR), szSysIni);
  296. WritePrivateProfileString(pstrSection, szExKey, NULL, szSysIni);
  297. WritePrivateProfileString(pstrSection, pstrType, szExFile, szSysIni);
  298. #ifdef TRASHDRIVERDESC
  299. //Exchanging the one in the drivers description section of control.ini
  300. GetPrivateProfileString(szDriversDesc, szExKey, NULL, szExDesc, sizeof(szExFile) / sizeof(TCHAR), szControlIni);
  301. WritePrivateProfileString(szDriversDesc, szExKey, NULL, szControlIni);
  302. WritePrivateProfileString(szDriversDesc, pstrType, szExDesc, szControlIni);
  303. #endif
  304. //If any related drivers were present under old alias switch them
  305. GetPrivateProfileString(szRelatedDesc, szExKey, NULL, szExDesc, sizeof(szExFile) / sizeof(TCHAR), szControlIni);
  306. if (wcslen(szExDesc))
  307. {
  308. WritePrivateProfileString(szRelatedDesc, szExKey, NULL, szControlIni);
  309. WritePrivateProfileString(szRelatedDesc, pstrType, szExDesc, szControlIni);
  310. }
  311. //If user installed driver under old alias switch them
  312. GetPrivateProfileString(szUserDrivers, szExKey, NULL, szExDesc, sizeof(szExFile) / sizeof(TCHAR), szControlIni);
  313. if (wcslen(szExDesc))
  314. {
  315. WritePrivateProfileString(szUserDrivers, szExKey, NULL, szControlIni);
  316. WritePrivateProfileString(szUserDrivers, pstrType, szExDesc, szControlIni);
  317. }
  318. #ifdef DOBOOT
  319. if (FindBootDriver(szExKey))
  320. {
  321. static TCHAR szTemp[MAXSTR];
  322. GetPrivateProfileString(szBoot, szDrivers, szTemp, szTemp,
  323. sizeof(szTemp) / sizeof(TCHAR), szSysIni);
  324. strcat(szTemp, TEXT(" "));
  325. strcat(szTemp, pstrType);
  326. WritePrivateProfileString(szBoot, szDrivers, szTemp, szSysIni);
  327. }
  328. #endif // DOBOOT
  329. }
  330. }
  331. return(bExchange);
  332. }
  333. int FileNameCmp(TCHAR far *pch1, TCHAR far *pch2)
  334. {
  335. LPTSTR pchEOS;
  336. while (*pch1 == TEXT(' ')) pch1++; // eat spaces
  337. while (*pch2 == TEXT(' ')) pch2++; // eat spaces
  338. for (pchEOS = pch1; *pchEOS && *pchEOS != TEXT(' '); pchEOS++);
  339. return _wcsnicmp(pch1, pch2, (size_t)(pchEOS - pch1));
  340. }
  341. #ifdef DOBOOT
  342. PSTR strstri(LPTSTR pszStr, LPTSTR pszKey)
  343. {
  344. while (pszStr)
  345. if (!_strnicmp(pszStr, pszKey, lstrlen(pszKey)))
  346. return(pszStr);
  347. else
  348. pszStr++;
  349. return(NULL);
  350. }
  351. /*
  352. * FindBootDriver()
  353. * Checks to see if the driver alias is on the drivers line of the
  354. * boot section. If so the alias is removed from the line.
  355. */
  356. BOOL FindBootDriver(TCHAR *szKey)
  357. {
  358. TCHAR *ptr;
  359. int wKeyLen = (int)wcslen(szKey);
  360. TCHAR *endkey;
  361. static TCHAR szDriverline[MAXSTR];
  362. GetPrivateProfileString(TEXT("boot"), TEXT("drivers"), szDriverline, szDriverline,
  363. MAX_PATH, szSysIni);
  364. ptr = strstri(szDriverline, szKey);
  365. if (ptr)
  366. {
  367. if ((((ptr != szDriverline) && (*(ptr - 1) == TEXT(' ') )) ||
  368. (ptr == szDriverline)) &&
  369. (*(ptr + wKeyLen) == TEXT(' ') || *(ptr + wKeyLen) == NULL))
  370. {
  371. endkey = ptr + wKeyLen;
  372. while (*endkey)
  373. *ptr++ = *endkey++;
  374. *ptr = NULL;
  375. WritePrivateProfileString(TEXT("boot"), TEXT("drivers"), szDriverline,
  376. szSysIni);
  377. return(TRUE);
  378. }
  379. }
  380. return(FALSE);
  381. }
  382. #endif // DOBOOT
  383. // Steal use of function in midi.c to delete a reg subtree.
  384. LONG SHRegDeleteKey(HKEY hKey, LPCTSTR lpSubKey);
  385. //****************************************************************************
  386. // Function: mystrtok()
  387. //
  388. // Purpose: Returns a pointer to the next token in a string.
  389. //
  390. // Parameters:
  391. // SrcString String containing token(s)
  392. // Seps Set of delimiter characters
  393. // State Pointer to a char* to hold state info
  394. // Return Code:
  395. // Ptr to next token, or NULL if no tokens left
  396. //
  397. // Comments:
  398. // Fixes problem with standard strtok, which can't be called recursively.
  399. //
  400. //****************************************************************************
  401. LPTSTR mystrtok(LPTSTR SrcString, LPCTSTR Seps, LPTSTR FAR *State)
  402. {
  403. LPTSTR ThisString;
  404. LPTSTR NextString;
  405. // If Seps is NULL, use default separators
  406. if (!Seps)
  407. {
  408. Seps = TEXT(" ,\t"); // space, comma, tab chars
  409. }
  410. if (SrcString)
  411. ThisString = SrcString;
  412. else
  413. ThisString = *State;
  414. // Find beginning of the current string
  415. ThisString = ThisString + wcsspn(ThisString,Seps);
  416. if (ThisString[0]==TEXT('\0'))
  417. return NULL;
  418. // Find the end of the current string
  419. NextString = ThisString + wcscspn(ThisString,Seps);
  420. if (NextString[0]!=TEXT('\0'))
  421. {
  422. *NextString++=TEXT('\0');
  423. }
  424. *State = NextString;
  425. return ThisString;
  426. }
  427. BOOL RemoveDriver(IN HDEVINFO DeviceInfoSet,
  428. IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
  429. )
  430. {
  431. BOOL bRet = FALSE; // Return value
  432. TCHAR szDriverKey[MAX_PATH]; // Value of Driver's key in Enum branch
  433. TCHAR *pszDrvInst; // Driver's instance, e.g. "0000", "0001", etc.
  434. HKEY hkDevReg = NULL; // Key to Driver portion of registry (e.g. classguid\0000)
  435. HKEY hkDrivers32 = NULL; // Key to Drivers32 portion of registry
  436. HKEY hkDrivers = NULL; // Key to classguid\0000\Drivers
  437. TCHAR szSubClasses[256]; // List of subclasses to process
  438. TCHAR *strtok_State; // strtok state
  439. TCHAR *pszClass; // Information about e.g. classguid\0000\Drivers\wave
  440. HKEY hkClass;
  441. DWORD idxR3DriverName; // Information about e.g. classguid\0000\Drivers\wave\foo.drv
  442. HKEY hkR3DriverName;
  443. TCHAR szR3DriverName[64];
  444. TCHAR szAlias[64]; // Alias in Drivers32 (e.g. wave1)
  445. TCHAR szDriver[64]; // Name of driver
  446. DWORD cbLen;
  447. LPCTSTR szAliasStringToUse; // Pointer to the Alias value name to use
  448. BOOL bIsWOW64Process = FALSE;// TRUE if we're running under WOW64
  449. //
  450. // If we're running in WOW64, we need to use a different Alias string so that
  451. // we don't overwrite the 64-bit alias string
  452. //
  453. if( IsWow64Process(GetCurrentProcess(), &bIsWOW64Process)
  454. && bIsWOW64Process )
  455. {
  456. szAliasStringToUse = gszAliasWOW64Value;
  457. }
  458. else
  459. {
  460. szAliasStringToUse = gszAliasValue;
  461. }
  462. // Get the Drivers key value under the device's Enum branch,
  463. // e.g. something like "{4D36E96C-E325-11CE-BFC1-08002BE10318}\0000"
  464. SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
  465. DeviceInfoData,
  466. SPDRP_DRIVER ,
  467. NULL,
  468. (LPBYTE)szDriverKey,
  469. MAX_PATH,
  470. NULL);
  471. // Get everything after the last \ character
  472. pszDrvInst = wcsrchr(szDriverKey,TEXT('\\'));
  473. if (!pszDrvInst)
  474. {
  475. goto RemoveDrivers32_exit;
  476. }
  477. pszDrvInst++;
  478. // Now pszDrvInst points to a string with the Driver Instance, e.g. "0000"
  479. // Open the Drivers32 section of the registry
  480. if (RegOpenKey(HKEY_LOCAL_MACHINE,
  481. TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32"),
  482. &hkDrivers32))
  483. {
  484. goto RemoveDrivers32_exit;
  485. }
  486. // Open the Driver reg key
  487. hkDevReg = SetupDiOpenDevRegKey(DeviceInfoSet,
  488. DeviceInfoData,
  489. DICS_FLAG_GLOBAL,
  490. 0,
  491. DIREG_DRV,
  492. KEY_ALL_ACCESS);
  493. if (hkDevReg == INVALID_HANDLE_VALUE)
  494. {
  495. goto RemoveDrivers32_exit;
  496. }
  497. // Enumerate through supporter classes in the Drivers subkey
  498. if (RegOpenKey(hkDevReg, TEXT("Drivers"), &hkDrivers))
  499. {
  500. goto RemoveDrivers32_exit;
  501. }
  502. // Read the SubClasses key to determine which subclasses to process
  503. cbLen=sizeof(szSubClasses);
  504. if (RegQueryValueEx(hkDrivers, TEXT("Subclasses"), NULL, NULL, (LPBYTE)szSubClasses, &cbLen))
  505. {
  506. goto RemoveDrivers32_exit;
  507. }
  508. // Enumerate all the subclasses
  509. for (
  510. pszClass = mystrtok(szSubClasses,NULL,&strtok_State);
  511. pszClass;
  512. pszClass = mystrtok(NULL,NULL,&strtok_State)
  513. )
  514. {
  515. #ifdef _WIN64
  516. //
  517. // Check for magic WaveWOW64 value
  518. if( 0 == _wcsnicmp( pszClass, gszWaveWOW64Value, wcslen(gszWaveWOW64Value) ) )
  519. {
  520. // Thunk the installation to the 32-bit mmsys.cpl installer
  521. mmWOW64ThunkMediaClassInstaller(DIF_REMOVE, DeviceInfoSet, DeviceInfoData);
  522. continue;
  523. }
  524. #endif //_WIN64
  525. // Open up each subclass
  526. if (RegOpenKey(hkDrivers, pszClass, &hkClass))
  527. {
  528. continue;
  529. }
  530. // Under each class is a set of driver name subkeys.
  531. // For each driver (e.g. foo1.drv, foo2.drv, etc.)
  532. for (idxR3DriverName = 0;
  533. !RegEnumKey(hkClass, idxR3DriverName, szR3DriverName, sizeof(szR3DriverName)/sizeof(TCHAR));
  534. idxR3DriverName++)
  535. {
  536. // Open the key to the driver name
  537. if (RegOpenKey(hkClass, szR3DriverName, &hkR3DriverName))
  538. {
  539. continue;
  540. }
  541. // Get the value of Driver under the driver name key
  542. cbLen = sizeof(szDriver);
  543. if (!RegQueryValueEx(hkR3DriverName, TEXT("Driver"), NULL, NULL, (LPBYTE)szDriver, &cbLen))
  544. {
  545. // Send the driver a DRV_REMOVE message to the driver
  546. HANDLE hDriver;
  547. hDriver = OpenDriver(szDriver, NULL, 0L);
  548. if (hDriver)
  549. {
  550. SendDriverMessage(hDriver, DRV_REMOVE, 0L, 0L);
  551. CloseDriver(hDriver, 0L, 0L);
  552. }
  553. }
  554. // Get the value of Alias under the driver name key
  555. cbLen = sizeof(szAlias);
  556. if (!RegQueryValueEx(hkR3DriverName, szAliasStringToUse, NULL, NULL, (LPBYTE)szAlias, &cbLen))
  557. {
  558. // Delete the corresponding entry in Drivers32
  559. RegDeleteValue(hkDrivers32,szAlias);
  560. }
  561. // Close the Driver Name key
  562. RegCloseKey(hkR3DriverName);
  563. }
  564. // Close the class key
  565. RegCloseKey(hkClass);
  566. }
  567. bRet = TRUE;
  568. RemoveDrivers32_exit:
  569. if (hkDrivers32) RegCloseKey(hkDrivers32);
  570. if (hkDevReg) RegCloseKey(hkDevReg);
  571. if (hkDrivers) RegCloseKey(hkDrivers);
  572. return bRet;
  573. }
  574. // The driver's private registry section is located in something like:
  575. // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E96C-E325-11CE-BFC1-08002BE10318}\xxxx
  576. // where xxxx is the device instance (e.g. 0000, 0001, etc.)
  577. // These last four digits are used to index into the driver's MediaResources section.
  578. // For example, suppose a device has a driver instance
  579. // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E96C-E325-11CE-BFC1-08002BE10318}\0001
  580. // and under that entry there is a Drivers\wave\foo.drv, meaning that the foo.drv driver supports a wave
  581. // API.
  582. // In this case, there would be an entry in
  583. // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\MediaResources\wave\foo.drv<0001>
  584. //
  585. // On removal, we need to delete that entry.
  586. BOOL RemoveMediaResources(IN HDEVINFO DeviceInfoSet,
  587. IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
  588. )
  589. {
  590. BOOL bRet = FALSE; // Return value
  591. TCHAR szDriverKey[MAX_PATH]; // Value of Driver's key in Enum branch
  592. TCHAR *pszDrvInst; // Driver's instance, e.g. "0000", "0001", etc.
  593. HKEY hkDevReg = NULL; // Key to Driver portion of registry (e.g. classguid\0000)
  594. HKEY hkDrivers = NULL; // Key to classguid\0000\Drivers
  595. HKEY hkMR = NULL; // Handle to MediaResources section
  596. TCHAR szSubClasses[256]; // List of subclasses to process
  597. TCHAR *strtok_State; // strtok state
  598. TCHAR *pszClass; // Information about e.g. classguid\0000\Drivers\wave
  599. HKEY hkClass;
  600. DWORD idxR3DriverName; // Information about e.g. classguid\0000\Drivers\wave\foo.drv
  601. HKEY hkR3DriverName;
  602. TCHAR szR3DriverName[64];
  603. TCHAR szDriver[64]; // Driver name (e.g. foo.drv)
  604. DWORD cbLen; // Size of szDriver
  605. TCHAR szDevNode[MAX_PATH+1]; // Path to driver's reg entry
  606. TCHAR szSoftwareKey[MAX_PATH+1]; // Value of SOFTWAREKEY
  607. // Open Media Resources section of registry
  608. if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_MEDIARESOURCES, &hkMR))
  609. {
  610. goto RemoveMediaResources_exit;
  611. }
  612. // Get the Drivers key value under the device's Enum branch,
  613. // e.g. something like "{4D36E96C-E325-11CE-BFC1-08002BE10318}\0000"
  614. SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
  615. DeviceInfoData,
  616. SPDRP_DRIVER ,
  617. NULL,
  618. (LPBYTE)szDriverKey,
  619. MAX_PATH,
  620. NULL);
  621. // Get everything after the last \ character
  622. pszDrvInst = wcsrchr(szDriverKey,TEXT('\\'));
  623. if (!pszDrvInst)
  624. {
  625. goto RemoveMediaResources_exit;
  626. }
  627. pszDrvInst++;
  628. // Now pszDrvInst points to a string with the Driver Instance, e.g. "0000"
  629. // Get full path to driver key
  630. wsprintf(szDevNode,
  631. TEXT("%s\\%s"),
  632. REGSTR_PATH_CLASS_NT,
  633. (LPTSTR)szDriverKey);
  634. // Open the Driver reg key
  635. hkDevReg = SetupDiOpenDevRegKey(DeviceInfoSet,
  636. DeviceInfoData,
  637. DICS_FLAG_GLOBAL,
  638. 0,
  639. DIREG_DRV,
  640. KEY_ALL_ACCESS);
  641. if (hkDevReg == INVALID_HANDLE_VALUE)
  642. {
  643. goto RemoveMediaResources_exit;
  644. }
  645. // Enumerate through supporter classes in the Drivers subkey
  646. if (RegOpenKey(hkDevReg, TEXT("Drivers"), &hkDrivers))
  647. {
  648. goto RemoveMediaResources_exit;
  649. }
  650. // Read the SubClasses key to determine which subclasses to process
  651. cbLen=sizeof(szSubClasses);
  652. if (RegQueryValueEx(hkDrivers, TEXT("Subclasses"), NULL, NULL, (LPBYTE)szSubClasses, &cbLen))
  653. {
  654. goto RemoveMediaResources_exit;
  655. }
  656. // Enumerate all the subclasses
  657. for (
  658. pszClass = mystrtok(szSubClasses,NULL,&strtok_State);
  659. pszClass;
  660. pszClass = mystrtok(NULL,NULL,&strtok_State)
  661. )
  662. {
  663. if (RegOpenKey(hkDrivers, pszClass, &hkClass))
  664. {
  665. continue;
  666. }
  667. // Under each class is a set of driver name subkeys.
  668. // For each driver (e.g. foo1.drv, foo2.drv, etc.)
  669. for (idxR3DriverName = 0;
  670. !RegEnumKey(hkClass, idxR3DriverName, szR3DriverName, sizeof(szR3DriverName)/sizeof(TCHAR));
  671. idxR3DriverName++)
  672. {
  673. // Open the key to the driver name
  674. if (RegOpenKey(hkClass, szR3DriverName, &hkR3DriverName))
  675. {
  676. continue;
  677. }
  678. // Get the value of Driver in under the driver name key
  679. cbLen = sizeof(szDriver);
  680. if (!RegQueryValueEx(hkR3DriverName, TEXT("Driver"), NULL, NULL, (LPBYTE)szDriver, &cbLen))
  681. {
  682. TCHAR szR3Path[256];
  683. // Create a path to the MediaResources entry to be deleted
  684. wsprintf(szR3Path,
  685. TEXT("%s\\%s\\%s<%s>"),
  686. REGSTR_PATH_MEDIARESOURCES,
  687. (LPTSTR)pszClass,
  688. (LPTSTR)szDriver,
  689. (LPTSTR)pszDrvInst);
  690. // Delete the key
  691. SHRegDeleteKey(HKEY_LOCAL_MACHINE, szR3Path);
  692. }
  693. // Close the Driver Name key
  694. RegCloseKey(hkR3DriverName);
  695. }
  696. // Close the class key in the devnode
  697. RegCloseKey(hkClass);
  698. // Backup mechanism, in case we missed something.
  699. // This shouldn't be necessary, but Win98 does it.
  700. // Open the class key in MediaResources
  701. if (RegOpenKey(hkMR, pszClass, &hkClass))
  702. {
  703. continue;
  704. }
  705. // Count the number of subkeys under the class key
  706. // We're gonna do this backwards because we'll be deleting keys later
  707. for (idxR3DriverName = 0;
  708. !RegEnumKey(hkClass, idxR3DriverName, szR3DriverName, sizeof(szR3DriverName)/sizeof(TCHAR));
  709. idxR3DriverName++)
  710. {
  711. ;
  712. }
  713. // For each driver subkey, working backwards.
  714. // Subkeys are e.g. msacm.iac2, msacm.imaadpcm, etc.
  715. for (idxR3DriverName--;
  716. ((int)idxR3DriverName >= 0) &&
  717. !RegEnumKey(hkClass, idxR3DriverName, szR3DriverName, sizeof(szR3DriverName)/sizeof(TCHAR));
  718. idxR3DriverName--)
  719. {
  720. // Open the driver key
  721. if (RegOpenKey(hkClass, szR3DriverName, &hkR3DriverName))
  722. {
  723. continue;
  724. }
  725. // Query the value of "SOFTWAREKEY"
  726. szSoftwareKey[0]=TEXT('\0'); // Init to safe value in case call fails
  727. cbLen = sizeof(szSoftwareKey);
  728. RegQueryValueEx(hkR3DriverName, TEXT("SOFTWAREKEY"), NULL, NULL, (LPBYTE)szSoftwareKey, &cbLen);
  729. // Close now, since we might delete in next line
  730. RegCloseKey(hkR3DriverName);
  731. // If the value of "SOFTWAREKEY" matches the path to the devnode, delete the key
  732. if (!lstrcmpi(szSoftwareKey, szDevNode))
  733. {
  734. SHRegDeleteKey(hkClass, szR3DriverName);
  735. }
  736. }
  737. // Close the class key in MediaResources
  738. RegCloseKey(hkClass);
  739. }
  740. bRet = TRUE;
  741. RemoveMediaResources_exit:
  742. if (hkDevReg) RegCloseKey(hkDevReg);
  743. if (hkDrivers) RegCloseKey(hkDrivers);
  744. if (hkMR) RegCloseKey(hkMR);
  745. return bRet;
  746. }
  747. // Clear out entries in the Driver's branch of the registry, e.g. in {4D36E96C-E325-11CE-BFC1-08002BE10318}\0000
  748. BOOL RemoveDriverInfo(IN HDEVINFO DeviceInfoSet,
  749. IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
  750. )
  751. {
  752. HKEY hkDevReg; // Key to Driver portion of registry (e.g. classguid\0000)
  753. // Remove entries in the driver's reg section
  754. hkDevReg = SetupDiOpenDevRegKey(DeviceInfoSet,
  755. DeviceInfoData,
  756. DICS_FLAG_GLOBAL,
  757. 0,
  758. DIREG_DRV,
  759. KEY_ALL_ACCESS);
  760. if (hkDevReg == INVALID_HANDLE_VALUE)
  761. {
  762. return FALSE;
  763. }
  764. // Delete any entries that might cause trouble
  765. RegDeleteValue(hkDevReg,REGSTR_VAL_DEVLOADER);
  766. RegDeleteValue(hkDevReg,REGSTR_VAL_DRIVER);
  767. RegDeleteValue(hkDevReg,REGSTR_VAL_ENUMPROPPAGES);
  768. RegDeleteValue(hkDevReg,TEXT("NTMPDriver"));
  769. RegDeleteValue(hkDevReg,TEXT("AssociatedFilters"));
  770. RegDeleteValue(hkDevReg,TEXT("FDMA"));
  771. RegDeleteValue(hkDevReg,TEXT("DriverType"));
  772. // Blow away the Drivers subtree
  773. SHRegDeleteKey(hkDevReg,TEXT("Drivers"));
  774. // For future use, allow a key under which everything gets blown away
  775. SHRegDeleteKey(hkDevReg,TEXT("UnretainedSettings"));
  776. RegCloseKey(hkDevReg);
  777. return TRUE;
  778. }
  779. // Clear out entries in the Device's Enum branch of the registry:
  780. BOOL RemoveDeviceInfo(IN HDEVINFO DeviceInfoSet,
  781. IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
  782. )
  783. {
  784. // Remove the Driver key. It looks something like "Driver = {4D36E96C-E325-11CE-BFC1-08002BE10318}\0000"
  785. // !!NO don't remove driver key, or else on driver upgrade system loses track of node & creates a new one
  786. // SetupDiSetDeviceRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_DRIVER , NULL, 0);
  787. // Remove the Service key.
  788. // Make sure before doing anything else that there is no service property for
  789. // this device instance. This allows us to know whether we should clean up the
  790. // device instance if we boot and find that it's no longer present.
  791. SetupDiSetDeviceRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_SERVICE, NULL, 0);
  792. return TRUE;
  793. }
  794. /* 5/14/98 andyraf for NT5 */
  795. /* Media_RemoveDevice
  796. *
  797. * This function gets called on driver removal (DIF_REMOVE) and driver installation (DIF_INSTALL).
  798. * It cleans up all the registry entries associated with the driver.
  799. */
  800. DWORD Media_RemoveDevice(IN HDEVINFO DeviceInfoSet,
  801. IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
  802. )
  803. {
  804. #if 0
  805. // Don't know how to do this on NT5
  806. if ((diFunction == DIF_REMOVE) &&
  807. (lpdi->Flags & DI_CLASSINSTALLPARAMS) &&
  808. (((LPREMOVEDEVICE_PARAMS)lpdi->lpClassInstallParams)->dwFlags & DI_REMOVEDEVICE_CONFIGSPECIFIC))
  809. {
  810. return ERROR_DI_DO_DEFAULT;
  811. }
  812. // Not needed on NT5??
  813. CleanupDummySysIniDevs(); //remove the wave=*.drv and midi=*.drv dummy devices.
  814. #endif
  815. #if 0 // We'll allow people to remove these drivers for now
  816. if (IsSpecialDriver(DeviceInfoSet, DeviceInfoData))
  817. {
  818. return NO_ERROR;
  819. }
  820. #endif
  821. // Send DRV_REMOVE to each driver and clean out Drivers32 section of registry
  822. RemoveDriver (DeviceInfoSet, DeviceInfoData);
  823. // Clean out MediaResources section of registry
  824. RemoveMediaResources(DeviceInfoSet, DeviceInfoData);
  825. // Clean out driver's classguid\instance section of registry
  826. RemoveDriverInfo (DeviceInfoSet, DeviceInfoData);
  827. // Clean out device's enum section of registry
  828. RemoveDeviceInfo (DeviceInfoSet, DeviceInfoData);
  829. return ERROR_DI_DO_DEFAULT;
  830. }
  831. #if 0 // Unused at present
  832. BOOL AddDrivers32(IN HDEVINFO DeviceInfoSet,
  833. IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
  834. )
  835. {
  836. BOOL bRet = FALSE; // Return value
  837. TCHAR szDriverKey[MAX_PATH]; // Value of Driver's key in Enum branch
  838. TCHAR *pszDrvInst; // Driver's instance, e.g. "0000", "0001", etc.
  839. HKEY hkDevReg = NULL; // Key to Driver portion of registry (e.g. classguid\0000)
  840. HKEY hkDrivers32 = NULL; // Key to Drivers32 portion of registry
  841. HKEY hkDrivers = NULL; // Key to classguid\0000\Drivers
  842. HKEY hkDriversDesc = NULL; // Key to drivers.desc portion of registry
  843. TCHAR szSubClasses[256]; // List of subclasses to process
  844. TCHAR *strtok_State; // strtok state
  845. TCHAR *pszClass; // Information about e.g. classguid\0000\Drivers\wave
  846. HKEY hkClass;
  847. DWORD idxR3DriverName; // Information about e.g. classguid\0000\Drivers\wave\foo.drv
  848. HKEY hkR3DriverName;
  849. TCHAR szR3DriverName[64];
  850. TCHAR szAlias[64]; // Alias in Drivers32 (e.g. wave1)
  851. TCHAR szDriver[64]; // Name of driver
  852. TCHAR szDescription[MAX_PATH];
  853. DWORD cbLen;
  854. // Get the Drivers key value under the device's Enum branch,
  855. // e.g. something like "{4D36E96C-E325-11CE-BFC1-08002BE10318}\0000"
  856. SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
  857. DeviceInfoData,
  858. SPDRP_DRIVER ,
  859. NULL,
  860. (LPBYTE)szDriverKey,
  861. MAX_PATH,
  862. NULL);
  863. // Get everything after the last \ character
  864. pszDrvInst = strrchr(szDriverKey,TEXT('\\'));
  865. if (!pszDrvInst)
  866. {
  867. goto RemoveDrivers32_exit;
  868. }
  869. pszDrvInst++;
  870. // Now pszDrvInst points to a string with the Driver Instance, e.g. "0000"
  871. // Open the Drivers32 section of the registry
  872. if (RegOpenKey(HKEY_LOCAL_MACHINE,
  873. TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32"),
  874. &hkDrivers32))
  875. {
  876. goto RemoveDrivers32_exit;
  877. }
  878. // If we're adding a driver, need to open key to drivers.desc also
  879. if (RegOpenKey(HKEY_LOCAL_MACHINE,
  880. TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\drivers.desc"),
  881. &hkDriversDesc))
  882. {
  883. goto RemoveDrivers32_exit;
  884. }
  885. // Open the Driver reg key
  886. hkDevReg = SetupDiOpenDevRegKey(DeviceInfoSet,
  887. DeviceInfoData,
  888. DICS_FLAG_GLOBAL,
  889. 0,
  890. DIREG_DRV,
  891. KEY_ALL_ACCESS);
  892. if (hkDevReg == INVALID_HANDLE_VALUE)
  893. {
  894. goto RemoveDrivers32_exit;
  895. }
  896. // Enumerate through supporter classes in the Drivers subkey
  897. if (RegOpenKey(hkDevReg, TEXT("Drivers"), &hkDrivers))
  898. {
  899. goto RemoveDrivers32_exit;
  900. }
  901. // Read the SubClasses key to determine which subclasses to process
  902. cbLen=sizeof(szSubClasses);
  903. if (RegQueryValueEx(hkDrivers, TEXT("Subclasses"), NULL, NULL, (LPBYTE)szSubClasses, &cbLen))
  904. {
  905. goto RemoveDrivers32_exit;
  906. }
  907. // Enumerate all the subclasses
  908. for (
  909. pszClass = mystrtok(szSubClasses,NULL,&strtok_State);
  910. pszClass;
  911. pszClass = mystrtok(NULL,NULL,&strtok_State)
  912. )
  913. {
  914. // Open up each subclass
  915. if (RegOpenKey(hkDrivers, pszClass, &hkClass))
  916. {
  917. continue;
  918. }
  919. // Under each class is a set of driver name subkeys.
  920. // For each driver (e.g. foo1.drv, foo2.drv, etc.)
  921. for (idxR3DriverName = 0;
  922. !RegEnumKey(hkClass, idxR3DriverName, szR3DriverName, sizeof(szR3DriverName)/sizeof(TCHAR));
  923. idxR3DriverName++)
  924. {
  925. // Open the key to the driver name
  926. if (RegOpenKey(hkClass, szR3DriverName, &hkR3DriverName))
  927. {
  928. continue;
  929. }
  930. // Get driver name
  931. cbLen = sizeof(szDriver);
  932. if (!RegQueryValueEx(hkR3DriverName, TEXT("Driver"), NULL, NULL, (LPBYTE)szDriver, &cbLen))
  933. {
  934. // Create the alias
  935. wsprintf(szAlias,TEXT("%s.%s<%s>"),(LPTSTR)pszClass,(LPTSTR)szDriver,(LPTSTR)pszDrvInst);
  936. // Write into Drivers32
  937. RegSetValueExA(hkDrivers32,szAlias,0,REG_SZ,(PBYTE)szDriver,(wcslen(szDriver)*sizeof(TCHAR)) + sizeof(TCHAR));
  938. // Write alias back into driver's reg area
  939. RegSetValueExA(hkR3DriverName,TEXT("Alias"),0,REG_SZ,(PBYTE)szAlias,(wcslen(szAlias)*sizeof(TCHAR)) + sizeof(TCHAR));
  940. }
  941. // Write out Description
  942. // Get driver description
  943. cbLen = sizeof(szDescription);
  944. if (!RegQueryValueEx(hkR3DriverName, TEXT("Description"), NULL, NULL, (LPBYTE)szDescription, &cbLen))
  945. {
  946. RegSetValueExA(hkDriversDesc,szDriver,0,REG_SZ,(PBYTE)szDescription,(wcslen(szDescription)*sizeof(TCHAR)) + sizeof(TCHAR));
  947. }
  948. // Close the Driver Name key
  949. RegCloseKey(hkR3DriverName);
  950. }
  951. // Close the class key
  952. RegCloseKey(hkClass);
  953. }
  954. bRet = TRUE;
  955. RemoveDrivers32_exit:
  956. if (hkDrivers32) RegCloseKey(hkDrivers32);
  957. if (hkDevReg) RegCloseKey(hkDevReg);
  958. if (hkDrivers) RegCloseKey(hkDrivers);
  959. if (hkDriversDesc) RegCloseKey(hkDriversDesc);
  960. return bRet;
  961. }
  962. #endif
  963. #if 0 // Unused at present
  964. // The driver's private registry section is located in something like:
  965. // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E96C-E325-11CE-BFC1-08002BE10318}\xxxx
  966. // where xxxx is the device instance (e.g. 0000, 0001, etc.)
  967. // These last four digits are used to index into the driver's MediaResources section.
  968. // For example, suppose a device has a driver instance
  969. // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E96C-E325-11CE-BFC1-08002BE10318}\0001
  970. // and under that entry there is a Drivers\wave\foo.drv, meaning that the foo.drv driver supports a wave
  971. // API.
  972. // In this case, there would be an entry in
  973. // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\MediaResources\wave\foo.drv<0001>
  974. //
  975. // On removal, we need to delete that entry.
  976. BOOL AddMediaResources(IN HDEVINFO DeviceInfoSet,
  977. IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
  978. )
  979. {
  980. BOOL bRet = FALSE; // Return value
  981. TCHAR szDriverKey[MAX_PATH]; // Value of Driver's key in Enum branch
  982. TCHAR *pszDrvInst; // Driver's instance, e.g. "0000", "0001", etc.
  983. HKEY hkDevReg = NULL; // Key to Driver portion of registry (e.g. classguid\0000)
  984. HKEY hkDrivers = NULL; // Key to classguid\0000\Drivers
  985. HKEY hkMR = NULL; // Handle to MediaResources section
  986. TCHAR szSubClasses[256]; // List of subclasses to process
  987. TCHAR *strtok_State; // strtok state
  988. TCHAR *pszClass; // Information about e.g. classguid\0000\Drivers\wave
  989. HKEY hkClass;
  990. DWORD idxR3DriverName; // Information about e.g. classguid\0000\Drivers\wave\foo.drv
  991. HKEY hkR3DriverName;
  992. TCHAR szR3DriverName[64];
  993. TCHAR szDriver[64]; // Driver name (e.g. foo.drv)
  994. DWORD cbLen; // Size of szDriver
  995. TCHAR szDevNode[MAX_PATH+1]; // Path to driver's reg entry
  996. TCHAR szSoftwareKey[MAX_PATH+1]; // Value of SOFTWAREKEY
  997. // Open Media Resources section of registry
  998. if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_MEDIARESOURCES, &hkMR))
  999. {
  1000. goto RemoveMediaResources_exit;
  1001. }
  1002. // Get the Drivers key value under the device's Enum branch,
  1003. // e.g. something like "{4D36E96C-E325-11CE-BFC1-08002BE10318}\0000"
  1004. SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
  1005. DeviceInfoData,
  1006. SPDRP_DRIVER ,
  1007. NULL,
  1008. (LPBYTE)szDriverKey,
  1009. MAX_PATH,
  1010. NULL);
  1011. // Get everything after the last \ character
  1012. pszDrvInst = strrchr(szDriverKey,TEXT('\\'));
  1013. if (!pszDrvInst)
  1014. {
  1015. goto RemoveMediaResources_exit;
  1016. }
  1017. pszDrvInst++;
  1018. // Now pszDrvInst points to a string with the Driver Instance, e.g. "0000"
  1019. // Get full path to driver key
  1020. wsprintf(szDevNode,
  1021. TEXT("%s\\%s"),
  1022. REGSTR_PATH_CLASS_NT,
  1023. (LPTSTR)szDriverKey);
  1024. // Open the Driver reg key
  1025. hkDevReg = SetupDiOpenDevRegKey(DeviceInfoSet,
  1026. DeviceInfoData,
  1027. DICS_FLAG_GLOBAL,
  1028. 0,
  1029. DIREG_DRV,
  1030. KEY_ALL_ACCESS);
  1031. if (hkDevReg == INVALID_HANDLE_VALUE)
  1032. {
  1033. goto RemoveMediaResources_exit;
  1034. }
  1035. // Enumerate through supporter classes in the Drivers subkey
  1036. if (RegOpenKey(hkDevReg, TEXT("Drivers"), &hkDrivers))
  1037. {
  1038. goto RemoveMediaResources_exit;
  1039. }
  1040. // Read the SubClasses key to determine which subclasses to process
  1041. cbLen=sizeof(szSubClasses);
  1042. if (RegQueryValueEx(hkDrivers, TEXT("Subclasses"), NULL, NULL, (LPBYTE)szSubClasses, &cbLen))
  1043. {
  1044. goto RemoveMediaResources_exit;
  1045. }
  1046. // Enumerate all the subclasses
  1047. for (
  1048. pszClass = mystrtok(szSubClasses,NULL,&strtok_State);
  1049. pszClass;
  1050. pszClass = mystrtok(NULL,NULL,&strtok_State)
  1051. )
  1052. {
  1053. if (RegOpenKey(hkDrivers, pszClass, &hkClass))
  1054. {
  1055. continue;
  1056. }
  1057. // Under each class is a set of driver name subkeys.
  1058. // For each driver (e.g. foo1.drv, foo2.drv, etc.)
  1059. for (idxR3DriverName = 0;
  1060. !RegEnumKey(hkClass, idxR3DriverName, szR3DriverName, sizeof(szR3DriverName)/sizeof(TCHAR));
  1061. idxR3DriverName++)
  1062. {
  1063. // Open the key to the driver name
  1064. if (RegOpenKey(hkClass, szR3DriverName, &hkR3DriverName))
  1065. {
  1066. continue;
  1067. }
  1068. // Get the value of Driver in under the driver name key
  1069. cbLen = sizeof(szDriver);
  1070. if (!RegQueryValueEx(hkR3DriverName, TEXT("Driver"), NULL, NULL, (LPBYTE)szDriver, &cbLen))
  1071. {
  1072. HKEY hkMRClass;
  1073. HKEY hkMRDriver;
  1074. TCHAR szMRDriver[256];
  1075. // Create the class key if it doesn't already exist
  1076. if (!RegCreateKey(hkMR,pszClass,&hkMRClass))
  1077. {
  1078. continue;
  1079. }
  1080. // Create the driver key if it doesn't already exist
  1081. wsprintf(szMRDriver,
  1082. TEXT("%s<%s>"),
  1083. (LPTSTR)szDriver,
  1084. (LPTSTR)pszDrvInst);
  1085. if (!RegCreateKey(hkMRClass,szMRDriver,&hkMRDriver))
  1086. {
  1087. RegCloseKey(hkMRClass);
  1088. continue;
  1089. }
  1090. // Migrate the values from the driver into the MediaResources key
  1091. // First write out driver name
  1092. // FEATURE: Not implemented yet.
  1093. RegCloseKey(hkMRClass);
  1094. RegCloseKey(hkMRDriver);
  1095. }
  1096. // Close the Driver Name key
  1097. RegCloseKey(hkR3DriverName);
  1098. }
  1099. // Close the class key in the devnode
  1100. RegCloseKey(hkClass);
  1101. }
  1102. bRet = TRUE;
  1103. RemoveMediaResources_exit:
  1104. if (hkDevReg) RegCloseKey(hkDevReg);
  1105. if (hkDrivers) RegCloseKey(hkDrivers);
  1106. if (hkMR) RegCloseKey(hkMR);
  1107. return bRet;
  1108. }
  1109. #endif
  1110. #ifdef _WIN64
  1111. void mmWOW64ThunkMediaClassInstaller(DWORD dwInstallationFlag, HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData)
  1112. {
  1113. DWORD dwInstanceIDSize = 0;
  1114. DWORD dwWow64DirSize = 0;
  1115. LPTSTR tcstrDeviceInstanceId = NULL;
  1116. LPTSTR tcstrWow64Directory = NULL;
  1117. LPTSTR tcstrRunDLL32Path = NULL;
  1118. PROCESS_INFORMATION processInformation;
  1119. STARTUPINFO startupInfo;
  1120. // Get the device instance ID
  1121. SetupDiGetDeviceInstanceId( DeviceInfoSet, DeviceInfoData, NULL, 0, &dwInstanceIDSize );
  1122. if( 0 == dwInstanceIDSize )
  1123. {
  1124. // Unable to retrieve required size - return
  1125. return;
  1126. }
  1127. tcstrDeviceInstanceId = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR) * dwInstanceIDSize);
  1128. if( NULL == tcstrDeviceInstanceId
  1129. || 0 == SetupDiGetDeviceInstanceId( DeviceInfoSet, DeviceInfoData, tcstrDeviceInstanceId, dwInstanceIDSize, NULL ) )
  1130. {
  1131. // Unable to retrieve device instance ID - return
  1132. LocalFree((HANDLE)tcstrDeviceInstanceId);
  1133. return;
  1134. }
  1135. dwWow64DirSize = GetSystemWow64Directory( NULL, 0 );
  1136. if( 0 == dwWow64DirSize )
  1137. {
  1138. // Unable to retrieve the Wow64Directory size - return
  1139. LocalFree((HANDLE)tcstrDeviceInstanceId);
  1140. return;
  1141. }
  1142. tcstrWow64Directory = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR) * dwWow64DirSize);
  1143. if( NULL == tcstrWow64Directory
  1144. || 0 == GetSystemWow64Directory( tcstrWow64Directory, dwWow64DirSize ) )
  1145. {
  1146. // Unable to retrieve the Wow64Directory - return
  1147. LocalFree((HANDLE)tcstrWow64Directory);
  1148. LocalFree((HANDLE)tcstrDeviceInstanceId);
  1149. return;
  1150. }
  1151. // The full path is the size of the format string, plus two times the length of the system path,
  1152. // plus the length of the instance ID, plus 10 (maximum length of a DWORD)
  1153. tcstrRunDLL32Path = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR) * (wcslen(gszRunDLL32Path) +
  1154. dwWow64DirSize * 2 + dwInstanceIDSize + 10));
  1155. if( NULL == tcstrRunDLL32Path )
  1156. {
  1157. // Unable to allocate RunDLL32 path - return
  1158. LocalFree((HANDLE)tcstrWow64Directory);
  1159. LocalFree((HANDLE)tcstrDeviceInstanceId);
  1160. return;
  1161. }
  1162. // Create the command line
  1163. wsprintf( tcstrRunDLL32Path, gszRunDLL32Path, tcstrWow64Directory, tcstrWow64Directory, tcstrDeviceInstanceId, dwInstallationFlag );
  1164. // Initialize the CreateProcess structures
  1165. ZeroMemory( &processInformation, sizeof(PROCESS_INFORMATION) );
  1166. ZeroMemory( &startupInfo, sizeof(STARTUPINFO) );
  1167. startupInfo.cb = sizeof(STARTUPINFO);
  1168. if( CreateProcess( NULL, tcstrRunDLL32Path, NULL, NULL, FALSE,
  1169. CREATE_NO_WINDOW, NULL, NULL, &startupInfo, &processInformation ) )
  1170. {
  1171. // Wait for the process to end
  1172. WaitForSingleObject( processInformation.hProcess, 5000 );
  1173. // Close process and thread handles.
  1174. CloseHandle( processInformation.hProcess );
  1175. CloseHandle( processInformation.hThread );
  1176. }
  1177. // Free up the strings we allocated
  1178. LocalFree((HANDLE)tcstrRunDLL32Path);
  1179. LocalFree((HANDLE)tcstrWow64Directory);
  1180. LocalFree((HANDLE)tcstrDeviceInstanceId);
  1181. }
  1182. #endif //_WIN64