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.

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