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.

3496 lines
106 KiB

  1. /*++
  2. Copyright (c) 1993-2000 Microsoft Corporation
  3. Module Name:
  4. devreg.c
  5. Abstract:
  6. Device Installer routines for registry storage/retrieval.
  7. Author:
  8. Lonny McMichael (lonnym) 1-July-1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. //
  14. // Private function prototypes
  15. //
  16. DWORD
  17. pSetupOpenOrCreateDevRegKey(
  18. IN PDEVICE_INFO_SET DeviceInfoSet,
  19. IN PDEVINFO_ELEM DevInfoElem,
  20. IN DWORD Scope,
  21. IN DWORD HwProfile,
  22. IN DWORD KeyType,
  23. IN BOOL Create,
  24. IN REGSAM samDesired,
  25. OUT PHKEY hDevRegKey
  26. );
  27. BOOL
  28. pSetupFindUniqueKey(
  29. IN HKEY hkRoot,
  30. IN LPTSTR SubKey,
  31. IN ULONG SubKeyLength
  32. );
  33. DWORD
  34. pSetupOpenOrCreateInterfaceDeviceRegKey(
  35. IN HKEY hInterfaceClassKey,
  36. IN PDEVICE_INFO_SET DeviceInfoSet,
  37. IN PSP_DEVICE_INTERFACE_DATA InterfaceDeviceData,
  38. IN BOOL Create,
  39. IN REGSAM samDesired,
  40. OUT PHKEY hInterfaceDeviceKey
  41. );
  42. DWORD
  43. pSetupDeleteInterfaceDeviceKey(
  44. IN HKEY hInterfaceClassKey,
  45. IN PDEVICE_INFO_SET DeviceInfoSet,
  46. IN PSP_DEVICE_INTERFACE_DATA InterfaceDeviceData
  47. );
  48. HKEY
  49. WINAPI
  50. SetupDiOpenClassRegKey(
  51. IN CONST GUID *ClassGuid, OPTIONAL
  52. IN REGSAM samDesired
  53. )
  54. /*++
  55. Routine Description:
  56. This API opens the installer class registry key or a specific class
  57. installer's subkey.
  58. Arguments:
  59. ClassGuid - Optionally, supplies a pointer to the GUID of the class whose
  60. key is to be opened. If this parameter is NULL, then the root of the
  61. class tree will be opened.
  62. samDesired - Specifies the access you require for this key.
  63. Return Value:
  64. If the function succeeds, the return value is a handle to an opened registry
  65. key.
  66. If the function fails, the return value is INVALID_HANDLE_VALUE. To get
  67. extended error information, call GetLastError.
  68. Remarks:
  69. This API _will not_ create a registry key if it doesn't already exist.
  70. The handle returned from this API must be closed by calling RegCloseKey.
  71. To get at the interface class (DeviceClasses) branch, or to access the
  72. registry on a remote machine, use SetupDiOpenClassRegKeyEx.
  73. --*/
  74. {
  75. return SetupDiOpenClassRegKeyEx(ClassGuid, samDesired, DIOCR_INSTALLER, NULL, NULL);
  76. }
  77. #ifdef UNICODE
  78. //
  79. // ANSI version
  80. //
  81. HKEY
  82. WINAPI
  83. SetupDiOpenClassRegKeyExA(
  84. IN CONST GUID *ClassGuid, OPTIONAL
  85. IN REGSAM samDesired,
  86. IN DWORD Flags,
  87. IN PCSTR MachineName, OPTIONAL
  88. IN PVOID Reserved
  89. )
  90. {
  91. PCWSTR UnicodeMachineName;
  92. DWORD rc;
  93. HKEY hk;
  94. hk = INVALID_HANDLE_VALUE;
  95. if(MachineName) {
  96. rc = pSetupCaptureAndConvertAnsiArg(MachineName, &UnicodeMachineName);
  97. } else {
  98. UnicodeMachineName = NULL;
  99. rc = NO_ERROR;
  100. }
  101. if(rc == NO_ERROR) {
  102. hk = SetupDiOpenClassRegKeyExW(ClassGuid,
  103. samDesired,
  104. Flags,
  105. UnicodeMachineName,
  106. Reserved
  107. );
  108. rc = GetLastError();
  109. if(UnicodeMachineName) {
  110. MyFree(UnicodeMachineName);
  111. }
  112. }
  113. SetLastError(rc);
  114. return hk;
  115. }
  116. #else
  117. //
  118. // Unicode version
  119. //
  120. HKEY
  121. WINAPI
  122. SetupDiOpenClassRegKeyExW(
  123. IN CONST GUID *ClassGuid, OPTIONAL
  124. IN REGSAM samDesired,
  125. IN DWORD Flags,
  126. IN PCWSTR MachineName, OPTIONAL
  127. IN PVOID Reserved
  128. )
  129. {
  130. UNREFERENCED_PARAMETER(ClassGuid);
  131. UNREFERENCED_PARAMETER(samDesired);
  132. UNREFERENCED_PARAMETER(Flags);
  133. UNREFERENCED_PARAMETER(MachineName);
  134. UNREFERENCED_PARAMETER(Reserved);
  135. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  136. return(FALSE);
  137. }
  138. #endif
  139. HKEY
  140. WINAPI
  141. SetupDiOpenClassRegKeyEx(
  142. IN CONST GUID *ClassGuid, OPTIONAL
  143. IN REGSAM samDesired,
  144. IN DWORD Flags,
  145. IN PCTSTR MachineName, OPTIONAL
  146. IN PVOID Reserved
  147. )
  148. /*++
  149. Routine Description:
  150. This API opens the root of either the installer or the interface class registry
  151. branch, or a specified class subkey under one of these branches.
  152. If the root key is requested, it will be created if not already present (i.e.,
  153. you're always guaranteed to get a handle to the root unless a registry error
  154. occurs).
  155. If a particular class subkey is requested, it will be returned if present.
  156. Otherwise, this API will return ERROR_INVALID_CLASS.
  157. Arguments:
  158. ClassGuid - Optionally, supplies a pointer to the GUID of the class whose
  159. key is to be opened. If this parameter is NULL, then the root of the
  160. class tree will be opened. This GUID is either an installer class or
  161. an interface class depending on the Flags argument.
  162. samDesired - Specifies the access you require for this key.
  163. Flags - Specifies which registry branch the key is to be opened for. May
  164. be one of the following values:
  165. DIOCR_INSTALLER - Open the class installer (Class) branch.
  166. DIOCR_INTERFACE - Open the interface class (DeviceClasses) branch.
  167. MachineName - If specified, this value indicates the remote machine where
  168. the key is to be opened.
  169. Reserved - Reserved for future use--must be NULL.
  170. Return Value:
  171. If the function succeeds, the return value is a handle to an opened registry
  172. key.
  173. If the function fails, the return value is INVALID_HANDLE_VALUE. To get
  174. extended error information, call GetLastError.
  175. Remarks:
  176. The handle returned from this API must be closed by calling RegCloseKey.
  177. --*/
  178. {
  179. HKEY hk;
  180. CONFIGRET cr;
  181. DWORD Err = NO_ERROR;
  182. HMACHINE hMachine = NULL;
  183. //
  184. // Make sure the user didn't pass us anything in the Reserved parameter.
  185. //
  186. if(Reserved) {
  187. SetLastError(ERROR_INVALID_PARAMETER);
  188. return INVALID_HANDLE_VALUE;
  189. }
  190. //
  191. // Validate the flags (really, just an enum for now, but treated as
  192. // flags for future extensibility).
  193. //
  194. if((Flags & ~(DIOCR_INSTALLER | DIOCR_INTERFACE)) ||
  195. ((Flags != DIOCR_INSTALLER) && (Flags != DIOCR_INTERFACE))) {
  196. SetLastError(ERROR_INVALID_FLAGS);
  197. return INVALID_HANDLE_VALUE;
  198. }
  199. try {
  200. if(MachineName) {
  201. if(CR_SUCCESS != (cr = CM_Connect_Machine(MachineName, &hMachine))) {
  202. //
  203. // Make sure machine handle is still invalid, so we won't
  204. // try to disconnect later.
  205. //
  206. hMachine = NULL;
  207. Err = MapCrToSpError(cr, ERROR_INVALID_DATA);
  208. goto clean0;
  209. }
  210. }
  211. if((cr = CM_Open_Class_Key_Ex((LPGUID)ClassGuid,
  212. NULL,
  213. samDesired,
  214. ClassGuid ? RegDisposition_OpenExisting
  215. : RegDisposition_OpenAlways,
  216. &hk,
  217. (Flags & DIOCR_INSTALLER) ? CM_OPEN_CLASS_KEY_INSTALLER
  218. : CM_OPEN_CLASS_KEY_INTERFACE,
  219. hMachine)) != CR_SUCCESS)
  220. {
  221. if(cr == CR_NO_SUCH_REGISTRY_KEY) {
  222. Err = ERROR_INVALID_CLASS;
  223. } else {
  224. Err = MapCrToSpError(cr, ERROR_INVALID_DATA);
  225. }
  226. }
  227. clean0: ; // nothing to do.
  228. } except(EXCEPTION_EXECUTE_HANDLER) {
  229. Err = ERROR_INVALID_PARAMETER;
  230. //
  231. // Reference the following variable(s) so the compiler will respect our statement
  232. // ordering w.r.t. assignment.
  233. //
  234. hMachine = hMachine;
  235. }
  236. if(hMachine) {
  237. CM_Disconnect_Machine(hMachine);
  238. }
  239. SetLastError(Err);
  240. return (Err == NO_ERROR) ? hk : INVALID_HANDLE_VALUE;
  241. }
  242. #ifdef UNICODE
  243. //
  244. // ANSI version
  245. //
  246. HKEY
  247. WINAPI
  248. SetupDiCreateDevRegKeyA(
  249. IN HDEVINFO DeviceInfoSet,
  250. IN PSP_DEVINFO_DATA DeviceInfoData,
  251. IN DWORD Scope,
  252. IN DWORD HwProfile,
  253. IN DWORD KeyType,
  254. IN HINF InfHandle, OPTIONAL
  255. IN PCSTR InfSectionName OPTIONAL
  256. )
  257. {
  258. DWORD rc;
  259. PWSTR name;
  260. HKEY h;
  261. if(InfSectionName) {
  262. rc = pSetupCaptureAndConvertAnsiArg(InfSectionName,&name);
  263. if(rc != NO_ERROR) {
  264. SetLastError(rc);
  265. return(INVALID_HANDLE_VALUE);
  266. }
  267. } else {
  268. name = NULL;
  269. }
  270. h = SetupDiCreateDevRegKeyW(
  271. DeviceInfoSet,
  272. DeviceInfoData,
  273. Scope,
  274. HwProfile,
  275. KeyType,
  276. InfHandle,
  277. name
  278. );
  279. rc = GetLastError();
  280. if(name) {
  281. MyFree(name);
  282. }
  283. SetLastError(rc);
  284. return(h);
  285. }
  286. #else
  287. //
  288. // Unicode stub
  289. //
  290. HKEY
  291. WINAPI
  292. SetupDiCreateDevRegKeyW(
  293. IN HDEVINFO DeviceInfoSet,
  294. IN PSP_DEVINFO_DATA DeviceInfoData,
  295. IN DWORD Scope,
  296. IN DWORD HwProfile,
  297. IN DWORD KeyType,
  298. IN HINF InfHandle, OPTIONAL
  299. IN PCWSTR InfSectionName OPTIONAL
  300. )
  301. {
  302. UNREFERENCED_PARAMETER(DeviceInfoSet);
  303. UNREFERENCED_PARAMETER(DeviceInfoData);
  304. UNREFERENCED_PARAMETER(Scope);
  305. UNREFERENCED_PARAMETER(HwProfile);
  306. UNREFERENCED_PARAMETER(KeyType);
  307. UNREFERENCED_PARAMETER(InfHandle);
  308. UNREFERENCED_PARAMETER(InfSectionName);
  309. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  310. return(INVALID_HANDLE_VALUE);
  311. }
  312. #endif
  313. HKEY
  314. WINAPI
  315. SetupDiCreateDevRegKey(
  316. IN HDEVINFO DeviceInfoSet,
  317. IN PSP_DEVINFO_DATA DeviceInfoData,
  318. IN DWORD Scope,
  319. IN DWORD HwProfile,
  320. IN DWORD KeyType,
  321. IN HINF InfHandle, OPTIONAL
  322. IN PCTSTR InfSectionName OPTIONAL
  323. )
  324. /*++
  325. Routine Description:
  326. This routine creates a registry storage key for device-specific configuration
  327. information, and returns a handle to the key.
  328. Arguments:
  329. DeviceInfoSet - Supplies a handle to the device information set containing
  330. information about the device instance whose registry configuration storage
  331. key is to be created.
  332. DeviceInfoData - Supplies a pointer to a SP_DEVINFO_DATA structure indicating
  333. the device instance to create the registry key for.
  334. Scope - Specifies the scope of the registry key to be created. This determines
  335. where the information is actually stored--the key created may be one that is
  336. global (i.e., constant regardless of current hardware profile) or hardware
  337. profile-specific. May be one of the following values:
  338. DICS_FLAG_GLOBAL - Create a key to store global configuration information.
  339. DICS_FLAG_CONFIGSPECIFIC - Create a key to store hardware profile-specific
  340. information.
  341. HwProfile - Specifies the hardware profile to create a key for, if the Scope parameter
  342. is set to DICS_FLAG_CONFIGSPECIFIC. If this parameter is 0, then the key
  343. for the current hardware profile should be created (i.e., in the Class branch
  344. under HKEY_CURRENT_CONFIG). If Scope is DICS_FLAG_GLOBAL, then this parameter
  345. is ignored.
  346. KeyType - Specifies the type of registry storage key to be created. May be one of
  347. the following values:
  348. DIREG_DEV - Create a hardware registry key for the device. This is the key for
  349. storage of driver-independent configuration information. (This key is in
  350. the device instance key in the Enum branch.
  351. DIREG_DRV - Create a software, or driver, registry key for the device. (This key
  352. is located in the class branch.)
  353. InfHandle - Optionally, supplies the handle of an opened INF file containing an
  354. install section to be executed for the newly-created key. If this parameter is
  355. specified, then InfSectionName must be specified as well.
  356. InfSectionName - Optionally, supplies the name of an install section in the INF
  357. file specified by InfHandle. This section will be executed for the newly
  358. created key. If this parameter is specified, then InfHandle must be specified
  359. as well.
  360. Return Value:
  361. If the function succeeds, the return value is a handle to a newly-created
  362. registry key where private configuration data pertaining to this device
  363. instance may be stored/retrieved.
  364. If the function fails, the return value is INVALID_HANDLE_VALUE. To get
  365. extended error information, call GetLastError.
  366. Remarks:
  367. The handle returned from this routine must be closed by calling RegCloseKey.
  368. The specified device instance must have been previously registered (i.e.,
  369. if it was created via SetupDiCreateDeviceInfo, then SetupDiRegisterDeviceInfo
  370. must have been subsequently called.)
  371. During GUI-mode setup on Windows NT, quiet-install behavior is always
  372. employed in the absence of a user-supplied file queue, regardless of
  373. whether the device information element has the DI_QUIETINSTALL flag set.
  374. --*/
  375. {
  376. HKEY hk = INVALID_HANDLE_VALUE;
  377. PDEVICE_INFO_SET pDeviceInfoSet;
  378. DWORD Err;
  379. PDEVINFO_ELEM DevInfoElem;
  380. PSP_FILE_CALLBACK MsgHandler;
  381. PVOID MsgHandlerContext;
  382. BOOL MsgHandlerIsNativeCharWidth;
  383. BOOL NoProgressUI;
  384. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  385. SetLastError(ERROR_INVALID_HANDLE);
  386. return INVALID_HANDLE_VALUE;
  387. }
  388. Err = NO_ERROR;
  389. try {
  390. //
  391. // Get a pointer to the element for the specified device
  392. // instance.
  393. //
  394. if(!(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  395. DeviceInfoData,
  396. NULL))) {
  397. Err = ERROR_INVALID_PARAMETER;
  398. goto clean0;
  399. }
  400. //
  401. // Create the requested registry storage key.
  402. //
  403. if((Err = pSetupOpenOrCreateDevRegKey(pDeviceInfoSet,
  404. DevInfoElem,
  405. Scope,
  406. HwProfile,
  407. KeyType,
  408. TRUE,
  409. KEY_ALL_ACCESS,
  410. &hk)) != NO_ERROR) {
  411. goto clean0;
  412. }
  413. //
  414. // We successfully created the storage key, now run an INF install
  415. // section against it (if specified).
  416. //
  417. if(InfHandle && (InfHandle != INVALID_HANDLE_VALUE) && InfSectionName) {
  418. //
  419. // If a copy msg handler and context haven't been specified, then use
  420. // the default one.
  421. //
  422. if(DevInfoElem->InstallParamBlock.InstallMsgHandler) {
  423. MsgHandler = DevInfoElem->InstallParamBlock.InstallMsgHandler;
  424. MsgHandlerContext = DevInfoElem->InstallParamBlock.InstallMsgHandlerContext;
  425. MsgHandlerIsNativeCharWidth = DevInfoElem->InstallParamBlock.InstallMsgHandlerIsNativeCharWidth;
  426. } else {
  427. NoProgressUI = (GuiSetupInProgress || (DevInfoElem->InstallParamBlock.Flags & DI_QUIETINSTALL));
  428. if(!(MsgHandlerContext = SetupInitDefaultQueueCallbackEx(
  429. DevInfoElem->InstallParamBlock.hwndParent,
  430. (NoProgressUI ? INVALID_HANDLE_VALUE : NULL),
  431. 0,
  432. 0,
  433. NULL))) {
  434. Err = ERROR_NOT_ENOUGH_MEMORY;
  435. goto clean0;
  436. }
  437. MsgHandler = SetupDefaultQueueCallback;
  438. MsgHandlerIsNativeCharWidth = TRUE;
  439. }
  440. if(!_SetupInstallFromInfSection(DevInfoElem->InstallParamBlock.hwndParent,
  441. InfHandle,
  442. InfSectionName,
  443. SPINST_ALL,
  444. hk,
  445. NULL,
  446. 0,
  447. MsgHandler,
  448. MsgHandlerContext,
  449. ((KeyType == DIREG_DEV) ? DeviceInfoSet
  450. : INVALID_HANDLE_VALUE),
  451. ((KeyType == DIREG_DEV) ? DeviceInfoData
  452. : NULL),
  453. MsgHandlerIsNativeCharWidth,
  454. NULL
  455. )) {
  456. Err = GetLastError();
  457. }
  458. //
  459. // If we used the default msg handler, release the default context now.
  460. //
  461. if(!DevInfoElem->InstallParamBlock.InstallMsgHandler) {
  462. SetupTermDefaultQueueCallback(MsgHandlerContext);
  463. }
  464. }
  465. clean0:
  466. ; // Nothing to do.
  467. } except(EXCEPTION_EXECUTE_HANDLER) {
  468. Err = ERROR_INVALID_PARAMETER;
  469. }
  470. UnlockDeviceInfoSet(pDeviceInfoSet);
  471. if(Err == NO_ERROR) {
  472. return hk;
  473. } else {
  474. if(hk != INVALID_HANDLE_VALUE) {
  475. RegCloseKey(hk);
  476. }
  477. SetLastError(Err);
  478. return INVALID_HANDLE_VALUE;
  479. }
  480. }
  481. HKEY
  482. WINAPI
  483. SetupDiOpenDevRegKey(
  484. IN HDEVINFO DeviceInfoSet,
  485. IN PSP_DEVINFO_DATA DeviceInfoData,
  486. IN DWORD Scope,
  487. IN DWORD HwProfile,
  488. IN DWORD KeyType,
  489. IN REGSAM samDesired
  490. )
  491. /*++
  492. Routine Description:
  493. This routine opens a registry storage key for device-specific configuration
  494. information, and returns a handle to the key.
  495. Arguments:
  496. DeviceInfoSet - Supplies a handle to the device information set containing
  497. information about the device instance whose registry configuration storage
  498. key is to be opened.
  499. DeviceInfoData - Supplies a pointer to a SP_DEVINFO_DATA structure indicating
  500. the device instance to open the registry key for.
  501. Scope - Specifies the scope of the registry key to be opened. This determines
  502. where the information is actually stored--the key opened may be one that is
  503. global (i.e., constant regardless of current hardware profile) or hardware
  504. profile-specific. May be one of the following values:
  505. DICS_FLAG_GLOBAL - Open a key to store global configuration information.
  506. DICS_FLAG_CONFIGSPECIFIC - Open a key to store hardware profile-specific
  507. information.
  508. HwProfile - Specifies the hardware profile to open a key for, if the Scope parameter
  509. is set to DICS_FLAG_CONFIGSPECIFIC. If this parameter is 0, then the key
  510. for the current hardware profile should be opened (i.e., in the Class branch
  511. under HKEY_CURRENT_CONFIG). If Scope is SPDICS_FLAG_GLOBAL, then this parameter
  512. is ignored.
  513. KeyType - Specifies the type of registry storage key to be opened. May be one of
  514. the following values:
  515. DIREG_DEV - Open a hardware registry key for the device. This is the key for
  516. storage of driver-independent configuration information. (This key is in
  517. the device instance key in the Enum branch.
  518. DIREG_DRV - Open a software (i.e., driver) registry key for the device. (This key
  519. is located in the class branch.)
  520. samDesired - Specifies the access you require for this key.
  521. Return Value:
  522. If the function succeeds, the return value is a handle to an opened registry
  523. key where private configuration data pertaining to this device instance may be
  524. stored/retrieved.
  525. If the function fails, the return value is INVALID_HANDLE_VALUE. To get
  526. extended error information, call GetLastError.
  527. Remarks:
  528. The handle returned from this routine must be closed by calling RegCloseKey.
  529. The specified device instance must have been previously registered (i.e., if it
  530. was created via SetupDiCreateDeviceInfo, then SetupDiRegisterDeviceInfo must have
  531. been subsequently called.)
  532. --*/
  533. {
  534. HKEY hk;
  535. PDEVICE_INFO_SET pDeviceInfoSet;
  536. DWORD Err;
  537. PDEVINFO_ELEM DevInfoElem;
  538. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  539. SetLastError(ERROR_INVALID_HANDLE);
  540. return INVALID_HANDLE_VALUE;
  541. }
  542. Err = NO_ERROR;
  543. try {
  544. //
  545. // Get a pointer to the element for the specified device
  546. // instance.
  547. //
  548. if(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  549. DeviceInfoData,
  550. NULL)) {
  551. //
  552. // Open the requested registry storage key.
  553. //
  554. Err = pSetupOpenOrCreateDevRegKey(pDeviceInfoSet,
  555. DevInfoElem,
  556. Scope,
  557. HwProfile,
  558. KeyType,
  559. FALSE,
  560. samDesired,
  561. &hk
  562. );
  563. } else {
  564. Err = ERROR_INVALID_PARAMETER;
  565. }
  566. } except(EXCEPTION_EXECUTE_HANDLER) {
  567. Err = ERROR_INVALID_PARAMETER;
  568. }
  569. UnlockDeviceInfoSet(pDeviceInfoSet);
  570. SetLastError(Err);
  571. return (Err == NO_ERROR) ? hk : INVALID_HANDLE_VALUE;
  572. }
  573. DWORD
  574. pSetupOpenOrCreateDevRegKey(
  575. IN PDEVICE_INFO_SET pDeviceInfoSet,
  576. IN PDEVINFO_ELEM DevInfoElem,
  577. IN DWORD Scope,
  578. IN DWORD HwProfile,
  579. IN DWORD KeyType,
  580. IN BOOL Create,
  581. IN REGSAM samDesired,
  582. OUT PHKEY hDevRegKey
  583. )
  584. /*++
  585. Routine Description:
  586. This routine creates or opens a registry storage key for the specified
  587. device information element, and returns a handle to the opened key.
  588. Arguments:
  589. DeviceInfoSet - Supplies a pointer to the device information set containing
  590. the element for which a registry storage key is to be created/opened.
  591. DevInfoElem - Supplies a pointer to the device information element for
  592. which a registry storage key is to be created/opened.
  593. Scope - Specifies the scope of the registry key to be created/opened. This determines
  594. where the information is actually stored--the key created may be one that is
  595. global (i.e., constant regardless of current hardware profile) or hardware
  596. profile-specific. May be one of the following values:
  597. DICS_FLAG_GLOBAL - Create/open a key to store global configuration information.
  598. DICS_FLAG_CONFIGSPECIFIC - Create/open a key to store hardware profile-specific
  599. information.
  600. HwProfile - Specifies the hardware profile to create/open a key for, if the Scope parameter
  601. is set to DICS_FLAG_CONFIGSPECIFIC. If this parameter is 0, then the key
  602. for the current hardware profile should be created/opened (i.e., in the Class branch
  603. under HKEY_CURRENT_CONFIG). If Scope is SPDICS_FLAG_GLOBAL, then this parameter
  604. is ignored.
  605. KeyType - Specifies the type of registry storage key to be created/opened. May be one of
  606. the following values:
  607. DIREG_DEV - Create/open a hardware registry key for the device. This is the key for
  608. storage of driver-independent configuration information. (This key is in
  609. the device instance key in the Enum branch.
  610. DIREG_DRV - Create/open a software, or driver, registry key for the device. (This key
  611. is located in the class branch.)
  612. Create - Specifies whether the key should be created if doesn't already exist.
  613. samDesired - Specifies the access you require for this key.
  614. hDevRegKey - Supplies the address of a variable that receives a handle to the
  615. requested registry key. (This variable will only be written to if the
  616. handle is successfully opened.)
  617. Return Value:
  618. If the function is successful, the return value is NO_ERROR, otherwise, it is
  619. the ERROR_* code indicating the error that occurred.
  620. Remarks:
  621. If a software key is requested (DIREG_DRV), and there isn't already a 'Driver'
  622. value entry, then one will be created. This entry is of the form:
  623. <ClassGUID>\<instance>
  624. where <instance> is a base-10, 4-digit number that is unique within that class.
  625. --*/
  626. {
  627. ULONG RegistryBranch;
  628. CONFIGRET cr;
  629. DWORD Err, Disposition;
  630. HKEY hk, hkClass;
  631. TCHAR DriverKey[GUID_STRING_LEN + 5]; // Eg, {4d36e978-e325-11ce-bfc1-08002be10318}\0000
  632. ULONG DriverKeyLength;
  633. TCHAR EmptyString = TEXT('\0');
  634. //
  635. // Under Win95, the class key uses the class name instead of its GUID. The maximum
  636. // length of a class name is less than the length of a GUID string, but put a check
  637. // here just to make sure that this assumption remains valid.
  638. //
  639. #if MAX_CLASS_NAME_LEN > MAX_GUID_STRING_LEN
  640. #error MAX_CLASS_NAME_LEN is larger than MAX_GUID_STRING_LEN--fix DriverKey!
  641. #endif
  642. //
  643. // Figure out what flags to pass to CM_Open_DevInst_Key
  644. //
  645. switch(KeyType) {
  646. case DIREG_DEV :
  647. RegistryBranch = CM_REGISTRY_HARDWARE;
  648. break;
  649. case DIREG_DRV :
  650. //
  651. // This key may only be opened if the device instance has been registered.
  652. //
  653. if(!(DevInfoElem->DiElemFlags & DIE_IS_REGISTERED)) {
  654. return ERROR_DEVINFO_NOT_REGISTERED;
  655. }
  656. //
  657. // Retrieve the 'Driver' registry property which indicates where the
  658. // storage key is located in the class branch.
  659. //
  660. DriverKeyLength = sizeof(DriverKey);
  661. if((cr = CM_Get_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  662. CM_DRP_DRIVER,
  663. NULL,
  664. DriverKey,
  665. &DriverKeyLength,
  666. 0,
  667. pDeviceInfoSet->hMachine)) != CR_SUCCESS) {
  668. if(cr != CR_NO_SUCH_VALUE) {
  669. return (cr == CR_INVALID_DEVINST) ? ERROR_NO_SUCH_DEVINST
  670. : ERROR_INVALID_DATA;
  671. } else if(!Create) {
  672. return ERROR_KEY_DOES_NOT_EXIST;
  673. }
  674. //
  675. // The Driver entry doesn't exist, and we should create it.
  676. //
  677. hk = INVALID_HANDLE_VALUE;
  678. if(CM_Open_Class_Key_Ex(NULL,
  679. NULL,
  680. KEY_ALL_ACCESS,
  681. RegDisposition_OpenAlways,
  682. &hkClass,
  683. 0,
  684. pDeviceInfoSet->hMachine) != CR_SUCCESS) {
  685. //
  686. // This shouldn't fail.
  687. //
  688. return ERROR_INVALID_DATA;
  689. }
  690. try {
  691. //
  692. // Find a unique key name under this class key.
  693. //
  694. DriverKeyLength = SIZECHARS(DriverKey);
  695. if(CM_Get_Class_Key_Name_Ex(&(DevInfoElem->ClassGuid),
  696. DriverKey,
  697. &DriverKeyLength,
  698. 0,
  699. pDeviceInfoSet->hMachine) != CR_SUCCESS) {
  700. Err = ERROR_INVALID_CLASS;
  701. goto clean0;
  702. }
  703. DriverKeyLength--; // don't want to include terminating NULL.
  704. while(pSetupFindUniqueKey(hkClass, DriverKey, DriverKeyLength)) {
  705. if((Err = RegCreateKeyEx(hkClass,
  706. DriverKey,
  707. 0,
  708. &EmptyString,
  709. REG_OPTION_NON_VOLATILE,
  710. KEY_ALL_ACCESS,
  711. NULL,
  712. &hk,
  713. &Disposition)) == ERROR_SUCCESS) {
  714. //
  715. // Everything's great, unless the Disposition indicates
  716. // that the key already existed. That means that someone
  717. // else claimed the key before we got a chance to. In
  718. // that case, we close this key, and try again.
  719. //
  720. if(Disposition == REG_OPENED_EXISTING_KEY) {
  721. RegCloseKey(hk);
  722. hk = INVALID_HANDLE_VALUE;
  723. //
  724. // Truncate off the class instance part, to be replaced
  725. // with a new instance number the next go-around.
  726. //
  727. DriverKey[GUID_STRING_LEN - 1] = TEXT('\0');
  728. } else {
  729. break;
  730. }
  731. } else {
  732. hk = INVALID_HANDLE_VALUE;
  733. break;
  734. }
  735. }
  736. if(Err != NO_ERROR) { // NO_ERROR == ERROR_SUCCESS
  737. goto clean0;
  738. }
  739. //
  740. // Set the device instance's 'Driver' registry property to reflect the
  741. // new software registry storage location.
  742. //
  743. CM_Set_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  744. CM_DRP_DRIVER,
  745. DriverKey,
  746. sizeof(DriverKey),
  747. 0,
  748. pDeviceInfoSet->hMachine);
  749. clean0: ; // nothing to do
  750. } except(EXCEPTION_EXECUTE_HANDLER) {
  751. Err = ERROR_INVALID_PARAMETER;
  752. //
  753. // Access the hk variable so that the compiler will respect
  754. // the statement ordering in the try clause.
  755. //
  756. hk = hk;
  757. }
  758. if(hk != INVALID_HANDLE_VALUE) {
  759. RegCloseKey(hk);
  760. }
  761. RegCloseKey(hkClass);
  762. if(Err != NO_ERROR) {
  763. return Err;
  764. }
  765. }
  766. RegistryBranch = CM_REGISTRY_SOFTWARE;
  767. break;
  768. default :
  769. return ERROR_INVALID_FLAGS;
  770. }
  771. if(Scope == DICS_FLAG_CONFIGSPECIFIC) {
  772. RegistryBranch |= CM_REGISTRY_CONFIG;
  773. } else if(Scope != DICS_FLAG_GLOBAL) {
  774. return ERROR_INVALID_FLAGS;
  775. }
  776. cr = CM_Open_DevInst_Key_Ex(DevInfoElem->DevInst,
  777. samDesired,
  778. HwProfile,
  779. (Create ? RegDisposition_OpenAlways : RegDisposition_OpenExisting),
  780. &hk,
  781. RegistryBranch,
  782. pDeviceInfoSet->hMachine);
  783. if(cr == CR_SUCCESS) {
  784. *hDevRegKey = hk;
  785. Err = NO_ERROR;
  786. } else {
  787. switch(cr) {
  788. case CR_INVALID_DEVINST :
  789. Err = ERROR_NO_SUCH_DEVINST;
  790. break;
  791. case CR_NO_SUCH_REGISTRY_KEY :
  792. Err = ERROR_KEY_DOES_NOT_EXIST;
  793. break;
  794. default :
  795. Err = ERROR_INVALID_DATA;
  796. }
  797. }
  798. return Err;
  799. }
  800. BOOL
  801. WINAPI
  802. _SetupDiGetDeviceRegistryProperty(
  803. IN HDEVINFO DeviceInfoSet,
  804. IN PSP_DEVINFO_DATA DeviceInfoData,
  805. IN DWORD Property,
  806. OUT PDWORD PropertyRegDataType, OPTIONAL
  807. OUT PBYTE PropertyBuffer,
  808. IN DWORD PropertyBufferSize,
  809. OUT PDWORD RequiredSize OPTIONAL
  810. #ifdef UNICODE
  811. IN ,BOOL Ansi
  812. #endif
  813. )
  814. {
  815. PDEVICE_INFO_SET pDeviceInfoSet;
  816. DWORD Err;
  817. PDEVINFO_ELEM DevInfoElem;
  818. CONFIGRET cr;
  819. ULONG CmRegProperty, PropLength;
  820. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  821. SetLastError(ERROR_INVALID_HANDLE);
  822. return FALSE;
  823. }
  824. Err = NO_ERROR;
  825. try {
  826. //
  827. // Get a pointer to the element for the specified device
  828. // instance.
  829. //
  830. if(!(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  831. DeviceInfoData,
  832. NULL))) {
  833. Err = ERROR_INVALID_PARAMETER;
  834. goto clean0;
  835. }
  836. if(Property < SPDRP_MAXIMUM_PROPERTY) {
  837. CmRegProperty = (ULONG)SPDRP_TO_CMDRP(Property);
  838. } else {
  839. Err = ERROR_INVALID_REG_PROPERTY;
  840. goto clean0;
  841. }
  842. PropLength = PropertyBufferSize;
  843. #ifdef UNICODE
  844. if(Ansi) {
  845. cr = CM_Get_DevInst_Registry_Property_ExA(
  846. DevInfoElem->DevInst,
  847. CmRegProperty,
  848. PropertyRegDataType,
  849. PropertyBuffer,
  850. &PropLength,
  851. 0,
  852. pDeviceInfoSet->hMachine);
  853. } else
  854. #endif
  855. cr = CM_Get_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  856. CmRegProperty,
  857. PropertyRegDataType,
  858. PropertyBuffer,
  859. &PropLength,
  860. 0,
  861. pDeviceInfoSet->hMachine);
  862. if((cr == CR_SUCCESS) || (cr == CR_BUFFER_SMALL)) {
  863. if(RequiredSize) {
  864. *RequiredSize = PropLength;
  865. }
  866. }
  867. if(cr != CR_SUCCESS) {
  868. switch(cr) {
  869. case CR_INVALID_DEVINST :
  870. Err = ERROR_NO_SUCH_DEVINST;
  871. break;
  872. case CR_INVALID_PROPERTY :
  873. Err = ERROR_INVALID_REG_PROPERTY;
  874. break;
  875. case CR_BUFFER_SMALL :
  876. Err = ERROR_INSUFFICIENT_BUFFER;
  877. break;
  878. default :
  879. Err = ERROR_INVALID_DATA;
  880. }
  881. }
  882. clean0:
  883. ; // Nothing to do.
  884. } except(EXCEPTION_EXECUTE_HANDLER) {
  885. Err = ERROR_INVALID_PARAMETER;
  886. }
  887. UnlockDeviceInfoSet(pDeviceInfoSet);
  888. SetLastError(Err);
  889. return (Err == NO_ERROR);
  890. }
  891. #ifdef UNICODE
  892. //
  893. // ANSI version
  894. //
  895. BOOL
  896. WINAPI
  897. SetupDiGetDeviceRegistryPropertyA(
  898. IN HDEVINFO DeviceInfoSet,
  899. IN PSP_DEVINFO_DATA DeviceInfoData,
  900. IN DWORD Property,
  901. OUT PDWORD PropertyRegDataType, OPTIONAL
  902. OUT PBYTE PropertyBuffer,
  903. IN DWORD PropertyBufferSize,
  904. OUT PDWORD RequiredSize OPTIONAL
  905. )
  906. {
  907. BOOL b;
  908. b = _SetupDiGetDeviceRegistryProperty(
  909. DeviceInfoSet,
  910. DeviceInfoData,
  911. Property,
  912. PropertyRegDataType,
  913. PropertyBuffer,
  914. PropertyBufferSize,
  915. RequiredSize,
  916. TRUE
  917. );
  918. return(b);
  919. }
  920. #else
  921. //
  922. // Unicode stub
  923. //
  924. BOOL
  925. WINAPI
  926. SetupDiGetDeviceRegistryPropertyW(
  927. IN HDEVINFO DeviceInfoSet,
  928. IN PSP_DEVINFO_DATA DeviceInfoData,
  929. IN DWORD Property,
  930. OUT PDWORD PropertyRegDataType, OPTIONAL
  931. OUT PBYTE PropertyBuffer,
  932. IN DWORD PropertyBufferSize,
  933. OUT PDWORD RequiredSize OPTIONAL
  934. )
  935. {
  936. UNREFERENCED_PARAMETER(DeviceInfoSet);
  937. UNREFERENCED_PARAMETER(DeviceInfoData);
  938. UNREFERENCED_PARAMETER(Property);
  939. UNREFERENCED_PARAMETER(PropertyRegDataType);
  940. UNREFERENCED_PARAMETER(PropertyBuffer);
  941. UNREFERENCED_PARAMETER(PropertyBufferSize);
  942. UNREFERENCED_PARAMETER(RequiredSize);
  943. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  944. return(FALSE);
  945. }
  946. #endif
  947. BOOL
  948. WINAPI
  949. SetupDiGetDeviceRegistryProperty(
  950. IN HDEVINFO DeviceInfoSet,
  951. IN PSP_DEVINFO_DATA DeviceInfoData,
  952. IN DWORD Property,
  953. OUT PDWORD PropertyRegDataType, OPTIONAL
  954. OUT PBYTE PropertyBuffer,
  955. IN DWORD PropertyBufferSize,
  956. OUT PDWORD RequiredSize OPTIONAL
  957. )
  958. /*++
  959. Routine Description:
  960. This routine retrieves the specified property from the Plug & Play device
  961. storage location in the registry.
  962. Arguments:
  963. DeviceInfoSet - Supplies a handle to the device information set containing
  964. information about the device instance to retrieve a Plug & Play registry
  965. property for.
  966. DeviceInfoData - Supplies a pointer to a SP_DEVINFO_DATA structure indicating
  967. the device instance to retrieve the Plug & Play registry property for.
  968. Property - Supplies an ordinal specifying the property to be retrieved. Refer
  969. to sdk\inc\setupapi.h for a complete list of properties that may be retrieved.
  970. PropertyRegDataType - Optionally, supplies the address of a variable that
  971. will receive the data type of the property being retrieved. This will
  972. be one of the standard registry data types (REG_SZ, REG_BINARY, etc.)
  973. PropertyBuffer - Supplies the address of a buffer that receives the property
  974. data.
  975. PropertyBufferSize - Supplies the length, in bytes, of PropertyBuffer.
  976. RequiredSize - Optionally, supplies the address of a variable that receives
  977. the number of bytes required to store the requested property in the buffer.
  978. Return Value:
  979. If the function succeeds, the return value is TRUE.
  980. If the function fails, the return value is FALSE. To get extended error
  981. information, call GetLastError. If the supplied buffer was not large enough
  982. to hold the requested property, the error will be ERROR_INSUFFICIENT_BUFFER,
  983. and RequiredSize will specify how large the buffer needs to be.
  984. --*/
  985. {
  986. BOOL b;
  987. b = _SetupDiGetDeviceRegistryProperty(
  988. DeviceInfoSet,
  989. DeviceInfoData,
  990. Property,
  991. PropertyRegDataType,
  992. PropertyBuffer,
  993. PropertyBufferSize,
  994. RequiredSize
  995. #ifdef UNICODE
  996. ,FALSE
  997. #endif
  998. );
  999. return(b);
  1000. }
  1001. BOOL
  1002. WINAPI
  1003. _SetupDiSetDeviceRegistryProperty(
  1004. IN HDEVINFO DeviceInfoSet,
  1005. IN OUT PSP_DEVINFO_DATA DeviceInfoData,
  1006. IN DWORD Property,
  1007. IN CONST BYTE* PropertyBuffer, OPTIONAL
  1008. IN DWORD PropertyBufferSize
  1009. #ifdef UNICODE
  1010. IN ,BOOL Ansi
  1011. #endif
  1012. )
  1013. {
  1014. PDEVICE_INFO_SET pDeviceInfoSet;
  1015. DWORD Err;
  1016. PDEVINFO_ELEM DevInfoElem;
  1017. CONFIGRET cr;
  1018. ULONG CmRegProperty;
  1019. GUID ClassGuid;
  1020. BOOL ClassGuidSpecified;
  1021. TCHAR ClassName[MAX_CLASS_NAME_LEN];
  1022. DWORD ClassNameLength;
  1023. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  1024. SetLastError(ERROR_INVALID_HANDLE);
  1025. return FALSE;
  1026. }
  1027. Err = NO_ERROR;
  1028. try {
  1029. //
  1030. // Get a pointer to the element for the specified device
  1031. // instance.
  1032. //
  1033. if(!(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  1034. DeviceInfoData,
  1035. NULL))) {
  1036. Err = ERROR_INVALID_PARAMETER;
  1037. goto clean0;
  1038. }
  1039. //
  1040. // Make sure the property code is in-range, and is not SPDRP_CLASS
  1041. // (the Class property is not settable directly, and is automatically
  1042. // updated when the ClassGUID property changes).
  1043. //
  1044. if((Property < SPDRP_MAXIMUM_PROPERTY) && (Property != SPDRP_CLASS)) {
  1045. CmRegProperty = (ULONG)SPDRP_TO_CMDRP(Property);
  1046. } else {
  1047. Err = ERROR_INVALID_REG_PROPERTY;
  1048. goto clean0;
  1049. }
  1050. //
  1051. // If the property we're setting is ClassGUID, then we need to check to
  1052. // see whether the new GUID is different from the current one. If there's
  1053. // no change, then we're done.
  1054. //
  1055. if(CmRegProperty == CM_DRP_CLASSGUID) {
  1056. if(!PropertyBuffer) {
  1057. //
  1058. // Then the intent is to reset the device's class GUID. Make
  1059. // sure they passed us a buffer length of zero.
  1060. //
  1061. if(PropertyBufferSize) {
  1062. Err = ERROR_INVALID_PARAMETER;
  1063. goto clean0;
  1064. }
  1065. ClassGuidSpecified = FALSE;
  1066. } else {
  1067. #ifdef UNICODE
  1068. //
  1069. // If we're being called from the ANSI API then we need
  1070. // to convert the ANSI string representation of the GUID
  1071. // to Unicode before we convert the string to an actual GUID.
  1072. //
  1073. PCWSTR UnicodeGuidString;
  1074. if(Ansi) {
  1075. UnicodeGuidString = pSetupAnsiToUnicode((PCSTR)PropertyBuffer);
  1076. if(!UnicodeGuidString) {
  1077. Err = ERROR_NOT_ENOUGH_MEMORY;
  1078. goto clean0;
  1079. }
  1080. } else {
  1081. UnicodeGuidString = (PCWSTR)PropertyBuffer;
  1082. }
  1083. Err = pSetupGuidFromString(UnicodeGuidString,&ClassGuid);
  1084. if(UnicodeGuidString != (PCWSTR)PropertyBuffer) {
  1085. MyFree(UnicodeGuidString);
  1086. }
  1087. if(Err != NO_ERROR) {
  1088. goto clean0;
  1089. }
  1090. #else
  1091. if((Err = pSetupGuidFromString((PCTSTR)PropertyBuffer, &ClassGuid)) != NO_ERROR) {
  1092. goto clean0;
  1093. }
  1094. #endif
  1095. ClassGuidSpecified = TRUE;
  1096. }
  1097. if(IsEqualGUID(&(DevInfoElem->ClassGuid),
  1098. (ClassGuidSpecified ? &ClassGuid
  1099. : &GUID_NULL))) {
  1100. //
  1101. // No change--nothing to do.
  1102. //
  1103. goto clean0;
  1104. }
  1105. //
  1106. // We're changing the class of this device. First, make sure that the
  1107. // set containing this device doesn't have an associated class (otherwise,
  1108. // we'll suddenly have a device whose class doesn't match the set's class).
  1109. //
  1110. if(pDeviceInfoSet->HasClassGuid) {
  1111. Err = ERROR_CLASS_MISMATCH;
  1112. } else {
  1113. Err = InvalidateHelperModules(DeviceInfoSet, DeviceInfoData, 0);
  1114. }
  1115. if(Err != NO_ERROR) {
  1116. goto clean0;
  1117. }
  1118. //
  1119. // Everything seems to be in order. Before going any further, we need to
  1120. // delete any software keys associated with this device, so we don't leave
  1121. // orphans in the registry when we change the device's class.
  1122. //
  1123. pSetupDeleteDevRegKeys(DevInfoElem->DevInst,
  1124. DICS_FLAG_GLOBAL | DICS_FLAG_CONFIGSPECIFIC,
  1125. (DWORD)-1,
  1126. DIREG_DRV,
  1127. TRUE
  1128. );
  1129. //
  1130. // Now delete the Driver property for this device...
  1131. //
  1132. CM_Set_DevInst_Registry_Property(DevInfoElem->DevInst,
  1133. CM_DRP_DRIVER,
  1134. NULL,
  1135. 0,
  1136. 0
  1137. );
  1138. }
  1139. #ifdef UNICODE
  1140. if(Ansi) {
  1141. cr = CM_Set_DevInst_Registry_PropertyA(
  1142. DevInfoElem->DevInst,
  1143. CmRegProperty,
  1144. (PVOID)PropertyBuffer,
  1145. PropertyBufferSize,
  1146. 0
  1147. );
  1148. } else
  1149. #endif
  1150. cr = CM_Set_DevInst_Registry_Property(DevInfoElem->DevInst,
  1151. CmRegProperty,
  1152. (PVOID)PropertyBuffer,
  1153. PropertyBufferSize,
  1154. 0
  1155. );
  1156. if(cr == CR_SUCCESS) {
  1157. //
  1158. // If we were setting the device's ClassGUID property, then we need to
  1159. // update its Class name property as well.
  1160. //
  1161. if(CmRegProperty == CM_DRP_CLASSGUID) {
  1162. if(ClassGuidSpecified) {
  1163. if(!SetupDiClassNameFromGuid(&ClassGuid,
  1164. ClassName,
  1165. SIZECHARS(ClassName),
  1166. &ClassNameLength)) {
  1167. //
  1168. // We couldn't retrieve the corresponding class name.
  1169. // Set ClassNameLength to zero so that we reset class
  1170. // name below.
  1171. //
  1172. ClassNameLength = 0;
  1173. }
  1174. } else {
  1175. //
  1176. // Resetting ClassGUID--we want to reset class name also.
  1177. //
  1178. ClassNameLength = 0;
  1179. }
  1180. CM_Set_DevInst_Registry_Property(DevInfoElem->DevInst,
  1181. CM_DRP_CLASS,
  1182. ClassNameLength ? (PVOID)ClassName : NULL,
  1183. ClassNameLength * sizeof(TCHAR),
  1184. 0
  1185. );
  1186. //
  1187. // Finally, update the device's class GUID, and also update the
  1188. // caller-supplied SP_DEVINFO_DATA structure to reflect the device's
  1189. // new class.
  1190. //
  1191. CopyMemory(&(DevInfoElem->ClassGuid),
  1192. (ClassGuidSpecified ? &ClassGuid : &GUID_NULL),
  1193. sizeof(GUID)
  1194. );
  1195. CopyMemory(&(DeviceInfoData->ClassGuid),
  1196. (ClassGuidSpecified ? &ClassGuid : &GUID_NULL),
  1197. sizeof(GUID)
  1198. );
  1199. }
  1200. } else {
  1201. switch(cr) {
  1202. case CR_INVALID_DEVINST :
  1203. Err = ERROR_NO_SUCH_DEVINST;
  1204. break;
  1205. case CR_INVALID_PROPERTY :
  1206. Err = ERROR_INVALID_REG_PROPERTY;
  1207. break;
  1208. case CR_INVALID_DATA :
  1209. Err = ERROR_INVALID_PARAMETER;
  1210. break;
  1211. default :
  1212. Err = ERROR_INVALID_DATA;
  1213. }
  1214. }
  1215. clean0:
  1216. ; // Nothing to do.
  1217. } except(EXCEPTION_EXECUTE_HANDLER) {
  1218. Err = ERROR_INVALID_PARAMETER;
  1219. }
  1220. UnlockDeviceInfoSet(pDeviceInfoSet);
  1221. SetLastError(Err);
  1222. return (Err == NO_ERROR);
  1223. }
  1224. #ifdef UNICODE
  1225. //
  1226. // ANSI version
  1227. //
  1228. BOOL
  1229. WINAPI
  1230. SetupDiSetDeviceRegistryPropertyA(
  1231. IN HDEVINFO DeviceInfoSet,
  1232. IN OUT PSP_DEVINFO_DATA DeviceInfoData,
  1233. IN DWORD Property,
  1234. IN CONST BYTE* PropertyBuffer, OPTIONAL
  1235. IN DWORD PropertyBufferSize
  1236. )
  1237. {
  1238. BOOL b;
  1239. b = _SetupDiSetDeviceRegistryProperty(
  1240. DeviceInfoSet,
  1241. DeviceInfoData,
  1242. Property,
  1243. PropertyBuffer,
  1244. PropertyBufferSize,
  1245. TRUE
  1246. );
  1247. return(b);
  1248. }
  1249. #else
  1250. //
  1251. // Unicode stub
  1252. //
  1253. BOOL
  1254. WINAPI
  1255. SetupDiSetDeviceRegistryPropertyW(
  1256. IN HDEVINFO DeviceInfoSet,
  1257. IN OUT PSP_DEVINFO_DATA DeviceInfoData,
  1258. IN DWORD Property,
  1259. IN CONST BYTE* PropertyBuffer, OPTIONAL
  1260. IN DWORD PropertyBufferSize
  1261. )
  1262. {
  1263. UNREFERENCED_PARAMETER(DeviceInfoSet);
  1264. UNREFERENCED_PARAMETER(DeviceInfoData);
  1265. UNREFERENCED_PARAMETER(Property);
  1266. UNREFERENCED_PARAMETER(PropertyBuffer);
  1267. UNREFERENCED_PARAMETER(PropertyBufferSize);
  1268. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  1269. return(FALSE);
  1270. }
  1271. #endif
  1272. BOOL
  1273. WINAPI
  1274. SetupDiSetDeviceRegistryProperty(
  1275. IN HDEVINFO DeviceInfoSet,
  1276. IN OUT PSP_DEVINFO_DATA DeviceInfoData,
  1277. IN DWORD Property,
  1278. IN CONST BYTE* PropertyBuffer, OPTIONAL
  1279. IN DWORD PropertyBufferSize
  1280. )
  1281. /*++
  1282. Routine Description:
  1283. This routine sets the specified Plug & Play device registry property.
  1284. Arguments:
  1285. DeviceInfoSet - Supplies a handle to the device information set containing
  1286. information about the device instance to set a Plug & Play registry
  1287. property for.
  1288. DeviceInfoData - Supplies a pointer to a SP_DEVINFO_DATA structure indicating
  1289. the device instance to set the Plug & Play registry property for. If the
  1290. ClassGUID property is being set, then this structure will be updated upon
  1291. return to reflect the device's new class.
  1292. Property - Supplies an ordinal specifying the property to be set. Refer to
  1293. sdk\inc\setupapi.h for a complete listing of values that may be set
  1294. (these values are denoted with 'R/W' in their descriptive comment).
  1295. PropertyBuffer - Supplies the address of a buffer containing the new data
  1296. for the property. If the property is being cleared, then this pointer
  1297. should be NULL, and PropertyBufferSize must be zero.
  1298. PropertyBufferSize - Supplies the length, in bytes, of PropertyBuffer. If
  1299. PropertyBuffer isn't specified (i.e., the property is to be cleared),
  1300. then this value must be zero.
  1301. Return Value:
  1302. If the function succeeds, the return value is TRUE.
  1303. If the function fails, the return value is FALSE. To get extended error
  1304. information, call GetLastError.
  1305. Remarks:
  1306. Note that the Class property cannot be set. This is because it is based on
  1307. the corresponding ClassGUID, and is automatically updated when that property
  1308. changes.
  1309. Also, note that when the ClassGUID property changes, this routine automatically
  1310. cleans up any software keys associated with the device. Otherwise, we would
  1311. be left with orphaned registry keys.
  1312. --*/
  1313. {
  1314. BOOL b;
  1315. b = _SetupDiSetDeviceRegistryProperty(
  1316. DeviceInfoSet,
  1317. DeviceInfoData,
  1318. Property,
  1319. PropertyBuffer,
  1320. PropertyBufferSize
  1321. #ifdef UNICODE
  1322. ,FALSE
  1323. #endif
  1324. );
  1325. return(b);
  1326. }
  1327. DWORD
  1328. _SetupDiGetClassRegistryProperty(
  1329. IN CONST GUID *ClassGuid,
  1330. IN DWORD Property,
  1331. OUT PDWORD PropertyRegDataType, OPTIONAL
  1332. OUT PBYTE PropertyBuffer,
  1333. IN DWORD PropertyBufferSize,
  1334. OUT PDWORD RequiredSize, OPTIONAL
  1335. IN PCTSTR MachineName, OPTIONAL
  1336. IN BOOL Ansi
  1337. )
  1338. /*++
  1339. See SetupDiGetClassRegistryProperty
  1340. --*/
  1341. {
  1342. DWORD Err;
  1343. CONFIGRET cr;
  1344. ULONG CmRegProperty, PropLength;
  1345. HMACHINE hMachine = NULL;
  1346. Err = NO_ERROR;
  1347. #ifndef UNICODE
  1348. UNREFERENCED_PARAMETER(Ansi);
  1349. #endif
  1350. try {
  1351. //
  1352. // if we want to set register for another machine, find that machine
  1353. //
  1354. if(MachineName) {
  1355. if(CR_SUCCESS != (cr = CM_Connect_Machine(MachineName, &hMachine))) {
  1356. //
  1357. // Make sure machine handle is still invalid, so we won't
  1358. // try to disconnect later.
  1359. //
  1360. hMachine = NULL;
  1361. Err = MapCrToSpError(cr, ERROR_INVALID_DATA);
  1362. leave;
  1363. }
  1364. }
  1365. if(Property < SPCRP_MAXIMUM_PROPERTY) {
  1366. CmRegProperty = (ULONG)SPCRP_TO_CMCRP(Property);
  1367. } else {
  1368. Err = ERROR_INVALID_REG_PROPERTY;
  1369. leave;
  1370. }
  1371. PropLength = PropertyBufferSize;
  1372. #ifdef UNICODE
  1373. if(Ansi) {
  1374. cr = CM_Get_Class_Registry_PropertyA(
  1375. (LPGUID)ClassGuid,
  1376. CmRegProperty,
  1377. PropertyRegDataType,
  1378. PropertyBuffer,
  1379. &PropLength,
  1380. 0,
  1381. hMachine);
  1382. } else {
  1383. cr = CM_Get_Class_Registry_PropertyW(
  1384. (LPGUID)ClassGuid,
  1385. CmRegProperty,
  1386. PropertyRegDataType,
  1387. PropertyBuffer,
  1388. &PropLength,
  1389. 0,
  1390. hMachine);
  1391. }
  1392. #else
  1393. //
  1394. // on ANSI version
  1395. //
  1396. cr = CM_Get_Class_Registry_Property(
  1397. (LPGUID)ClassGuid,
  1398. CmRegProperty,
  1399. PropertyRegDataType,
  1400. PropertyBuffer,
  1401. &PropLength,
  1402. 0,
  1403. hMachine);
  1404. #endif
  1405. if((cr == CR_SUCCESS) || (cr == CR_BUFFER_SMALL)) {
  1406. if(RequiredSize) {
  1407. *RequiredSize = PropLength;
  1408. }
  1409. }
  1410. if(cr != CR_SUCCESS) {
  1411. switch(cr) {
  1412. case CR_INVALID_DEVINST :
  1413. Err = ERROR_NO_SUCH_DEVINST;
  1414. break;
  1415. case CR_INVALID_PROPERTY :
  1416. Err = ERROR_INVALID_REG_PROPERTY;
  1417. break;
  1418. case CR_BUFFER_SMALL :
  1419. Err = ERROR_INSUFFICIENT_BUFFER;
  1420. break;
  1421. default :
  1422. Err = MapCrToSpError(cr, ERROR_INVALID_DATA);
  1423. }
  1424. }
  1425. } except(EXCEPTION_EXECUTE_HANDLER) {
  1426. Err = ERROR_INVALID_PARAMETER;
  1427. }
  1428. if (hMachine != NULL) {
  1429. CM_Disconnect_Machine(hMachine);
  1430. }
  1431. return Err;
  1432. }
  1433. #ifdef UNICODE
  1434. //
  1435. // ANSI version
  1436. //
  1437. WINSETUPAPI
  1438. BOOL
  1439. WINAPI
  1440. SetupDiGetClassRegistryPropertyA(
  1441. IN CONST GUID *ClassGuid,
  1442. IN DWORD Property,
  1443. OUT PDWORD PropertyRegDataType, OPTIONAL
  1444. OUT PBYTE PropertyBuffer,
  1445. IN DWORD PropertyBufferSize,
  1446. OUT PDWORD RequiredSize, OPTIONAL
  1447. IN PCSTR MachineName, OPTIONAL
  1448. IN PVOID Reserved
  1449. )
  1450. /*++
  1451. See SetupDiGetClassRegistryProperty
  1452. --*/
  1453. {
  1454. PCWSTR MachineString = NULL;
  1455. DWORD Err = NO_ERROR;
  1456. if (Reserved != NULL) {
  1457. //
  1458. // make sure caller doesn't pass a value here
  1459. // so we know we can use this at a later date
  1460. SetLastError(ERROR_INVALID_PARAMETER);
  1461. return FALSE;
  1462. }
  1463. try {
  1464. //
  1465. // convert machine-name to local
  1466. //
  1467. if (MachineName != NULL) {
  1468. MachineString = pSetupAnsiToUnicode(MachineName);
  1469. if(!MachineString) {
  1470. Err = ERROR_NOT_ENOUGH_MEMORY;
  1471. leave;
  1472. }
  1473. }
  1474. Err = _SetupDiGetClassRegistryProperty(ClassGuid,
  1475. Property,
  1476. PropertyRegDataType,
  1477. PropertyBuffer,
  1478. PropertyBufferSize,
  1479. RequiredSize,
  1480. MachineString,
  1481. TRUE);
  1482. } except(EXCEPTION_EXECUTE_HANDLER) {
  1483. Err = NO_ERROR;
  1484. }
  1485. if (MachineString != NULL) {
  1486. MyFree(MachineString);
  1487. }
  1488. SetLastError(Err);
  1489. return (BOOL)(Err == NO_ERROR);
  1490. }
  1491. #else
  1492. //
  1493. // UNICODE stub
  1494. //
  1495. WINSETUPAPI
  1496. BOOL
  1497. WINAPI
  1498. SetupDiGetClassRegistryPropertyW(
  1499. IN CONST GUID *ClassGuid,
  1500. IN DWORD Property,
  1501. OUT PDWORD PropertyRegDataType, OPTIONAL
  1502. OUT PBYTE PropertyBuffer,
  1503. IN DWORD PropertyBufferSize,
  1504. OUT PDWORD RequiredSize, OPTIONAL
  1505. IN PCWSTR MachineName, OPTIONAL
  1506. IN PVOID Reserved
  1507. )
  1508. /*++
  1509. See SetupDiGetClassRegistryProperty
  1510. --*/
  1511. {
  1512. UNREFERENCED_PARAMETER(ClassGuid);
  1513. UNREFERENCED_PARAMETER(Property);
  1514. UNREFERENCED_PARAMETER(PropertyRegDataType);
  1515. UNREFERENCED_PARAMETER(PropertyBuffer);
  1516. UNREFERENCED_PARAMETER(PropertyBufferSize);
  1517. UNREFERENCED_PARAMETER(RequiredSize);
  1518. UNREFERENCED_PARAMETER(MachineName);
  1519. UNREFERENCED_PARAMETER(Reserved);
  1520. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  1521. return(FALSE);
  1522. }
  1523. #endif // UNICODE
  1524. WINSETUPAPI
  1525. BOOL
  1526. WINAPI
  1527. SetupDiGetClassRegistryProperty(
  1528. IN CONST GUID *ClassGuid,
  1529. IN DWORD Property,
  1530. OUT PDWORD PropertyRegDataType, OPTIONAL
  1531. OUT PBYTE PropertyBuffer,
  1532. IN DWORD PropertyBufferSize,
  1533. OUT PDWORD RequiredSize, OPTIONAL
  1534. IN PCTSTR MachineName, OPTIONAL
  1535. IN PVOID Reserved
  1536. )
  1537. /*++
  1538. Routine Description:
  1539. This routine gets the specified Plug & Play device class registry property.
  1540. This is just a wrapper around the Config Mgr API
  1541. Typically the properties here can be overridden on a per-device basis,
  1542. however this routine returns the class properties only.
  1543. Arguments:
  1544. ClassGuid - Supplies the class Guid that the property is to be got from
  1545. Property - Supplies an ordinal specifying the property to be set. Refer to
  1546. sdk\inc\setupapi.h for a complete listing of values that may be set
  1547. (these values are denoted with 'R/W' in their descriptive comment).
  1548. PropertyBuffer - Supplies the address of a buffer containing the new data
  1549. for the property. If the property is being cleared, then this pointer
  1550. should be NULL, and PropertyBufferSize must be zero.
  1551. PropertyBufferSize - Supplies the length, in bytes, of PropertyBuffer. If
  1552. PropertyBuffer isn't specified (i.e., the property is to be cleared),
  1553. then this value must be zero.
  1554. MachineName - Allows properties to be set on a remote machine (if Non-NULL)
  1555. Reserved - should be nULL
  1556. Return Value:
  1557. If the function succeeds, the return value is TRUE.
  1558. If the function fails, the return value is FALSE. To get extended error
  1559. information, call GetLastError.
  1560. --*/
  1561. {
  1562. DWORD Err = NO_ERROR;
  1563. if (Reserved != NULL) {
  1564. //
  1565. // make sure caller doesn't pass a value here
  1566. // so we know we can use this at a later date
  1567. SetLastError(ERROR_INVALID_PARAMETER);
  1568. return FALSE;
  1569. }
  1570. Err = _SetupDiGetClassRegistryProperty(ClassGuid,
  1571. Property,
  1572. PropertyRegDataType,
  1573. PropertyBuffer,
  1574. PropertyBufferSize,
  1575. RequiredSize,
  1576. MachineName,
  1577. FALSE);
  1578. SetLastError(Err);
  1579. return (BOOL)(Err == NO_ERROR);
  1580. }
  1581. DWORD
  1582. _SetupDiSetClassRegistryProperty(
  1583. IN CONST GUID *ClassGuid,
  1584. IN DWORD Property,
  1585. IN CONST BYTE* PropertyBuffer, OPTIONAL
  1586. IN DWORD PropertyBufferSize,
  1587. IN PCTSTR MachineName, OPTIONAL
  1588. IN BOOL Ansi
  1589. )
  1590. /*++
  1591. See SetupDiGetClassRegistryProperty
  1592. --*/
  1593. {
  1594. DWORD Err;
  1595. CONFIGRET cr;
  1596. ULONG CmRegProperty, PropLength;
  1597. HMACHINE hMachine = NULL;
  1598. Err = NO_ERROR;
  1599. try {
  1600. //
  1601. // if we want to set register for another machine, find that machine
  1602. //
  1603. if(MachineName) {
  1604. if(CR_SUCCESS != (cr = CM_Connect_Machine(MachineName, &hMachine))) {
  1605. //
  1606. // Make sure machine handle is still invalid, so we won't
  1607. // try to disconnect later.
  1608. //
  1609. hMachine = NULL;
  1610. Err = MapCrToSpError(cr, ERROR_INVALID_DATA);
  1611. leave;
  1612. }
  1613. }
  1614. if(Property < SPCRP_MAXIMUM_PROPERTY) {
  1615. CmRegProperty = (ULONG)SPCRP_TO_CMCRP(Property);
  1616. } else {
  1617. Err = ERROR_INVALID_REG_PROPERTY;
  1618. leave;
  1619. }
  1620. PropLength = PropertyBufferSize;
  1621. #ifdef UNICODE
  1622. if(Ansi) {
  1623. cr = CM_Set_Class_Registry_PropertyA(
  1624. (LPGUID)ClassGuid,
  1625. CmRegProperty,
  1626. PropertyBuffer,
  1627. PropLength,
  1628. 0,
  1629. hMachine);
  1630. } else {
  1631. cr = CM_Set_Class_Registry_PropertyW(
  1632. (LPGUID)ClassGuid,
  1633. CmRegProperty,
  1634. PropertyBuffer,
  1635. PropLength,
  1636. 0,
  1637. hMachine);
  1638. }
  1639. #else
  1640. //
  1641. // on ANSI version
  1642. //
  1643. cr = CM_Set_Class_Registry_Property(
  1644. (LPGUID)ClassGuid,
  1645. CmRegProperty,
  1646. PropertyBuffer,
  1647. PropLength,
  1648. 0,
  1649. hMachine);
  1650. #endif
  1651. if(cr != CR_SUCCESS) {
  1652. switch(cr) {
  1653. case CR_INVALID_PROPERTY :
  1654. Err = ERROR_INVALID_REG_PROPERTY;
  1655. break;
  1656. default :
  1657. Err = MapCrToSpError(cr, ERROR_INVALID_DATA);
  1658. }
  1659. }
  1660. } except(EXCEPTION_EXECUTE_HANDLER) {
  1661. Err = ERROR_INVALID_PARAMETER;
  1662. }
  1663. if (hMachine != NULL) {
  1664. CM_Disconnect_Machine(hMachine);
  1665. }
  1666. return Err;
  1667. }
  1668. #ifdef UNICODE
  1669. //
  1670. // ANSI version
  1671. //
  1672. WINSETUPAPI
  1673. BOOL
  1674. WINAPI
  1675. SetupDiSetClassRegistryPropertyA(
  1676. IN CONST GUID *ClassGuid,
  1677. IN DWORD Property,
  1678. IN CONST BYTE* PropertyBuffer, OPTIONAL
  1679. IN DWORD PropertyBufferSize,
  1680. IN PCSTR MachineName, OPTIONAL
  1681. IN PVOID Reserved
  1682. )
  1683. /*++
  1684. See SetupDiSetClassRegistryProperty
  1685. --*/
  1686. {
  1687. PCWSTR MachineString = NULL;
  1688. DWORD Err = NO_ERROR;
  1689. if (Reserved != NULL) {
  1690. //
  1691. // make sure caller doesn't pass a value here
  1692. // so we know we can use this at a later date
  1693. SetLastError(ERROR_INVALID_PARAMETER);
  1694. return FALSE;
  1695. }
  1696. try {
  1697. //
  1698. // convert machine-name to local
  1699. //
  1700. if (MachineName != NULL) {
  1701. MachineString = pSetupAnsiToUnicode(MachineName);
  1702. if(!MachineString) {
  1703. Err = ERROR_NOT_ENOUGH_MEMORY;
  1704. leave;
  1705. }
  1706. }
  1707. Err = _SetupDiSetClassRegistryProperty(ClassGuid,
  1708. Property,
  1709. PropertyBuffer,
  1710. PropertyBufferSize,
  1711. MachineString,
  1712. TRUE);
  1713. } except(EXCEPTION_EXECUTE_HANDLER) {
  1714. Err = NO_ERROR;
  1715. }
  1716. if (MachineString != NULL) {
  1717. MyFree(MachineString);
  1718. }
  1719. SetLastError(Err);
  1720. return (BOOL)(Err == NO_ERROR);
  1721. }
  1722. #else
  1723. //
  1724. // UNICODE stub
  1725. //
  1726. WINSETUPAPI
  1727. BOOL
  1728. WINAPI
  1729. SetupDiSetClassRegistryPropertyW(
  1730. IN CONST GUID *ClassGuid,
  1731. IN DWORD Property,
  1732. IN CONST BYTE* PropertyBuffer, OPTIONAL
  1733. IN DWORD PropertyBufferSize,
  1734. IN PCWSTR MachineName, OPTIONAL
  1735. IN PVOID Reserved
  1736. )
  1737. /*++
  1738. See SetupDiSetClassRegistryProperty
  1739. --*/
  1740. {
  1741. UNREFERENCED_PARAMETER(ClassGuid);
  1742. UNREFERENCED_PARAMETER(Property);
  1743. UNREFERENCED_PARAMETER(PropertyBuffer);
  1744. UNREFERENCED_PARAMETER(PropertyBufferSize);
  1745. UNREFERENCED_PARAMETER(MachineName);
  1746. UNREFERENCED_PARAMETER(Reserved);
  1747. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  1748. return(FALSE);
  1749. }
  1750. #endif // UNICODE
  1751. WINSETUPAPI
  1752. BOOL
  1753. WINAPI
  1754. SetupDiSetClassRegistryProperty(
  1755. IN CONST GUID *ClassGuid,
  1756. IN DWORD Property,
  1757. IN CONST BYTE* PropertyBuffer, OPTIONAL
  1758. IN DWORD PropertyBufferSize,
  1759. IN PCTSTR MachineName, OPTIONAL
  1760. IN PVOID Reserved
  1761. )
  1762. /*++
  1763. Routine Description:
  1764. This routine sets the specified Plug & Play device class registry property.
  1765. This is just a wrapper around the Config Mgr API
  1766. Typically the properties here can be overridden on a per-device basis
  1767. Arguments:
  1768. ClassGuid - Supplies the class Guid for the P&P device, that the property is to
  1769. be set for
  1770. Property - Supplies an ordinal specifying the property to be retrieved. Refer
  1771. to sdk\inc\setupapi.h for a complete list of properties that may be retrieved.
  1772. PropertyRegDataType - Optionally, supplies the address of a variable that
  1773. will receive the data type of the property being retrieved. This will
  1774. be one of the standard registry data types (REG_SZ, REG_BINARY, etc.)
  1775. PropertyBuffer - Supplies the address of a buffer that receives the property
  1776. data.
  1777. PropertyBufferSize - Supplies the length, in bytes, of PropertyBuffer.
  1778. RequiredSize - Optionally, supplies the address of a variable that receives
  1779. the number of bytes required to store the requested property in the buffer.
  1780. MachineName - Allows properties to be got from a remote machine (if Non-NULL)
  1781. Reserved - should be nULL
  1782. Return Value:
  1783. If the function succeeds, the return value is TRUE.
  1784. If the function fails, the return value is FALSE. To get extended error
  1785. information, call GetLastError.
  1786. --*/
  1787. {
  1788. DWORD Err;
  1789. Err = _SetupDiSetClassRegistryProperty(ClassGuid,
  1790. Property,
  1791. PropertyBuffer,
  1792. PropertyBufferSize,
  1793. MachineName,
  1794. FALSE);
  1795. SetLastError(Err);
  1796. return (BOOL)(Err == NO_ERROR);
  1797. }
  1798. BOOL
  1799. pSetupFindUniqueKey(
  1800. IN HKEY hkRoot,
  1801. IN LPTSTR SubKey,
  1802. IN ULONG SubKeyLength
  1803. )
  1804. /*++
  1805. Routine Description:
  1806. This routine finds a unique key under the specified subkey. This key is
  1807. of the form <SubKey>\xxxx, where xxxx is a base-10, 4-digit number.
  1808. Arguments:
  1809. hkRoot - Root key under which the specified SubKey is located.
  1810. SubKey - Name of the subkey, under which a unique key is to be generated.
  1811. SubKeyLength - Supplies the length of the SubKey string, not including
  1812. terminating NULL.
  1813. Return Value:
  1814. If the function succeeds, the return value is TRUE.
  1815. If the function fails, the return value is FALSE.
  1816. --*/
  1817. {
  1818. INT i;
  1819. HKEY hk;
  1820. for(i = 0; i <= 9999; i++) {
  1821. wsprintf(&(SubKey[SubKeyLength]), pszUniqueSubKey, i);
  1822. if(RegOpenKeyEx(hkRoot, SubKey, 0, KEY_READ, &hk) != ERROR_SUCCESS) {
  1823. return TRUE;
  1824. }
  1825. RegCloseKey(hk);
  1826. }
  1827. return FALSE;
  1828. }
  1829. BOOL
  1830. WINAPI
  1831. SetupDiDeleteDevRegKey(
  1832. IN HDEVINFO DeviceInfoSet,
  1833. IN PSP_DEVINFO_DATA DeviceInfoData,
  1834. IN DWORD Scope,
  1835. IN DWORD HwProfile,
  1836. IN DWORD KeyType
  1837. )
  1838. /*++
  1839. Routine Description:
  1840. This routine deletes the specified registry key(s) associated with a device
  1841. information element.
  1842. Arguments:
  1843. DeviceInfoSet - Supplies a handle to the device information set containing
  1844. the device instance to delete key(s) for.
  1845. DeviceInfoData - Supplies a pointer to a SP_DEVINFO_DATA structure indicating
  1846. the device instance to delete key(s) for.
  1847. Scope - Specifies the scope of the registry key to be deleted. This determines
  1848. where the key to be deleted is located--the key may be one that is global
  1849. (i.e., constant regardless of current hardware profile) or hardware
  1850. profile-specific. May be a combination of the following values:
  1851. DICS_FLAG_GLOBAL - Delete the key that stores global configuration information.
  1852. DICS_FLAG_CONFIGSPECIFIC - Delete the key that stores hardware profile-specific
  1853. information.
  1854. HwProfile - Specifies the hardware profile to delete a key for, if the Scope parameter
  1855. includes the DICS_FLAG_CONFIGSPECIFIC flag. If this parameter is 0, then the key
  1856. for the current hardware profile should be deleted (i.e., in the Class branch
  1857. under HKEY_CURRENT_CONFIG). If this parameter is 0xFFFFFFFF, then the key for
  1858. _all_ hardware profiles should be deleted.
  1859. KeyType - Specifies the type of registry storage key to be deleted. May be one of
  1860. the following values:
  1861. DIREG_DEV - Delete the hardware registry key for the device. This is the key for
  1862. storage of driver-independent configuration information. (This key is in
  1863. the device instance key in the Enum branch.
  1864. DIREG_DRV - Delete the software (i.e., driver) registry key for the device. (This key
  1865. is located in the class branch.)
  1866. DIREG_BOTH - Delete both the hardware and software keys for the device.
  1867. Return Value:
  1868. If the function succeeds, the return value is TRUE.
  1869. If the function fails, the return value is FALSE. To get extended error
  1870. information, call GetLastError.
  1871. --*/
  1872. {
  1873. PDEVICE_INFO_SET pDeviceInfoSet;
  1874. DWORD Err;
  1875. PDEVINFO_ELEM DevInfoElem;
  1876. CONFIGRET cr;
  1877. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  1878. SetLastError(ERROR_INVALID_HANDLE);
  1879. return FALSE;
  1880. }
  1881. try {
  1882. //
  1883. // Get a pointer to the element for the specified device
  1884. // instance.
  1885. //
  1886. if(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  1887. DeviceInfoData,
  1888. NULL)) {
  1889. Err = pSetupDeleteDevRegKeys(DevInfoElem->DevInst, Scope, HwProfile, KeyType, FALSE);
  1890. } else {
  1891. Err = ERROR_INVALID_PARAMETER;
  1892. }
  1893. } except(EXCEPTION_EXECUTE_HANDLER) {
  1894. Err = ERROR_INVALID_PARAMETER;
  1895. }
  1896. UnlockDeviceInfoSet(pDeviceInfoSet);
  1897. SetLastError(Err);
  1898. return(Err == NO_ERROR);
  1899. }
  1900. DWORD
  1901. pSetupDeleteDevRegKeys(
  1902. IN DEVINST DevInst,
  1903. IN DWORD Scope,
  1904. IN DWORD HwProfile,
  1905. IN DWORD KeyType,
  1906. IN BOOL DeleteUserKeys
  1907. )
  1908. /*++
  1909. Routine Description:
  1910. This is the worker routine for SetupDiDeleteDevRegKey. See the discussion of
  1911. that API for details.
  1912. Return Value:
  1913. If successful, the return value is NO_ERROR;
  1914. If failure, the return value is a Win32 error code indicating the cause of failure.
  1915. Remarks:
  1916. Even if one of the operations in this routine fails, all operations will be attempted.
  1917. Thus, as many keys as possible will be deleted. The error returned will be the first
  1918. error that was encountered in this case.
  1919. --*/
  1920. {
  1921. CONFIGRET cr, crTemp;
  1922. DWORD Err;
  1923. cr = CR_SUCCESS;
  1924. if(Scope & DICS_FLAG_GLOBAL) {
  1925. if((KeyType == DIREG_DEV) || (KeyType == DIREG_BOTH)) {
  1926. crTemp = CM_Delete_DevInst_Key(DevInst, 0, CM_REGISTRY_HARDWARE);
  1927. if((cr == CR_SUCCESS) && (crTemp != CR_SUCCESS) && (crTemp != CR_NO_SUCH_REGISTRY_KEY)) {
  1928. cr = crTemp;
  1929. }
  1930. }
  1931. if((KeyType == DIREG_DRV) || (KeyType == DIREG_BOTH)) {
  1932. crTemp = CM_Delete_DevInst_Key(DevInst, 0, CM_REGISTRY_SOFTWARE);
  1933. if((cr == CR_SUCCESS) && (crTemp != CR_SUCCESS) && (crTemp != CR_NO_SUCH_REGISTRY_KEY)) {
  1934. cr = crTemp;
  1935. }
  1936. }
  1937. }
  1938. if(Scope & DICS_FLAG_CONFIGSPECIFIC) {
  1939. if((KeyType == DIREG_DEV) || (KeyType == DIREG_BOTH)) {
  1940. crTemp = CM_Delete_DevInst_Key(DevInst, HwProfile, CM_REGISTRY_HARDWARE | CM_REGISTRY_CONFIG);
  1941. if((cr == CR_SUCCESS) && (crTemp != CR_SUCCESS) && (crTemp != CR_NO_SUCH_REGISTRY_KEY)) {
  1942. cr = crTemp;
  1943. }
  1944. }
  1945. if((KeyType == DIREG_DRV) || (KeyType == DIREG_BOTH)) {
  1946. crTemp = CM_Delete_DevInst_Key(DevInst, HwProfile, CM_REGISTRY_SOFTWARE | CM_REGISTRY_CONFIG);
  1947. if((cr == CR_SUCCESS) && (crTemp != CR_SUCCESS) && (crTemp != CR_NO_SUCH_REGISTRY_KEY)) {
  1948. cr = crTemp;
  1949. }
  1950. }
  1951. }
  1952. if(DeleteUserKeys) {
  1953. if((KeyType == DIREG_DEV) || (KeyType == DIREG_BOTH)) {
  1954. crTemp = CM_Delete_DevInst_Key(DevInst, 0, CM_REGISTRY_HARDWARE | CM_REGISTRY_USER);
  1955. if((cr == CR_SUCCESS) && (crTemp != CR_SUCCESS) && (crTemp != CR_NO_SUCH_REGISTRY_KEY)) {
  1956. cr = crTemp;
  1957. }
  1958. }
  1959. if((KeyType == DIREG_DRV) || (KeyType == DIREG_BOTH)) {
  1960. crTemp = CM_Delete_DevInst_Key(DevInst, 0, CM_REGISTRY_SOFTWARE | CM_REGISTRY_USER);
  1961. if((cr == CR_SUCCESS) && (crTemp != CR_SUCCESS) && (crTemp != CR_NO_SUCH_REGISTRY_KEY)) {
  1962. cr = crTemp;
  1963. }
  1964. }
  1965. }
  1966. //
  1967. // Now translate the ConfigMgr return code into a Win32 one.
  1968. //
  1969. switch(cr) {
  1970. case CR_SUCCESS :
  1971. Err = NO_ERROR;
  1972. break;
  1973. case CR_REGISTRY_ERROR :
  1974. Err = ERROR_ACCESS_DENIED;
  1975. break;
  1976. case CR_INVALID_DEVINST :
  1977. Err = ERROR_NO_SUCH_DEVINST;
  1978. break;
  1979. default :
  1980. Err = ERROR_INVALID_DATA;
  1981. }
  1982. return Err;
  1983. }
  1984. #ifdef UNICODE
  1985. //
  1986. // ANSI version
  1987. //
  1988. HKEY
  1989. WINAPI
  1990. SetupDiCreateDeviceInterfaceRegKeyA(
  1991. IN HDEVINFO DeviceInfoSet,
  1992. IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
  1993. IN DWORD Reserved,
  1994. IN REGSAM samDesired,
  1995. IN HINF InfHandle, OPTIONAL
  1996. IN PCSTR InfSectionName OPTIONAL
  1997. )
  1998. {
  1999. DWORD rc;
  2000. PWSTR name;
  2001. HKEY h;
  2002. if(InfSectionName) {
  2003. rc = pSetupCaptureAndConvertAnsiArg(InfSectionName, &name);
  2004. if(rc != NO_ERROR) {
  2005. SetLastError(rc);
  2006. return(INVALID_HANDLE_VALUE);
  2007. }
  2008. } else {
  2009. name = NULL;
  2010. }
  2011. h = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet,
  2012. DeviceInterfaceData,
  2013. Reserved,
  2014. samDesired,
  2015. InfHandle,
  2016. name
  2017. );
  2018. rc = GetLastError();
  2019. if(name) {
  2020. MyFree(name);
  2021. }
  2022. SetLastError(rc);
  2023. return(h);
  2024. }
  2025. #else
  2026. //
  2027. // Unicode stub
  2028. //
  2029. HKEY
  2030. WINAPI
  2031. SetupDiCreateDeviceInterfaceRegKeyW(
  2032. IN HDEVINFO DeviceInfoSet,
  2033. IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
  2034. IN DWORD Reserved,
  2035. IN REGSAM samDesired,
  2036. IN HINF InfHandle, OPTIONAL
  2037. IN PCWSTR InfSectionName OPTIONAL
  2038. )
  2039. {
  2040. UNREFERENCED_PARAMETER(DeviceInfoSet);
  2041. UNREFERENCED_PARAMETER(DeviceInterfaceData);
  2042. UNREFERENCED_PARAMETER(Reserved);
  2043. UNREFERENCED_PARAMETER(samDesired);
  2044. UNREFERENCED_PARAMETER(InfHandle);
  2045. UNREFERENCED_PARAMETER(InfSectionName);
  2046. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  2047. return(INVALID_HANDLE_VALUE);
  2048. }
  2049. #endif
  2050. HKEY
  2051. WINAPI
  2052. SetupDiCreateDeviceInterfaceRegKey(
  2053. IN HDEVINFO DeviceInfoSet,
  2054. IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
  2055. IN DWORD Reserved,
  2056. IN REGSAM samDesired,
  2057. IN HINF InfHandle, OPTIONAL
  2058. IN PCTSTR InfSectionName OPTIONAL
  2059. )
  2060. /*++
  2061. Routine Description:
  2062. This routine creates a registry storage key for a particular device interface,
  2063. and returns a handle to the key.
  2064. Arguments:
  2065. DeviceInfoSet - Supplies a handle to the device information set containing
  2066. the device interface for whom a registry key is to be created.
  2067. DeviceInterfaceData - Supplies a pointer to a device interface data structure
  2068. indicating which device interface a key is to be created for.
  2069. Reserved - Reserved for future use, must be set to 0.
  2070. samDesired - Specifies the registry access desired for the resulting key handle.
  2071. InfHandle - Optionally, supplies the handle of an opened INF file containing an
  2072. install section to be executed for the newly-created key. If this parameter is
  2073. specified, then InfSectionName must be specified as well.
  2074. InfSectionName - Optionally, supplies the name of an install section in the INF
  2075. file specified by InfHandle. This section will be executed for the newly
  2076. created key. If this parameter is specified, then InfHandle must be specified
  2077. as well.
  2078. Return Value:
  2079. If the function succeeds, the return value is a handle to a newly-created
  2080. registry key where private configuration data pertaining to this device
  2081. interface may be stored/retrieved.
  2082. If the function fails, the return value is INVALID_HANDLE_VALUE. To get
  2083. extended error information, call GetLastError.
  2084. Remarks:
  2085. The handle returned from this routine must be closed by calling RegCloseKey.
  2086. During GUI-mode setup on Windows NT, quiet-install behavior is always
  2087. employed in the absence of a user-supplied file queue, regardless of
  2088. whether the device information element has the DI_QUIETINSTALL flag set.
  2089. --*/
  2090. {
  2091. HKEY hk, hSubKey;
  2092. PDEVICE_INFO_SET pDeviceInfoSet;
  2093. DWORD Err;
  2094. PDEVINFO_ELEM DevInfoElem;
  2095. PSP_FILE_CALLBACK MsgHandler;
  2096. PVOID MsgHandlerContext;
  2097. BOOL MsgHandlerIsNativeCharWidth;
  2098. BOOL NoProgressUI;
  2099. if(Reserved != 0) {
  2100. SetLastError(ERROR_INVALID_PARAMETER);
  2101. return INVALID_HANDLE_VALUE;
  2102. }
  2103. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  2104. SetLastError(ERROR_INVALID_HANDLE);
  2105. return INVALID_HANDLE_VALUE;
  2106. }
  2107. Err = NO_ERROR;
  2108. hk = hSubKey = INVALID_HANDLE_VALUE;
  2109. try {
  2110. //
  2111. // Get a pointer to the device information element for the specified
  2112. // interface device.
  2113. //
  2114. if(!(DevInfoElem = FindDevInfoElemForInterfaceDevice(pDeviceInfoSet, DeviceInterfaceData))) {
  2115. Err = ERROR_INVALID_PARAMETER;
  2116. goto clean0;
  2117. }
  2118. hk = SetupDiOpenClassRegKeyEx(&(DeviceInterfaceData->InterfaceClassGuid),
  2119. KEY_READ,
  2120. DIOCR_INTERFACE,
  2121. NULL,
  2122. NULL
  2123. );
  2124. if(hk == INVALID_HANDLE_VALUE) {
  2125. //
  2126. // We couldn't open the interface class subkey--this should never happen.
  2127. //
  2128. Err = GetLastError();
  2129. goto clean0;
  2130. }
  2131. //
  2132. // Now, create the client-accessible registry storage key for this interface device.
  2133. //
  2134. Err = pSetupOpenOrCreateInterfaceDeviceRegKey(hk,
  2135. pDeviceInfoSet,
  2136. DeviceInterfaceData,
  2137. TRUE,
  2138. samDesired,
  2139. &hSubKey
  2140. );
  2141. RegCloseKey(hk);
  2142. hk = INVALID_HANDLE_VALUE;
  2143. if(Err != NO_ERROR) {
  2144. goto clean0;
  2145. }
  2146. //
  2147. // We successfully created the storage key, now run an INF install
  2148. // section against it (if specified).
  2149. //
  2150. if(InfHandle && (InfHandle != INVALID_HANDLE_VALUE) && InfSectionName) {
  2151. //
  2152. // If a copy msg handler and context haven't been specified, then
  2153. // use the default one.
  2154. //
  2155. if(DevInfoElem->InstallParamBlock.InstallMsgHandler) {
  2156. MsgHandler = DevInfoElem->InstallParamBlock.InstallMsgHandler;
  2157. MsgHandlerContext = DevInfoElem->InstallParamBlock.InstallMsgHandlerContext;
  2158. MsgHandlerIsNativeCharWidth = DevInfoElem->InstallParamBlock.InstallMsgHandlerIsNativeCharWidth;
  2159. } else {
  2160. NoProgressUI = (GuiSetupInProgress || (DevInfoElem->InstallParamBlock.Flags & DI_QUIETINSTALL));
  2161. if(!(MsgHandlerContext = SetupInitDefaultQueueCallbackEx(
  2162. DevInfoElem->InstallParamBlock.hwndParent,
  2163. (NoProgressUI ? INVALID_HANDLE_VALUE : NULL),
  2164. 0,
  2165. 0,
  2166. NULL))) {
  2167. Err = ERROR_NOT_ENOUGH_MEMORY;
  2168. goto clean0;
  2169. }
  2170. MsgHandler = SetupDefaultQueueCallback;
  2171. MsgHandlerIsNativeCharWidth = TRUE;
  2172. }
  2173. if(!_SetupInstallFromInfSection(DevInfoElem->InstallParamBlock.hwndParent,
  2174. InfHandle,
  2175. InfSectionName,
  2176. SPINST_ALL ^ SPINST_LOGCONFIG,
  2177. hSubKey,
  2178. NULL,
  2179. 0,
  2180. MsgHandler,
  2181. MsgHandlerContext,
  2182. INVALID_HANDLE_VALUE,
  2183. NULL,
  2184. MsgHandlerIsNativeCharWidth,
  2185. NULL
  2186. )) {
  2187. Err = GetLastError();
  2188. }
  2189. //
  2190. // If we used the default msg handler, release the default context
  2191. // now.
  2192. //
  2193. if(!DevInfoElem->InstallParamBlock.InstallMsgHandler) {
  2194. SetupTermDefaultQueueCallback(MsgHandlerContext);
  2195. }
  2196. }
  2197. clean0:
  2198. ; // Nothing to do.
  2199. } except(EXCEPTION_EXECUTE_HANDLER) {
  2200. Err = ERROR_INVALID_PARAMETER;
  2201. if(hk != INVALID_HANDLE_VALUE) {
  2202. RegCloseKey(hk);
  2203. }
  2204. //
  2205. // Access the following registry handle so that the compiler will
  2206. // respect statement ordering w.r.t. its assignment.
  2207. //
  2208. hSubKey = hSubKey;
  2209. }
  2210. UnlockDeviceInfoSet(pDeviceInfoSet);
  2211. if(Err == NO_ERROR) {
  2212. return hSubKey;
  2213. } else {
  2214. if(hSubKey != INVALID_HANDLE_VALUE) {
  2215. RegCloseKey(hSubKey);
  2216. }
  2217. SetLastError(Err);
  2218. return INVALID_HANDLE_VALUE;
  2219. }
  2220. }
  2221. HKEY
  2222. WINAPI
  2223. SetupDiOpenDeviceInterfaceRegKey(
  2224. IN HDEVINFO DeviceInfoSet,
  2225. IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
  2226. IN DWORD Reserved,
  2227. IN REGSAM samDesired
  2228. )
  2229. /*++
  2230. Routine Description:
  2231. This routine opens a registry storage key for a particular device interface,
  2232. and returns a handle to the key.
  2233. Arguments:
  2234. DeviceInfoSet - Supplies a handle to the device information set containing
  2235. the device interface for whom a registry key is to be opened.
  2236. InterfaceDeviceData - Supplies a pointer to a device interface data structure
  2237. indicating which device interface a key is to be opened for.
  2238. Reserved - Reserved for future use, must be set to 0.
  2239. samDesired - Specifies the access you require for this key.
  2240. Return Value:
  2241. If the function succeeds, the return value is a handle to an opened registry
  2242. key where private configuration data pertaining to this device interface may be
  2243. stored/retrieved.
  2244. If the function fails, the return value is INVALID_HANDLE_VALUE. To get
  2245. extended error information, call GetLastError.
  2246. Remarks:
  2247. The handle returned from this routine must be closed by calling RegCloseKey.
  2248. --*/
  2249. {
  2250. HKEY hk, hSubKey;
  2251. PDEVICE_INFO_SET pDeviceInfoSet;
  2252. DWORD Err;
  2253. PDEVINFO_ELEM DevInfoElem;
  2254. if(Reserved != 0) {
  2255. SetLastError(ERROR_INVALID_PARAMETER);
  2256. return INVALID_HANDLE_VALUE;
  2257. }
  2258. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  2259. SetLastError(ERROR_INVALID_HANDLE);
  2260. return INVALID_HANDLE_VALUE;
  2261. }
  2262. Err = NO_ERROR;
  2263. hk = INVALID_HANDLE_VALUE;
  2264. try {
  2265. //
  2266. // Get a pointer to the device information element for the specified
  2267. // interface device.
  2268. //
  2269. if(!(DevInfoElem = FindDevInfoElemForInterfaceDevice(pDeviceInfoSet, DeviceInterfaceData))) {
  2270. Err = ERROR_INVALID_PARAMETER;
  2271. goto clean0;
  2272. }
  2273. hk = SetupDiOpenClassRegKeyEx(&(DeviceInterfaceData->InterfaceClassGuid),
  2274. KEY_READ,
  2275. DIOCR_INTERFACE,
  2276. NULL,
  2277. NULL
  2278. );
  2279. if(hk == INVALID_HANDLE_VALUE) {
  2280. //
  2281. // We couldn't open the interface class subkey--this should never happen.
  2282. //
  2283. Err = GetLastError();
  2284. goto clean0;
  2285. }
  2286. //
  2287. // Now, open up the client-accessible registry storage key for this interface device.
  2288. //
  2289. Err = pSetupOpenOrCreateInterfaceDeviceRegKey(hk,
  2290. pDeviceInfoSet,
  2291. DeviceInterfaceData,
  2292. FALSE,
  2293. samDesired,
  2294. &hSubKey
  2295. );
  2296. clean0:
  2297. ; // nothing to do.
  2298. } except(EXCEPTION_EXECUTE_HANDLER) {
  2299. Err = ERROR_INVALID_PARAMETER;
  2300. //
  2301. // Access the following registry handle so that the compiler will respect
  2302. // statement ordering w.r.t. its assignment.
  2303. //
  2304. hk = hk;
  2305. }
  2306. UnlockDeviceInfoSet(pDeviceInfoSet);
  2307. if(hk != INVALID_HANDLE_VALUE) {
  2308. RegCloseKey(hk);
  2309. }
  2310. SetLastError(Err);
  2311. return (Err == NO_ERROR) ? hSubKey : INVALID_HANDLE_VALUE;
  2312. }
  2313. BOOL
  2314. WINAPI
  2315. SetupDiDeleteDeviceInterfaceRegKey(
  2316. IN HDEVINFO DeviceInfoSet,
  2317. IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
  2318. IN DWORD Reserved
  2319. )
  2320. /*++
  2321. Routine Description:
  2322. This routine deletes the registry key associated with a device interface.
  2323. Arguments:
  2324. DeviceInfoSet - Supplies a handle to the device information set containing
  2325. the device interface whose registry key is to be deleted.
  2326. DeviceInterfaceData - Supplies a pointer to a device interface data structure
  2327. indicating which device interface is to have its registry key deleted.
  2328. Reserved - Reserved for future use, must be set to 0.
  2329. Return Value:
  2330. If the function succeeds, the return value is TRUE.
  2331. If the function fails, the return value is FALSE. To get extended error
  2332. information, call GetLastError.
  2333. --*/
  2334. {
  2335. HKEY hk;
  2336. PDEVICE_INFO_SET pDeviceInfoSet;
  2337. DWORD Err;
  2338. PDEVINFO_ELEM DevInfoElem;
  2339. if(Reserved != 0) {
  2340. SetLastError(ERROR_INVALID_PARAMETER);
  2341. return FALSE;
  2342. }
  2343. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  2344. SetLastError(ERROR_INVALID_HANDLE);
  2345. return FALSE;
  2346. }
  2347. hk = INVALID_HANDLE_VALUE;
  2348. try {
  2349. //
  2350. // Get a pointer to the device information element for the specified
  2351. // interface device.
  2352. //
  2353. if(!(DevInfoElem = FindDevInfoElemForInterfaceDevice(pDeviceInfoSet, DeviceInterfaceData))) {
  2354. Err = ERROR_INVALID_PARAMETER;
  2355. goto clean0;
  2356. }
  2357. hk = SetupDiOpenClassRegKeyEx(&(DeviceInterfaceData->InterfaceClassGuid),
  2358. KEY_READ,
  2359. DIOCR_INTERFACE,
  2360. NULL,
  2361. NULL
  2362. );
  2363. if(hk == INVALID_HANDLE_VALUE) {
  2364. //
  2365. // We couldn't open the interface class subkey--this should never happen.
  2366. //
  2367. Err = GetLastError();
  2368. goto clean0;
  2369. }
  2370. //
  2371. // Now delete the interface device key.
  2372. //
  2373. Err = pSetupDeleteInterfaceDeviceKey(hk, pDeviceInfoSet, DeviceInterfaceData);
  2374. clean0:
  2375. ; // nothing to do.
  2376. } except(EXCEPTION_EXECUTE_HANDLER) {
  2377. Err = ERROR_INVALID_PARAMETER;
  2378. //
  2379. // Access the following registry handle so the compiler will respect statement
  2380. // ordering w.r.t. its assignment.
  2381. //
  2382. hk = hk;
  2383. }
  2384. UnlockDeviceInfoSet(pDeviceInfoSet);
  2385. if(hk != INVALID_HANDLE_VALUE) {
  2386. RegCloseKey(hk);
  2387. }
  2388. SetLastError(Err);
  2389. return(Err == NO_ERROR);
  2390. }
  2391. DWORD
  2392. pSetupOpenOrCreateInterfaceDeviceRegKey(
  2393. IN HKEY hInterfaceClassKey,
  2394. IN PDEVICE_INFO_SET DeviceInfoSet,
  2395. IN PSP_DEVICE_INTERFACE_DATA InterfaceDeviceData,
  2396. IN BOOL Create,
  2397. IN REGSAM samDesired,
  2398. OUT PHKEY hInterfaceDeviceKey
  2399. )
  2400. /*++
  2401. Routine Description:
  2402. This routine creates or opens a registry storage key for the specified
  2403. interface device, and returns a handle to the opened key.
  2404. Arguments:
  2405. hInterfaceClassKey - Supplies a handle to the opened driver key, underneath which
  2406. resides the interface device key to be deleted.
  2407. DeviceInfoSet - Supplies a pointer to the device information set containing
  2408. the interface device for which a registry storage key is to be created/opened.
  2409. InterfaceDeviceData - Supplies a pointer to an interface device data structure
  2410. indicating which interface device a key is to be opened/created for.
  2411. Create - Specifies whether the key should be created if doesn't already exist.
  2412. samDesired - Specifies the access you require for this key.
  2413. hInterfaceDeviceKey - Supplies the address of a variable that receives a handle
  2414. to the requested registry key. (This variable will only be written to if the
  2415. handle is successfully opened.)
  2416. Return Value:
  2417. If the function is successful, the return value is NO_ERROR, otherwise, it is
  2418. the ERROR_* code indicating the error that occurred.
  2419. Remarks:
  2420. The algorithm used to form the storage keys for an interface device must be kept
  2421. in sync with the kernel mode implementation of IoOpenDeviceClassRegistryKey.
  2422. --*/
  2423. {
  2424. DWORD Err;
  2425. PINTERFACE_DEVICE_NODE InterfaceDeviceNode;
  2426. LPGUID ClassGuid;
  2427. HKEY hInterfaceDeviceRootKey, hSubKey;
  2428. DWORD Disposition;
  2429. PCTSTR DevicePath;
  2430. Err = NO_ERROR;
  2431. hInterfaceDeviceRootKey = INVALID_HANDLE_VALUE;
  2432. try {
  2433. //
  2434. // Get the interface device node, and verify that its class matches what the
  2435. // caller passed us.
  2436. //
  2437. InterfaceDeviceNode = (PINTERFACE_DEVICE_NODE)(InterfaceDeviceData->Reserved);
  2438. ClassGuid = &(DeviceInfoSet->GuidTable[InterfaceDeviceNode->GuidIndex]);
  2439. if(!IsEqualGUID(ClassGuid, &(InterfaceDeviceData->InterfaceClassGuid))) {
  2440. Err = ERROR_INVALID_PARAMETER;
  2441. goto clean0;
  2442. }
  2443. //
  2444. // Verify that this interface device hasn't been removed.
  2445. //
  2446. if(InterfaceDeviceNode->Flags & SPINT_REMOVED) {
  2447. Err = ERROR_DEVICE_INTERFACE_REMOVED;
  2448. goto clean0;
  2449. }
  2450. //
  2451. // OK, now open the interface device's root storage key.
  2452. //
  2453. DevicePath = pStringTableStringFromId(DeviceInfoSet->StringTable,
  2454. InterfaceDeviceNode->SymLinkName
  2455. );
  2456. if(ERROR_SUCCESS != OpenDeviceInterfaceSubKey(hInterfaceClassKey,
  2457. DevicePath,
  2458. KEY_READ,
  2459. &hInterfaceDeviceRootKey,
  2460. NULL,
  2461. NULL)) {
  2462. //
  2463. // Make sure hInterfaceDeviceRootKey is still INVALID_HANDLE_VALUE, so we
  2464. // won't try to close it later.
  2465. //
  2466. hInterfaceDeviceRootKey = INVALID_HANDLE_VALUE;
  2467. Err = ERROR_INVALID_PARAMETER;
  2468. goto clean0;
  2469. }
  2470. if(Create) {
  2471. Err = RegCreateKeyEx(hInterfaceDeviceRootKey,
  2472. pszDeviceParameters,
  2473. 0,
  2474. NULL,
  2475. REG_OPTION_NON_VOLATILE,
  2476. samDesired,
  2477. NULL,
  2478. &hSubKey,
  2479. &Disposition
  2480. );
  2481. } else {
  2482. Err = RegOpenKeyEx(hInterfaceDeviceRootKey,
  2483. pszDeviceParameters,
  2484. 0,
  2485. samDesired,
  2486. &hSubKey
  2487. );
  2488. }
  2489. clean0:
  2490. ; // nothing to do.
  2491. } except(EXCEPTION_EXECUTE_HANDLER) {
  2492. Err = ERROR_INVALID_PARAMETER;
  2493. //
  2494. // Access the following variable so the compiler will respect statement ordering
  2495. // w.r.t. assignment.
  2496. //
  2497. hInterfaceDeviceRootKey = hInterfaceDeviceRootKey;
  2498. }
  2499. if(hInterfaceDeviceRootKey != INVALID_HANDLE_VALUE) {
  2500. RegCloseKey(hInterfaceDeviceRootKey);
  2501. }
  2502. if(Err == NO_ERROR) {
  2503. *hInterfaceDeviceKey = hSubKey;
  2504. }
  2505. return Err;
  2506. }
  2507. DWORD
  2508. pSetupDeleteInterfaceDeviceKey(
  2509. IN HKEY hInterfaceClassKey,
  2510. IN PDEVICE_INFO_SET DeviceInfoSet,
  2511. IN PSP_DEVICE_INTERFACE_DATA InterfaceDeviceData
  2512. )
  2513. /*++
  2514. Routine Description:
  2515. This routine deletes an interface device registry key (recursively deleting
  2516. any subkeys as well).
  2517. Arguments:
  2518. hInterfaceClassKey - Supplies the handle to the registry key underneath which the 2-level
  2519. interface class hierarchy exists.
  2520. DeviceInfoSet - Supplies a pointer to the device information set containing
  2521. the interface device whose registry key is to be deleted.
  2522. InterfaceDeviceData - Supplies a pointer to an interface device data structure
  2523. indicating which interface device is to have its registry key deleted.
  2524. Return Value:
  2525. If successful, the return value is NO_ERROR;
  2526. If failure, the return value is a Win32 error code indicating the cause of failure.
  2527. --*/
  2528. {
  2529. DWORD Err;
  2530. PINTERFACE_DEVICE_NODE InterfaceDeviceNode;
  2531. LPGUID ClassGuid;
  2532. HKEY hInterfaceDeviceRootKey;
  2533. PCTSTR DevicePath;
  2534. Err = NO_ERROR;
  2535. hInterfaceDeviceRootKey = INVALID_HANDLE_VALUE;
  2536. try {
  2537. //
  2538. // Get the interface device node, and verify that its class matches what the
  2539. // caller passed us.
  2540. //
  2541. InterfaceDeviceNode = (PINTERFACE_DEVICE_NODE)(InterfaceDeviceData->Reserved);
  2542. ClassGuid = &(DeviceInfoSet->GuidTable[InterfaceDeviceNode->GuidIndex]);
  2543. if(!IsEqualGUID(ClassGuid, &(InterfaceDeviceData->InterfaceClassGuid))) {
  2544. Err = ERROR_INVALID_PARAMETER;
  2545. goto clean0;
  2546. }
  2547. //
  2548. // Verify that this interface device hasn't been removed.
  2549. //
  2550. if(InterfaceDeviceNode->Flags & SPINT_REMOVED) {
  2551. Err = ERROR_DEVICE_INTERFACE_REMOVED;
  2552. goto clean0;
  2553. }
  2554. //
  2555. // OK, now open the interface device's root storage key.
  2556. //
  2557. DevicePath = pStringTableStringFromId(DeviceInfoSet->StringTable,
  2558. InterfaceDeviceNode->SymLinkName
  2559. );
  2560. if(ERROR_SUCCESS != OpenDeviceInterfaceSubKey(hInterfaceClassKey,
  2561. DevicePath,
  2562. KEY_READ,
  2563. &hInterfaceDeviceRootKey,
  2564. NULL,
  2565. NULL)) {
  2566. //
  2567. // Make sure hInterfaceDeviceRootKey is still INVALID_HANDLE_VALUE, so we
  2568. // won't try to close it later.
  2569. //
  2570. hInterfaceDeviceRootKey = INVALID_HANDLE_VALUE;
  2571. Err = ERROR_INVALID_PARAMETER;
  2572. goto clean0;
  2573. }
  2574. Err = pSetupRegistryDelnode(hInterfaceDeviceRootKey, pszDeviceParameters);
  2575. clean0:
  2576. ; // nothing to do.
  2577. } except(EXCEPTION_EXECUTE_HANDLER) {
  2578. Err = ERROR_INVALID_PARAMETER;
  2579. //
  2580. // Access the following variable so the compiler will respect statement ordering
  2581. // w.r.t. assignment.
  2582. //
  2583. hInterfaceDeviceRootKey = hInterfaceDeviceRootKey;
  2584. }
  2585. if(hInterfaceDeviceRootKey != INVALID_HANDLE_VALUE) {
  2586. RegCloseKey(hInterfaceDeviceRootKey);
  2587. }
  2588. return Err;
  2589. }
  2590. #ifdef UNICODE
  2591. BOOL
  2592. WINAPI
  2593. _SetupDiGetCustomDeviceProperty(
  2594. IN HDEVINFO DeviceInfoSet,
  2595. IN PSP_DEVINFO_DATA DeviceInfoData,
  2596. IN CONST VOID *CustomPropertyName, // ANSI or Unicode, depending on "Ansi" param.
  2597. IN DWORD Flags,
  2598. OUT PDWORD PropertyRegDataType, OPTIONAL
  2599. OUT PBYTE PropertyBuffer,
  2600. IN DWORD PropertyBufferSize,
  2601. OUT PDWORD RequiredSize, OPTIONAL
  2602. IN BOOL Ansi
  2603. )
  2604. {
  2605. PDEVICE_INFO_SET pDeviceInfoSet;
  2606. DWORD Err;
  2607. PDEVINFO_ELEM DevInfoElem;
  2608. CONFIGRET cr;
  2609. ULONG PropLength, CmFlags;
  2610. //
  2611. // At present, there's only one valid flag...
  2612. //
  2613. if(Flags & ~DICUSTOMDEVPROP_MERGE_MULTISZ) {
  2614. SetLastError(ERROR_INVALID_FLAGS);
  2615. return FALSE;
  2616. }
  2617. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  2618. SetLastError(ERROR_INVALID_HANDLE);
  2619. return FALSE;
  2620. }
  2621. Err = NO_ERROR;
  2622. try {
  2623. //
  2624. // Get a pointer to the element for the specified device
  2625. // instance.
  2626. //
  2627. if(!(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  2628. DeviceInfoData,
  2629. NULL))) {
  2630. Err = ERROR_INVALID_PARAMETER;
  2631. goto clean0;
  2632. }
  2633. if(Flags & DICUSTOMDEVPROP_MERGE_MULTISZ) {
  2634. CmFlags = CM_CUSTOMDEVPROP_MERGE_MULTISZ;
  2635. } else {
  2636. CmFlags = 0;
  2637. }
  2638. PropLength = PropertyBufferSize;
  2639. if(Ansi) {
  2640. cr = CM_Get_DevInst_Custom_Property_ExA(
  2641. DevInfoElem->DevInst,
  2642. CustomPropertyName,
  2643. PropertyRegDataType,
  2644. PropertyBuffer,
  2645. &PropLength,
  2646. CmFlags,
  2647. pDeviceInfoSet->hMachine
  2648. );
  2649. } else {
  2650. cr = CM_Get_DevInst_Custom_Property_ExW(
  2651. DevInfoElem->DevInst,
  2652. CustomPropertyName,
  2653. PropertyRegDataType,
  2654. PropertyBuffer,
  2655. &PropLength,
  2656. CmFlags,
  2657. pDeviceInfoSet->hMachine
  2658. );
  2659. }
  2660. if((cr == CR_SUCCESS) || (cr == CR_BUFFER_SMALL)) {
  2661. if(RequiredSize) {
  2662. *RequiredSize = PropLength;
  2663. }
  2664. }
  2665. if(cr != CR_SUCCESS) {
  2666. switch(cr) {
  2667. case CR_INVALID_DEVINST :
  2668. Err = ERROR_NO_SUCH_DEVINST;
  2669. break;
  2670. case CR_BUFFER_SMALL :
  2671. Err = ERROR_INSUFFICIENT_BUFFER;
  2672. break;
  2673. case CR_NO_SUCH_VALUE :
  2674. Err = ERROR_NOT_FOUND;
  2675. break;
  2676. default :
  2677. Err = ERROR_INVALID_DATA;
  2678. }
  2679. }
  2680. clean0:
  2681. ; // Nothing to do.
  2682. } except(EXCEPTION_EXECUTE_HANDLER) {
  2683. Err = ERROR_INVALID_PARAMETER;
  2684. }
  2685. UnlockDeviceInfoSet(pDeviceInfoSet);
  2686. SetLastError(Err);
  2687. return (Err == NO_ERROR);
  2688. }
  2689. #endif
  2690. #ifdef UNICODE
  2691. //
  2692. // Unicode version
  2693. //
  2694. BOOL
  2695. WINAPI
  2696. SetupDiGetCustomDevicePropertyW(
  2697. IN HDEVINFO DeviceInfoSet,
  2698. IN PSP_DEVINFO_DATA DeviceInfoData,
  2699. IN PCWSTR CustomPropertyName,
  2700. IN DWORD Flags,
  2701. OUT PDWORD PropertyRegDataType, OPTIONAL
  2702. OUT PBYTE PropertyBuffer,
  2703. IN DWORD PropertyBufferSize,
  2704. OUT PDWORD RequiredSize OPTIONAL
  2705. )
  2706. /*++
  2707. Routine Description:
  2708. This routine retrieves the data for the specified property, either from the
  2709. device information element's hardware key, or from the most-specific
  2710. per-hardware-id storage key containing that property.
  2711. Arguments:
  2712. DeviceInfoSet -- Supplies a handle to the device information set containing
  2713. information about the device instance to retrieve a Plug & Play
  2714. registry property for.
  2715. DeviceInfoData -- Supplies a pointer to a SP_DEVINFO_DATA structure
  2716. indicating the device instance to retrieve the Plug & Play registry
  2717. property for
  2718. CustomPropertyName - Supplies the name of the property to be retrieved.
  2719. Flags - Supplies flags controlling how the property data is to be
  2720. retrieved. May be a combination of the following values:
  2721. DICUSTOMDEVPROP_MERGE_MULTISZ : Merge the devnode-specific REG_SZ or
  2722. REG_MULTI_SZ property (if present) with
  2723. the per-hardware-id REG_SZ or
  2724. REG_MULTI_SZ property (if present).
  2725. The resultant data will always be a
  2726. multi-sz list.
  2727. PropertyRegDataType -- Optionally, supplies the address of a variable that
  2728. will receive the data type of the property being retrieved. This will
  2729. be one of the standard registry data types (REG_SZ, REG_BINARY, etc.)
  2730. PropertyBuffer -- Supplies the address of a buffer that receives the
  2731. property data.
  2732. PropertyBufferSize -- Supplies the length, in bytes, of PropertyBuffer.
  2733. RequiredSize -- Optionally, supplies the address of a variable that
  2734. receives the number of bytes required to store the requested property
  2735. in the buffer.
  2736. Return Value:
  2737. If the function succeeds, the return value is TRUE.
  2738. If the function fails, the return value is FALSE. To get extended error
  2739. information, call GetLastError. If the supplied buffer was not large
  2740. enough to hold the requested property, the error will be
  2741. ERROR_INSUFFICIENT_BUFFER and RequiredSize will specify how large the
  2742. buffer needs to be.
  2743. --*/
  2744. {
  2745. BOOL b;
  2746. b = _SetupDiGetCustomDeviceProperty(
  2747. DeviceInfoSet,
  2748. DeviceInfoData,
  2749. CustomPropertyName,
  2750. Flags,
  2751. PropertyRegDataType,
  2752. PropertyBuffer,
  2753. PropertyBufferSize,
  2754. RequiredSize,
  2755. FALSE // want Unicode results
  2756. );
  2757. return(b);
  2758. }
  2759. //
  2760. // ANSI version
  2761. //
  2762. BOOL
  2763. WINAPI
  2764. SetupDiGetCustomDevicePropertyA(
  2765. IN HDEVINFO DeviceInfoSet,
  2766. IN PSP_DEVINFO_DATA DeviceInfoData,
  2767. IN PCSTR CustomPropertyName,
  2768. IN DWORD Flags,
  2769. OUT PDWORD PropertyRegDataType, OPTIONAL
  2770. OUT PBYTE PropertyBuffer,
  2771. IN DWORD PropertyBufferSize,
  2772. OUT PDWORD RequiredSize OPTIONAL
  2773. )
  2774. /*++
  2775. Routine Description:
  2776. (See SetupDiGetCustomDevicePropertyW)
  2777. --*/
  2778. {
  2779. BOOL b;
  2780. b = _SetupDiGetCustomDeviceProperty(
  2781. DeviceInfoSet,
  2782. DeviceInfoData,
  2783. CustomPropertyName,
  2784. Flags,
  2785. PropertyRegDataType,
  2786. PropertyBuffer,
  2787. PropertyBufferSize,
  2788. RequiredSize,
  2789. TRUE // want ANSI results
  2790. );
  2791. return(b);
  2792. }
  2793. #else // Both Unicode and ANSI stubs are unimplemented in ANSI setupapi...
  2794. //
  2795. // Unicode stub
  2796. //
  2797. BOOL
  2798. WINAPI
  2799. SetupDiGetCustomDevicePropertyW(
  2800. IN HDEVINFO DeviceInfoSet,
  2801. IN PSP_DEVINFO_DATA DeviceInfoData,
  2802. IN PCWSTR CustomPropertyName,
  2803. IN DWORD Flags,
  2804. OUT PDWORD PropertyRegDataType, OPTIONAL
  2805. OUT PBYTE PropertyBuffer,
  2806. IN DWORD PropertyBufferSize,
  2807. OUT PDWORD RequiredSize OPTIONAL
  2808. )
  2809. {
  2810. UNREFERENCED_PARAMETER(DeviceInfoSet);
  2811. UNREFERENCED_PARAMETER(DeviceInfoData);
  2812. UNREFERENCED_PARAMETER(CustomPropertyName);
  2813. UNREFERENCED_PARAMETER(Flags);
  2814. UNREFERENCED_PARAMETER(PropertyRegDataType);
  2815. UNREFERENCED_PARAMETER(PropertyBuffer);
  2816. UNREFERENCED_PARAMETER(PropertyBufferSize);
  2817. UNREFERENCED_PARAMETER(RequiredSize);
  2818. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  2819. return(FALSE);
  2820. }
  2821. //
  2822. // ANSI stub
  2823. //
  2824. BOOL
  2825. WINAPI
  2826. SetupDiGetCustomDevicePropertyA(
  2827. IN HDEVINFO DeviceInfoSet,
  2828. IN PSP_DEVINFO_DATA DeviceInfoData,
  2829. IN PCSTR CustomPropertyName,
  2830. IN DWORD Flags,
  2831. OUT PDWORD PropertyRegDataType, OPTIONAL
  2832. OUT PBYTE PropertyBuffer,
  2833. IN DWORD PropertyBufferSize,
  2834. OUT PDWORD RequiredSize OPTIONAL
  2835. )
  2836. {
  2837. UNREFERENCED_PARAMETER(DeviceInfoSet);
  2838. UNREFERENCED_PARAMETER(DeviceInfoData);
  2839. UNREFERENCED_PARAMETER(CustomPropertyName);
  2840. UNREFERENCED_PARAMETER(Flags);
  2841. UNREFERENCED_PARAMETER(PropertyRegDataType);
  2842. UNREFERENCED_PARAMETER(PropertyBuffer);
  2843. UNREFERENCED_PARAMETER(PropertyBufferSize);
  2844. UNREFERENCED_PARAMETER(RequiredSize);
  2845. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  2846. return(FALSE);
  2847. }
  2848. #endif