Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1065 lines
32 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. rhwprof.c
  5. Abstract:
  6. This module contains the server-side hardware profile APIs.
  7. PNP_IsDockStationPresent
  8. PNP_RequestEjectPC
  9. PNP_HwProfFlags
  10. PNP_GetHwProfInfo
  11. PNP_SetHwProf
  12. Author:
  13. Paula Tomlinson (paulat) 7-18-1995
  14. Environment:
  15. User-mode only.
  16. Revision History:
  17. 18-July-1995 paulat
  18. Creation and initial implementation.
  19. --*/
  20. //
  21. // includes
  22. //
  23. #include "precomp.h"
  24. #pragma hdrstop
  25. #include "umpnpi.h"
  26. #include "umpnpdat.h"
  27. #include <profiles.h>
  28. //
  29. // private prototypes
  30. //
  31. BOOL
  32. IsCurrentProfile(
  33. ULONG ulProfile
  34. );
  35. CONFIGRET
  36. PNP_IsDockStationPresent(
  37. IN handle_t hBinding,
  38. OUT PBOOL Present
  39. )
  40. /*++
  41. Routine Description:
  42. This routine determines whether a docking station is currently present.
  43. Parameters:
  44. hBinding RPC binding handle.
  45. Present Supplies the address of a boolean variable that is set
  46. upon successful return to indicate whether or not a
  47. docking station is currently present.
  48. Return Value:
  49. If the function succeeds, the return value is CR_SUCCESS.
  50. If the function fails, the return value is a CR failure code.
  51. --*/
  52. {
  53. CONFIGRET Status = CR_SUCCESS;
  54. HKEY hCurrentDockInfo = NULL, hIDConfigDB = NULL;
  55. DWORD dataType;
  56. ULONG dockingState;
  57. ULONG ejectableDocks;
  58. ULONG size;
  59. UNREFERENCED_PARAMETER(hBinding);
  60. try {
  61. //
  62. // Validate parameters.
  63. //
  64. if (!ARGUMENT_PRESENT(Present)) {
  65. Status = CR_FAILURE;
  66. goto Clean0;
  67. }
  68. *Present = FALSE;
  69. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  70. pszRegPathIDConfigDB,
  71. 0,
  72. KEY_READ,
  73. &hIDConfigDB) != ERROR_SUCCESS) {
  74. Status = CR_REGISTRY_ERROR;
  75. hIDConfigDB = NULL;
  76. goto Clean0;
  77. }
  78. if (RegOpenKeyEx(hIDConfigDB,
  79. pszRegKeyCurrentDockInfo,
  80. 0,
  81. KEY_READ,
  82. &hCurrentDockInfo) != ERROR_SUCCESS) {
  83. Status = CR_REGISTRY_ERROR;
  84. hCurrentDockInfo = NULL;
  85. goto Clean0;
  86. }
  87. size = sizeof (dockingState);
  88. if ((RegQueryValueEx(hCurrentDockInfo,
  89. pszRegValueDockingState,
  90. 0,
  91. &dataType,
  92. (PUCHAR) &dockingState,
  93. &size) != ERROR_SUCCESS) ||
  94. (dataType != REG_DWORD) ||
  95. (size != sizeof (ULONG))) {
  96. Status = CR_REGISTRY_ERROR;
  97. goto Clean0;
  98. }
  99. if ((dockingState & HW_PROFILE_DOCKSTATE_UNKNOWN) ==
  100. HW_PROFILE_DOCKSTATE_DOCKED) {
  101. size = sizeof(ejectableDocks);
  102. if ((RegQueryValueEx(hCurrentDockInfo,
  103. pszRegValueEjectableDocks,
  104. 0,
  105. &dataType,
  106. (PUCHAR) &ejectableDocks,
  107. &size) == ERROR_SUCCESS) &&
  108. (dataType == REG_DWORD) &&
  109. (size == sizeof(ULONG)) &&
  110. (ejectableDocks > 0)) {
  111. *Present = TRUE;
  112. }
  113. }
  114. Clean0:
  115. NOTHING;
  116. } except(EXCEPTION_EXECUTE_HANDLER) {
  117. Status = CR_FAILURE;
  118. }
  119. if (hIDConfigDB) {
  120. RegCloseKey(hIDConfigDB);
  121. }
  122. if (hCurrentDockInfo) {
  123. RegCloseKey(hCurrentDockInfo);
  124. }
  125. return Status;
  126. } // PNP_IsDockStationPresent
  127. CONFIGRET
  128. PNP_RequestEjectPC(
  129. IN handle_t hBinding
  130. )
  131. /*++
  132. Routine Description:
  133. This routine requests that the PC be ejected (i.e., undocked).
  134. Parameters:
  135. hBinding RPC binding handle.
  136. Return Value:
  137. If the function succeeds, the return value is CR_SUCCESS.
  138. If the function fails, the return value is a CR failure code.
  139. --*/
  140. {
  141. CONFIGRET Status = CR_SUCCESS;
  142. NTSTATUS ntStatus;
  143. WCHAR szDockDevInst[MAX_DEVICE_ID_LEN + 1];
  144. PLUGPLAY_CONTROL_RETRIEVE_DOCK_DATA dockData;
  145. try {
  146. //
  147. // Find the dock devnode, if one exists.
  148. //
  149. dockData.DeviceInstance = szDockDevInst;
  150. dockData.DeviceInstanceLength = MAX_DEVICE_ID_LEN;
  151. ntStatus = NtPlugPlayControl(PlugPlayControlRetrieveDock,
  152. &dockData,
  153. sizeof(PLUGPLAY_CONTROL_RETRIEVE_DOCK_DATA));
  154. if (!NT_SUCCESS(ntStatus)) {
  155. Status = MapNtStatusToCmError(ntStatus);
  156. goto Clean0;
  157. }
  158. //
  159. // Request eject on the dock devnode. Note PNP_RequestDeviceEject may
  160. // require additional access and/or privileges, as appropriate.
  161. //
  162. Status = PNP_RequestDeviceEject(hBinding,
  163. szDockDevInst,
  164. NULL, // pVetoType
  165. NULL, // pszVetoName
  166. 0, // ulNameLength
  167. 0); // ulFlags
  168. Clean0:
  169. NOTHING;
  170. } except(EXCEPTION_EXECUTE_HANDLER) {
  171. Status = CR_FAILURE;
  172. }
  173. return Status;
  174. } // PNP_RequestEjectPC
  175. CONFIGRET
  176. PNP_HwProfFlags(
  177. IN handle_t hBinding,
  178. IN ULONG ulAction,
  179. IN LPCWSTR pDeviceID,
  180. IN ULONG ulConfig,
  181. IN OUT PULONG pulValue,
  182. OUT PPNP_VETO_TYPE pVetoType,
  183. OUT LPWSTR pszVetoName,
  184. IN ULONG ulNameLength,
  185. IN ULONG ulFlags
  186. )
  187. /*++
  188. Routine Description:
  189. This is the RPC server entry point for the ConfigManager routines that
  190. get and set the hardware profile flags.
  191. Arguments:
  192. hBinding RPC binding handle.
  193. ulAction Specified whether to get or set the flag. Can be one
  194. of the PNP_*_HWPROFFLAGS values.
  195. pDeviceID Device instance to get/set the hw profile flag for.
  196. ulConfig Specifies which profile to get/set the flag for. A
  197. value of zero indicates to use the current profile.
  198. pulValue If setting the flag, then this value on entry contains
  199. the value to set the hardware profile flag to. If
  200. getting the flag, then this value will return the
  201. current hardware profile flag.
  202. pVetoType Buffer to receive the type of veto. If this is NULL
  203. then no veto information will be received and the OS wil
  204. display the veto information.
  205. pszVetoName Buffer to receive the veto information. If this is NULL
  206. then no veto information will be received and the OS will
  207. display the veto information.
  208. ulNameLength Size of the pszVetoName buffer.
  209. ulFlags Depends on the action being performed.
  210. For PNP_GET_HWPROFFLAGS, no flags are valid.
  211. For PNP_SET_HWPROFFLAGS, may be CM_SET_HW_PROF_FLAGS_BITS.
  212. Return Value:
  213. If the function succeeds it returns CR_SUCCESS. Otherwise it returns one
  214. of the CR_* values.
  215. --*/
  216. {
  217. CONFIGRET Status = CR_SUCCESS;
  218. ULONG RegStatus = ERROR_SUCCESS;
  219. WCHAR RegStr[MAX_CM_PATH];
  220. HKEY hKey = NULL, hDevKey = NULL;
  221. ULONG ulValueSize = sizeof(ULONG);
  222. ULONG ulCurrentValue, ulChange, ulDisposition;
  223. BOOL AffectsCurrentProfile;
  224. //
  225. // NOTE: The device is not checked for presence or not, this flag is
  226. // always just set or retrieved directly from the registry, as it is
  227. // done on Windows 95
  228. //
  229. try {
  230. //
  231. // validate parameters
  232. //
  233. if ((ulAction != PNP_GET_HWPROFFLAGS) &&
  234. (ulAction != PNP_SET_HWPROFFLAGS)) {
  235. Status = CR_INVALID_DATA;
  236. goto Clean0;
  237. }
  238. if (ulAction == PNP_GET_HWPROFFLAGS) {
  239. //
  240. // Validate flags for PNP_GET_HWPROFFLAGS
  241. //
  242. if (INVALID_FLAGS(ulFlags, 0)) {
  243. Status = CR_INVALID_FLAG;
  244. goto Clean0;
  245. }
  246. } else if (ulAction == PNP_SET_HWPROFFLAGS) {
  247. //
  248. // Verify client "write" access
  249. //
  250. if (!VerifyClientAccess(hBinding,
  251. PLUGPLAY_WRITE)) {
  252. Status = CR_ACCESS_DENIED;
  253. goto Clean0;
  254. }
  255. //
  256. // Validate flags for PNP_SET_HWPROFFLAGS
  257. //
  258. if (INVALID_FLAGS(ulFlags, CM_SET_HW_PROF_FLAGS_BITS)) {
  259. Status = CR_INVALID_FLAG;
  260. goto Clean0;
  261. }
  262. }
  263. //
  264. // validate parameters
  265. //
  266. if (!ARGUMENT_PRESENT(pulValue)) {
  267. Status = CR_INVALID_POINTER;
  268. goto Clean0;
  269. }
  270. //
  271. // Validate value for PNP_SET_HWPROFFLAGS
  272. //
  273. if ((ulAction == PNP_SET_HWPROFFLAGS) &&
  274. (INVALID_FLAGS(*pulValue, CSCONFIGFLAG_BITS))) {
  275. Status = CR_INVALID_DATA;
  276. goto Clean0;
  277. }
  278. if (!IsLegalDeviceId(pDeviceID)) {
  279. Status = CR_INVALID_DEVNODE;
  280. goto Clean0;
  281. }
  282. //
  283. // Construct the path to the Enum branch for the hardware profile
  284. // specified.
  285. //
  286. if (ulConfig == 0) {
  287. //
  288. // a configuration value of zero implies to use the current config
  289. // System\CCS\Hardware Profiles\Current\System\Enum
  290. //
  291. if (FAILED(StringCchPrintf(
  292. RegStr,
  293. MAX_CM_PATH,
  294. L"%s\\%s\\%s",
  295. pszRegPathHwProfiles,
  296. pszRegKeyCurrent,
  297. pszRegPathEnum))) {
  298. Status = CR_FAILURE;
  299. goto Clean0;
  300. }
  301. } else {
  302. //
  303. // use the specified profile id
  304. // System\CCS\Hardware Profiles\xxxx\System\Enum
  305. //
  306. if (FAILED(StringCchPrintf(
  307. RegStr,
  308. MAX_CM_PATH,
  309. L"%s\\%04u\\%s",
  310. pszRegPathHwProfiles,
  311. ulConfig,
  312. pszRegPathEnum))) {
  313. Status = CR_FAILURE;
  314. goto Clean0;
  315. }
  316. }
  317. //----------------------------------------------------
  318. // caller wants to retrieve the hw profile flag value
  319. //----------------------------------------------------
  320. if (ulAction == PNP_GET_HWPROFFLAGS) {
  321. //
  322. // open the profile specific enum key
  323. //
  324. RegStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE, RegStr, 0,
  325. KEY_QUERY_VALUE, &hKey);
  326. if (RegStatus != ERROR_SUCCESS) {
  327. *pulValue = 0; // success,this is what Win95 does
  328. goto Clean0;
  329. }
  330. //
  331. // open the enum\device-instance key under the profile key
  332. //
  333. RegStatus = RegOpenKeyEx( hKey, pDeviceID, 0, KEY_QUERY_VALUE, &hDevKey);
  334. if (RegStatus != ERROR_SUCCESS) {
  335. *pulValue = 0; // success,this is what Win95 does
  336. goto Clean0;
  337. }
  338. //
  339. // query the profile flag
  340. //
  341. ulValueSize = sizeof(ULONG);
  342. RegStatus = RegQueryValueEx( hDevKey, pszRegValueCSConfigFlags,
  343. NULL, NULL, (LPBYTE)pulValue,
  344. &ulValueSize);
  345. if (RegStatus != ERROR_SUCCESS) {
  346. *pulValue = 0;
  347. if (RegStatus != ERROR_CANTREAD && RegStatus != ERROR_FILE_NOT_FOUND) {
  348. Status = CR_REGISTRY_ERROR;
  349. goto Clean0;
  350. }
  351. }
  352. }
  353. //----------------------------------------------
  354. // caller wants to set the hw profile flag value
  355. //----------------------------------------------
  356. else if (ulAction == PNP_SET_HWPROFFLAGS) {
  357. //
  358. // open the profile specific enum key.
  359. //
  360. // note that we may actually end up creating a Hardware Profile key
  361. // here for the specified profile id, even if no such profile
  362. // exists. ideally, we should check that such a profile exists, but
  363. // we've been doing this for too long to change it now. the
  364. // consolation here is that the client must be granted appropriate
  365. // access to actually do this.
  366. //
  367. RegStatus = RegCreateKeyEx( HKEY_LOCAL_MACHINE, RegStr, 0, NULL,
  368. REG_OPTION_NON_VOLATILE, KEY_QUERY_VALUE,
  369. NULL, &hKey, &ulDisposition);
  370. if (RegStatus != ERROR_SUCCESS) {
  371. Status = CR_REGISTRY_ERROR;
  372. goto Clean0;
  373. }
  374. //
  375. // open the enum\device-instance key under the profile key
  376. //
  377. RegStatus = RegCreateKeyEx( hKey, pDeviceID, 0, NULL,
  378. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
  379. NULL, &hDevKey, NULL);
  380. if (RegStatus != ERROR_SUCCESS) {
  381. Status = CR_REGISTRY_ERROR;
  382. goto Clean0;
  383. }
  384. //
  385. // before setting, query the current profile flag
  386. //
  387. ulValueSize = sizeof(ulCurrentValue);
  388. RegStatus = RegQueryValueEx( hDevKey, pszRegValueCSConfigFlags,
  389. NULL, NULL, (LPBYTE)&ulCurrentValue,
  390. &ulValueSize);
  391. if (RegStatus == ERROR_CANTREAD || RegStatus == ERROR_FILE_NOT_FOUND) {
  392. ulCurrentValue = 0; // success,this is what Win95 does
  393. } else if (RegStatus != ERROR_SUCCESS) {
  394. Status = CR_REGISTRY_ERROR;
  395. goto Clean0;
  396. }
  397. //
  398. // if requested flags different than current, write out to registry
  399. //
  400. ulChange = ulCurrentValue ^ *pulValue;
  401. if (ulChange) {
  402. AffectsCurrentProfile = (BOOL)(ulConfig == 0 || IsCurrentProfile(ulConfig));
  403. //
  404. // we're about to change the disable bit on the current profile,
  405. // try and disable the device in the process
  406. //
  407. if ((ulChange & CSCONFIGFLAG_DISABLED) &&
  408. (*pulValue & CSCONFIGFLAG_DISABLED) && AffectsCurrentProfile) {
  409. //
  410. // Verify client "execute" access and privilege.
  411. //
  412. // Note that as the PLUGPLAY_* access rights are *currently*
  413. // granted, we know that the client should have execute
  414. // access (because they were already granted "write" access,
  415. // which is granted to a strict subset of groups that are
  416. // granted "execute" access). Since this does not always
  417. // have to be the case, we'll make the separate check for
  418. // "execute" access here, prior to making the privilege
  419. // check, as usual.
  420. //
  421. if ((!VerifyClientAccess(hBinding,
  422. PLUGPLAY_EXECUTE)) ||
  423. (!VerifyClientPrivilege(hBinding,
  424. SE_LOAD_DRIVER_PRIVILEGE,
  425. L"Device Action (disable device)"))) {
  426. //
  427. // The client either does not possess the privilege, or
  428. // did not have the right to use that privilege with the
  429. // PlugPlay service. Since they were able to modify the
  430. // persistent state (i.e. granted "write" access),
  431. // rather than return "access denied", we'll tell them
  432. // that a restart is required for the change to take
  433. // place for the device to be disabled. Set the status,
  434. // but fall through so that the CSConfigFlags are still
  435. // updated.
  436. //
  437. // (Note that when Status is set to any failure code
  438. // other than CR_NOT_DISABLEABLE, it will always be set
  439. // to CR_NEED_RESTART below, but we'll go ahead use that
  440. // failure code here as well, rather than confusing the
  441. // issue.)
  442. //
  443. Status = CR_NEED_RESTART;
  444. } else {
  445. //
  446. // NOTE: We enter a critical section here to guard against concurrent
  447. // read/write operations to the "DisableCount" registry value of any
  448. // single device instance by DisableDevInst (below), and SetupDevInst,
  449. // EnableDevInst (called by PNP_DeviceInstanceAction).
  450. //
  451. PNP_ENTER_SYNCHRONOUS_CALL();
  452. //
  453. // disable the devnode
  454. //
  455. Status = DisableDevInst(pDeviceID,
  456. pVetoType,
  457. pszVetoName,
  458. ulNameLength,
  459. FALSE);
  460. PNP_LEAVE_SYNCHRONOUS_CALL();
  461. }
  462. if (Status == CR_NOT_DISABLEABLE) {
  463. //
  464. // we got refused!
  465. // (note that this error also implies *NO* changes to the registry entry)
  466. //
  467. goto Clean0;
  468. } else if (Status != CR_SUCCESS) {
  469. //
  470. // we can go ahead and disable after restart
  471. //
  472. Status = CR_NEED_RESTART;
  473. }
  474. }
  475. //
  476. // assume Status is valid and typically CR_SUCCESS or CR_NEED_RESTART
  477. //
  478. //
  479. // now update the registry
  480. //
  481. RegStatus = RegSetValueEx( hDevKey, pszRegValueCSConfigFlags, 0,
  482. REG_DWORD, (LPBYTE)pulValue,
  483. sizeof(ULONG));
  484. if (RegStatus != ERROR_SUCCESS) {
  485. Status = CR_REGISTRY_ERROR;
  486. goto Clean0;
  487. }
  488. if (Status == CR_NEED_RESTART) {
  489. //
  490. // we have to RESTART due to not being able to disable device immediately
  491. //
  492. goto Clean0;
  493. }
  494. //
  495. // If this doesn't effect the current config, then we're done.
  496. //
  497. if (!AffectsCurrentProfile) {
  498. goto Clean0;
  499. }
  500. //
  501. // are we enabling the device?
  502. //
  503. if ((ulChange & CSCONFIGFLAG_DISABLED) && !(*pulValue & CSCONFIGFLAG_DISABLED)) {
  504. //
  505. // enable the devnode
  506. //
  507. //
  508. // NOTE: We enter a critical section here to guard against
  509. // concurrent read/write operations to the "DisableCount"
  510. // registry value of any single device instance by
  511. // EnableDevInst (called below), SetupDevInst, and
  512. // DisableDevInst.
  513. //
  514. PNP_ENTER_SYNCHRONOUS_CALL();
  515. //
  516. // enable the devnode
  517. //
  518. EnableDevInst(pDeviceID, FALSE);
  519. PNP_LEAVE_SYNCHRONOUS_CALL();
  520. }
  521. //
  522. // did the do-not-create bit change?
  523. //
  524. if (ulChange & CSCONFIGFLAG_DO_NOT_CREATE) {
  525. if (*pulValue & CSCONFIGFLAG_DO_NOT_CREATE) {
  526. //
  527. // if subtree can be removed, remove it now
  528. //
  529. if (QueryAndRemoveSubTree( pDeviceID,
  530. pVetoType,
  531. pszVetoName,
  532. ulNameLength,
  533. PNP_QUERY_AND_REMOVE_NO_RESTART) != CR_SUCCESS) {
  534. Status = CR_NEED_RESTART;
  535. goto Clean0;
  536. }
  537. }
  538. else {
  539. //
  540. // The DO_NOT_CREATE flag was turned off, reenumerate the devnode
  541. //
  542. ReenumerateDevInst(pDeviceID, TRUE, 0);
  543. }
  544. }
  545. }
  546. }
  547. Clean0:
  548. NOTHING;
  549. } except(EXCEPTION_EXECUTE_HANDLER) {
  550. Status = CR_FAILURE;
  551. }
  552. if (hKey != NULL) {
  553. RegCloseKey(hKey);
  554. }
  555. if (hDevKey != NULL) {
  556. RegCloseKey(hDevKey);
  557. }
  558. return Status;
  559. } // PNP_HwProfFlags
  560. CONFIGRET
  561. PNP_GetHwProfInfo(
  562. IN handle_t hBinding,
  563. IN ULONG ulIndex,
  564. OUT PHWPROFILEINFO pHWProfileInfo,
  565. IN ULONG ulProfileInfoSize,
  566. IN ULONG ulFlags
  567. )
  568. /*++
  569. Routine Description:
  570. This is the RPC server entry point for the ConfigManager routine
  571. CM_Get_Hardware_Profile_Info. It returns a structure of info for
  572. the specified hardware profile.
  573. Arguments:
  574. hBinding RPC binding handle.
  575. ulIndex Specifies which profile to use. A value of 0xFFFFFFFF
  576. indicates to use the current profile.
  577. pHWProfileInfo Pointer to HWPROFILEINFO struct, returns profile info
  578. ulProfileInfoSize Specifies the size of the HWPROFILEINFO struct
  579. ulFlags Not used, must be zero.
  580. Return Value:
  581. If the function succeeds it returns CR_SUCCESS. Otherwise it returns one
  582. of the CR_* values.
  583. --*/
  584. {
  585. CONFIGRET Status = CR_SUCCESS;
  586. ULONG RegStatus = ERROR_SUCCESS;
  587. WCHAR RegStr[MAX_CM_PATH];
  588. HKEY hKey = NULL, hDockKey = NULL, hCfgKey = NULL;
  589. ULONG ulSize, ulDisposition;
  590. ULONG enumIndex, targetIndex;
  591. UNREFERENCED_PARAMETER(hBinding);
  592. try {
  593. //
  594. // validate parameters
  595. //
  596. if (INVALID_FLAGS(ulFlags, 0)) {
  597. Status = CR_INVALID_FLAG;
  598. goto Clean0;
  599. }
  600. //
  601. // validate the size of the HWPROFILEINFO struct
  602. //
  603. if (ulProfileInfoSize != sizeof(HWPROFILEINFO)) {
  604. Status = CR_INVALID_DATA;
  605. goto Clean0;
  606. }
  607. //
  608. // initialize the HWPROFILEINFO struct fields
  609. //
  610. pHWProfileInfo->HWPI_ulHWProfile = 0;
  611. pHWProfileInfo->HWPI_szFriendlyName[0] = L'\0';
  612. pHWProfileInfo->HWPI_dwFlags = 0;
  613. //
  614. // open a key to IDConfigDB (create if it doesn't already exist
  615. //
  616. RegStatus = RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszRegPathIDConfigDB, 0,
  617. NULL, REG_OPTION_NON_VOLATILE, KEY_QUERY_VALUE,
  618. NULL, &hKey, &ulDisposition);
  619. if (RegStatus != ERROR_SUCCESS) {
  620. Status = CR_REGISTRY_ERROR;
  621. goto Clean0;
  622. }
  623. //
  624. // open a key to Hardware Profiles (create if it doesn't already exist)
  625. //
  626. RegStatus = RegCreateKeyEx(hKey, pszRegKeyKnownDockingStates, 0,
  627. NULL, REG_OPTION_NON_VOLATILE,
  628. KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, NULL,
  629. &hDockKey, &ulDisposition);
  630. if (RegStatus != ERROR_SUCCESS) {
  631. Status = CR_REGISTRY_ERROR;
  632. goto Clean0;
  633. }
  634. //
  635. // a configuration value of 0xFFFFFFFF implies to use the current config
  636. //
  637. if (ulIndex == 0xFFFFFFFF) {
  638. //
  639. // get the current profile index stored under IDConfigDB
  640. //
  641. ulSize = sizeof(ULONG);
  642. RegStatus = RegQueryValueEx(
  643. hKey, pszRegValueCurrentConfig, NULL, NULL,
  644. (LPBYTE)&pHWProfileInfo->HWPI_ulHWProfile, &ulSize);
  645. if (RegStatus != ERROR_SUCCESS) {
  646. Status = CR_REGISTRY_ERROR;
  647. pHWProfileInfo->HWPI_ulHWProfile = 0;
  648. goto Clean0;
  649. }
  650. }
  651. //
  652. // values other than 0xFFFFFFFF mean that we're essentially
  653. // enumerating profiles (the value is an enumeration index)
  654. //
  655. else {
  656. //
  657. // enumerate the profile keys under Known Docking States
  658. //
  659. Status = CR_SUCCESS;
  660. enumIndex = 0;
  661. targetIndex = ulIndex;
  662. while(enumIndex <= targetIndex) {
  663. ulSize = MAX_CM_PATH;
  664. RegStatus = RegEnumKeyEx(hDockKey,
  665. enumIndex,
  666. RegStr,
  667. &ulSize,
  668. NULL,
  669. NULL,
  670. NULL,
  671. NULL);
  672. if (RegStatus == ERROR_NO_MORE_ITEMS) {
  673. Status = CR_NO_MORE_HW_PROFILES;
  674. goto Clean0;
  675. } else if (RegStatus != ERROR_SUCCESS) {
  676. Status = CR_REGISTRY_ERROR;
  677. goto Clean0;
  678. }
  679. if (_wtoi(RegStr) == 0) {
  680. //
  681. // we found the pristine amidst the profiles we're enumerating.
  682. // enumerate one extra key to make up for it.
  683. //
  684. targetIndex++;
  685. }
  686. if (enumIndex == targetIndex) {
  687. //
  688. // this is the one we want.
  689. //
  690. pHWProfileInfo->HWPI_ulHWProfile = _wtoi(RegStr);
  691. Status = CR_SUCCESS;
  692. break;
  693. }
  694. enumIndex++;
  695. }
  696. }
  697. //
  698. // open the key for this profile
  699. //
  700. if (FAILED(StringCchPrintf(
  701. RegStr,
  702. MAX_CM_PATH,
  703. L"%04u",
  704. pHWProfileInfo->HWPI_ulHWProfile))) {
  705. Status = CR_FAILURE;
  706. goto Clean0;
  707. }
  708. RegStatus =
  709. RegOpenKeyEx(
  710. hDockKey,
  711. RegStr,
  712. 0,
  713. KEY_QUERY_VALUE,
  714. &hCfgKey);
  715. if (RegStatus != ERROR_SUCCESS) {
  716. Status = CR_REGISTRY_ERROR;
  717. goto Clean0;
  718. }
  719. //
  720. // retrieve the friendly name
  721. //
  722. ulSize = MAX_PROFILE_LEN * sizeof(WCHAR);
  723. RegStatus = RegQueryValueEx(
  724. hCfgKey, pszRegValueFriendlyName, NULL, NULL,
  725. (LPBYTE)(pHWProfileInfo->HWPI_szFriendlyName),
  726. &ulSize);
  727. //
  728. // retrieve the DockState
  729. //
  730. #if 0
  731. //
  732. // KENRAY
  733. // This is the wrong way to determine docking state caps
  734. // You must instead check the alias tables
  735. //
  736. StringCchPrintf(
  737. RegStr,
  738. MAX_CM_PATH,
  739. L"%04u",
  740. pHWProfileInfo->HWPI_ulHWProfile);
  741. ulSize = sizeof(SYSTEM_DOCK_STATE);
  742. RegStatus = RegQueryValueEx(
  743. hCfgKey, pszRegValueDockState, NULL, NULL,
  744. (LPBYTE)&DockState, &ulSize);
  745. if (RegStatus != ERROR_SUCCESS) {
  746. pHWProfileInfo->HWPI_dwFlags = CM_HWPI_NOT_DOCKABLE;
  747. }
  748. else {
  749. //
  750. // map SYSTEM_DOCK_STATE enumerated types into CM_HWPI_ flags
  751. //
  752. if (DockState == SystemDocked) {
  753. pHWProfileInfo->HWPI_dwFlags = CM_HWPI_DOCKED;
  754. }
  755. else if (DockState == SystemUndocked) {
  756. pHWProfileInfo->HWPI_dwFlags = CM_HWPI_UNDOCKED;
  757. }
  758. else {
  759. pHWProfileInfo->HWPI_dwFlags = CM_HWPI_NOT_DOCKABLE;
  760. }
  761. }
  762. #endif
  763. Clean0:
  764. NOTHING;
  765. } except(EXCEPTION_EXECUTE_HANDLER) {
  766. Status = CR_FAILURE;
  767. }
  768. if (hKey != NULL) {
  769. RegCloseKey(hKey);
  770. }
  771. if (hDockKey != NULL) {
  772. RegCloseKey(hDockKey);
  773. }
  774. if (hCfgKey != NULL) {
  775. RegCloseKey(hCfgKey);
  776. }
  777. return Status;
  778. } // PNP_GetHwProfInfo
  779. CONFIGRET
  780. PNP_SetHwProf(
  781. IN handle_t hBinding,
  782. IN ULONG ulHardwareProfile,
  783. IN ULONG ulFlags
  784. )
  785. {
  786. UNREFERENCED_PARAMETER(ulHardwareProfile);
  787. UNREFERENCED_PARAMETER(ulFlags);
  788. //
  789. // Verify client "execute" access
  790. //
  791. if (!VerifyClientAccess(hBinding,
  792. PLUGPLAY_EXECUTE)) {
  793. return CR_ACCESS_DENIED;
  794. }
  795. //
  796. // Verify client privilege
  797. //
  798. if (!VerifyClientPrivilege(hBinding,
  799. SE_LOAD_DRIVER_PRIVILEGE,
  800. L"Set Hardware Profile (not implemented)")) {
  801. return CR_ACCESS_DENIED;
  802. }
  803. return CR_CALL_NOT_IMPLEMENTED;
  804. } // PNP_SetHwProf
  805. //-------------------------------------------------------------------
  806. // Private utility routines
  807. //-------------------------------------------------------------------
  808. BOOL
  809. IsCurrentProfile(
  810. ULONG ulProfile
  811. )
  812. /*++
  813. Routine Description:
  814. This routine determines if the specified profile matches the current
  815. profile.
  816. Arguments:
  817. ulProfile Profile id value (value from 1 - 9999).
  818. Return Value:
  819. Return TRUE if this is the current profile, FALSE if it isn't.
  820. --*/
  821. {
  822. HKEY hKey;
  823. ULONG ulSize, ulCurrentProfile;
  824. //
  825. // open a key to IDConfigDB
  826. //
  827. if (RegOpenKeyEx(
  828. HKEY_LOCAL_MACHINE, pszRegPathIDConfigDB, 0,
  829. KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) {
  830. return FALSE;
  831. }
  832. //
  833. // get the current profile index stored under IDConfigDB
  834. //
  835. ulSize = sizeof(ULONG);
  836. if (RegQueryValueEx(
  837. hKey, pszRegValueCurrentConfig, NULL, NULL,
  838. (LPBYTE)&ulCurrentProfile, &ulSize) != ERROR_SUCCESS) {
  839. RegCloseKey(hKey);
  840. return FALSE;
  841. }
  842. RegCloseKey(hKey);
  843. if (ulCurrentProfile == ulProfile) {
  844. return TRUE;
  845. }
  846. return FALSE;
  847. } // IsCurrentProfile