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.

2162 lines
57 KiB

  1. /*++
  2. Copyright (c) 1995-2001 Microsoft Corporation
  3. Module Name:
  4. devnode.c
  5. Abstract:
  6. This module contains the API routines that operate directly on device
  7. instances (or DevNodes, in Win95 terminology).
  8. CM_Create_DevNode
  9. CM_Setup_DevNode
  10. CM_Disable_DevNode
  11. CM_Enable_DevNode
  12. CM_Get_DevNode_Status
  13. CM_Set_DevNode_Problem
  14. CM_Reenumerate_DevNode
  15. CM_Query_And_Remove_SubTree
  16. CM_Uninstall_DevNode
  17. CM_Request_Device_Eject
  18. CM_Add_ID
  19. CM_Register_Device_Driver
  20. This module also contains the following API routines which are
  21. not implemented.
  22. CM_Move_DevNode
  23. CM_Query_Remove_Subtree
  24. CM_Remove_SubTree
  25. Author:
  26. Paula Tomlinson (paulat) 6-20-1995
  27. Environment:
  28. User mode only.
  29. Revision History:
  30. 6-Jun-1995 paulat
  31. Creation and initial implementation.
  32. --*/
  33. //
  34. // includes
  35. //
  36. #include "precomp.h"
  37. #include "cfgi.h"
  38. #include "setupapi.h"
  39. #include "spapip.h"
  40. #include <pnpmgr.h>
  41. CONFIGRET
  42. CM_Create_DevNode_ExW(
  43. OUT PDEVINST pdnDevInst,
  44. IN DEVINSTID_W pDeviceID,
  45. IN DEVINST dnParent,
  46. IN ULONG ulFlags,
  47. IN HMACHINE hMachine
  48. )
  49. /*++
  50. Routine Description:
  51. This routine creates a new device instance in the hardware tree.
  52. Parameters:
  53. pdnDevNode Supplies the address of the variable that receives a handle
  54. to the new device instance.
  55. pDeviceID Supplies a pointer to a NULL-terminated string specifying
  56. the device instance ID for this new device instance. This
  57. is the registry path (relative to the Enum branch) where
  58. this device instance will be located (e.g., Root\*PNP0500\0000).
  59. In Windows NT, this parameter is not optional.
  60. dnParent Supplies the handle of the device instance that is the parent
  61. of the device instance being created.
  62. ulFlags Supplies flags specifying options for the creation of the
  63. device instance. May be one of the following values:
  64. CM_CREATE_DEVNODE_NORMAL
  65. Create the device instance now, and perform installation
  66. for it at a later time.
  67. CM_CREATE_DEVNODE_NO_WAIT_INSTALL
  68. Create the device instance, and perform installation for
  69. it immediately.
  70. CM_CREATE_DEVNODE_PHANTOM
  71. Create a phantom device instance (i.e., a handle to a
  72. device instance that is not alive as far as the ConfigMgr
  73. APIs are concerned). This may be used for CM APIs that
  74. require a devnode handle, but for which no real devnode
  75. currently exists (e.g., registry property APIs). This
  76. flag may not be specified with CR_CREATE_DEVNODE_NORMAL
  77. or CR_CREATE_DEVNODE_NO_WAIT_INSTALL. A phantom devnode
  78. created in this manner is not accessible to other callers
  79. (i.e., CM_Locate_DevNode won't find it). However, callers
  80. attempting to create a devnode with the same name as this
  81. phantom devnode will not be able to do so (they will get
  82. CR_ALREADY_SUCH_DEVNODE).
  83. CM_CREATE_DEVNODE_GENERATE_ID
  84. Create a Root-enumerated devnode using a unique device
  85. instance ID generated from the supplied device ID in
  86. pDeviceID. If this flag is set, then pDeviceID is assumed
  87. to contain simply a device ID (i.e., no enumerator key
  88. prefix, and no device instance suffix). A unique 4-digit,
  89. base-10 identifier string will be created under
  90. Enum\Root\<pDeviceID>, and the devnode will be created
  91. based on that device instance ID. For instance, to add a
  92. new legacy COM port devnode, this API would be called with
  93. a pDeviceID of *PNP0500. Assuming there was already one
  94. COM port instance in the registry (instance 0000), the new
  95. device instance ID would be: Root\*PNP0500\0001
  96. The caller may find out what device instance name was
  97. generated by calling CM_Get_Device_ID with the devnode
  98. returned from this API.
  99. Return Value:
  100. If the function succeeds, the return value is CR_SUCCESS.
  101. If the function fails, the return value is one of the following:
  102. CR_ALREADY_SUCH_DEVNODE,
  103. CR_INVALID_DEVICE_ID,
  104. CR_INVALID_DEVNODE,
  105. CR_INVALID_FLAG,
  106. CR_INVALID_POINTER, or
  107. CR_OUT_OF_MEMORY.
  108. --*/
  109. {
  110. CONFIGRET Status = CR_SUCCESS;
  111. WCHAR ParentID[MAX_DEVICE_ID_LEN];
  112. WCHAR szNewDeviceID[MAX_DEVICE_ID_LEN];
  113. PVOID hStringTable = NULL;
  114. handle_t hBinding = NULL;
  115. ULONG ulLen=MAX_DEVICE_ID_LEN;
  116. BOOL Success;
  117. try {
  118. //
  119. // validate parameters
  120. //
  121. if (!ARGUMENT_PRESENT(pdnDevInst)) {
  122. Status = CR_INVALID_POINTER;
  123. goto Clean0;
  124. }
  125. if (dnParent == 0) {
  126. Status = CR_INVALID_DEVINST;
  127. goto Clean0;
  128. }
  129. //
  130. // the length of the supplied device id string must be shorter than
  131. // MAX_DEVICE_ID_LEN chars so that there is also room for the NULL term
  132. // char in a buffer of this size. (many of the CM_ APIs make different
  133. // assumptions about the consideration of the NULL term char in
  134. // MAX_DEVICE_ID_LEN; account for the NULL term char to be safe)
  135. //
  136. if ((!ARGUMENT_PRESENT(pDeviceID)) ||
  137. (lstrlen(pDeviceID) >= MAX_DEVICE_ID_LEN)) {
  138. Status = CR_INVALID_DEVICE_ID;
  139. goto Clean0;
  140. }
  141. if (INVALID_FLAGS(ulFlags, CM_CREATE_DEVNODE_BITS)) {
  142. Status = CR_INVALID_FLAG;
  143. goto Clean0;
  144. }
  145. //
  146. // Windows NT 5.0 does not support CM_CREATE_DEVNODE_NO_WAIT_INSTALL
  147. //
  148. if (ulFlags & CM_CREATE_DEVNODE_NO_WAIT_INSTALL) {
  149. Status = CR_INVALID_FLAG;
  150. goto Clean0;
  151. }
  152. //
  153. // setup rpc binding handle and string table handle
  154. //
  155. if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
  156. Status = CR_FAILURE;
  157. goto Clean0;
  158. }
  159. //
  160. // Initialize the caller's devnode. This will have the side effect of
  161. // generating an exception before we actually do anything if the caller
  162. // supplied a bogus address.
  163. //
  164. *pdnDevInst = 0;
  165. //
  166. // retreive device instance string that corresponds to dnParent
  167. // (note that this is not optional, even a first level device instance
  168. // has a parent (the root device instance)
  169. //
  170. Success = pSetupStringTableStringFromIdEx(hStringTable, dnParent,ParentID,&ulLen);
  171. if (Success == FALSE || INVALID_DEVINST(ParentID)) {
  172. Status = CR_INVALID_DEVNODE;
  173. goto Clean0;
  174. }
  175. //
  176. // make sure the new device instance is properly formatted
  177. //
  178. CopyFixedUpDeviceId(szNewDeviceID, pDeviceID, lstrlen(pDeviceID));
  179. //
  180. // If not requesting instance generation, then it must be a
  181. // valid device instance path.
  182. //
  183. if (!(ulFlags & CM_CREATE_DEVINST_GENERATE_ID)) {
  184. if ((!*szNewDeviceID) ||
  185. (!IsLegalDeviceId(szNewDeviceID))) {
  186. Status = CR_INVALID_DEVINST;
  187. goto Clean0;
  188. }
  189. }
  190. RpcTryExcept {
  191. //
  192. // call rpc service entry point
  193. //
  194. Status = PNP_CreateDevInst(
  195. hBinding, // rpc binding handle
  196. szNewDeviceID, // device instance to create
  197. ParentID, // parent device instance
  198. MAX_DEVICE_ID_LEN, // max length of szNewDeviceID
  199. ulFlags); // flags
  200. }
  201. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  202. KdPrintEx((DPFLTR_PNPMGR_ID,
  203. DBGF_ERRORS,
  204. "PNP_CreateDevInst caused an exception (%d)\n",
  205. RpcExceptionCode()));
  206. Status = MapRpcExceptionToCR(RpcExceptionCode());
  207. }
  208. RpcEndExcept
  209. if (Status != CR_SUCCESS) {
  210. goto Clean0;
  211. }
  212. //
  213. // assign a unique device instance value to the newly created device
  214. // instance
  215. //
  216. ASSERT(*szNewDeviceID && IsLegalDeviceId(szNewDeviceID));
  217. *pdnDevInst = pSetupStringTableAddString(hStringTable, szNewDeviceID,
  218. STRTAB_CASE_SENSITIVE);
  219. if (*pdnDevInst == 0) {
  220. Status = CR_NO_SUCH_DEVNODE;
  221. }
  222. Clean0:
  223. NOTHING;
  224. } except(EXCEPTION_EXECUTE_HANDLER) {
  225. Status = CR_FAILURE;
  226. }
  227. return Status;
  228. } // CM_Create_DevNode_ExW
  229. CONFIGRET
  230. CM_Move_DevNode_Ex(
  231. IN DEVINST dnFromDevInst,
  232. IN DEVINST dnToDevInst,
  233. IN ULONG ulFlags,
  234. IN HMACHINE hMachine
  235. )
  236. /*++
  237. Routine Description:
  238. This routine replaces a root-enumerated device instance by the valid
  239. non-root-enumerated device instance. The device installer uses this
  240. service when it detects that a non-root enumerated device instance is
  241. really the same as its root enumerated counterpart. This API migrates
  242. the old device instance to the new location, and marks the old location
  243. as having a problem.
  244. ** THIS ROUTINE IS NOT IMPLEMENTED **
  245. Parameters:
  246. dnFromDevNode Supplies the handle of the device instance that has been
  247. root enumerated.
  248. dnToDevNode Supplies the handle of the device instance that is a
  249. reenumeration (duplicate) of the root device instance.
  250. ulFlags Must be zero.
  251. Return Value:
  252. ** PRESENTLY, ALWAYS RETURNS CR_CALL_NOT_IMPLEMENTED **
  253. If the function succeeds, the return value is CR_SUCCESS.
  254. If the function fails, the return value is one of the following:
  255. CR_INVALID_FLAG,
  256. CR_INVALID_DEVNODE,
  257. CR_OUT_OF_MEMORY.
  258. (Windows 95 may also return CR_NOT_AT_APPY_TIME.)
  259. --*/
  260. {
  261. UNREFERENCED_PARAMETER(dnFromDevInst);
  262. UNREFERENCED_PARAMETER(dnToDevInst);
  263. UNREFERENCED_PARAMETER(ulFlags);
  264. UNREFERENCED_PARAMETER(hMachine);
  265. return CR_CALL_NOT_IMPLEMENTED;
  266. } // CM_Move_DevNode_Ex
  267. CONFIGRET
  268. CM_Setup_DevNode_Ex(
  269. IN DEVINST dnDevInst,
  270. IN ULONG ulFlags,
  271. IN HMACHINE hMachine
  272. )
  273. /*++
  274. Routine Description:
  275. This routine reenables and configures a specified device instance or
  276. retrieves information from its enumerator.
  277. Parameters:
  278. dnDevNode Supplies the handle of the device instance which may be
  279. reconfigured.
  280. ulFlags Supplies a flag indicating the action to take. Can be one
  281. of the following values:
  282. CM_SETUP_DEVNODE_READY
  283. Reenable the device instance that had a problem.
  284. CM_SETUP_DOWNLOAD
  285. Retrieve information about this device instance
  286. from its enumerator.
  287. Return Value:
  288. If the function succeeds, the return value is CR_SUCCESS.
  289. If the function fails, the return value is one of the following:
  290. CR_INVALID_FLAG,
  291. CR_INVALID_DEVNODE,
  292. CR_OUT_OF_MEMORY, or
  293. CR_FAILURE.
  294. --*/
  295. {
  296. CONFIGRET Status = CR_SUCCESS;
  297. WCHAR DeviceID[MAX_DEVICE_ID_LEN];
  298. PVOID hStringTable = NULL;
  299. handle_t hBinding = NULL;
  300. ULONG ulLen=MAX_DEVICE_ID_LEN;
  301. BOOL Success;
  302. try {
  303. //
  304. // validate parameters
  305. //
  306. if (INVALID_FLAGS(ulFlags, CM_SETUP_BITS)) {
  307. Status = CR_INVALID_FLAG;
  308. goto Clean0;
  309. }
  310. if (dnDevInst == 0) {
  311. Status = CR_INVALID_DEVINST;
  312. goto Clean0;
  313. }
  314. //
  315. // setup rpc binding handle and string table handle
  316. //
  317. if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
  318. Status = CR_FAILURE;
  319. goto Clean0;
  320. }
  321. //
  322. // retrieve the device instance ID string associated with the devinst
  323. //
  324. Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
  325. if (Success == FALSE || INVALID_DEVINST(DeviceID)) {
  326. Status = CR_INVALID_DEVINST;
  327. goto Clean0;
  328. }
  329. RpcTryExcept {
  330. //
  331. // call rpc service entry point
  332. //
  333. Status = PNP_DeviceInstanceAction(
  334. hBinding, // rpc binding handle
  335. PNP_DEVINST_SETUP, // requested major action - SETUP
  336. ulFlags, // requested minor action
  337. DeviceID, // device instance to create
  338. NULL); // (not used)
  339. }
  340. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  341. KdPrintEx((DPFLTR_PNPMGR_ID,
  342. DBGF_ERRORS,
  343. "PNP_DeviceInstanceAction caused an exception (%d)\n",
  344. RpcExceptionCode()));
  345. Status = MapRpcExceptionToCR(RpcExceptionCode());
  346. }
  347. RpcEndExcept
  348. Clean0:
  349. NOTHING;
  350. } except(EXCEPTION_EXECUTE_HANDLER) {
  351. Status = CR_FAILURE;
  352. }
  353. return Status;
  354. } // CM_Setup_DevNode_Ex
  355. CONFIGRET
  356. CM_Disable_DevNode_Ex(
  357. IN DEVINST dnDevInst,
  358. IN ULONG ulFlags,
  359. IN HMACHINE hMachine
  360. )
  361. /*++
  362. Routine Description:
  363. This routine disables a device instance.
  364. Parameters:
  365. dnDevNode Supplies the handle of the device instance to be disabled.
  366. ulFlags May be one of CM_DISABLE_BITS.
  367. Return Value:
  368. If the function succeeds, the return value is CR_SUCCESS.
  369. If the function fails, the return value is one of the following:
  370. CR_INVALID_FLAG,
  371. CR_NOT_DISABLEABLE, or
  372. CR_INVALID_DEVNODE.
  373. (Note, Windows 95 also may return CR_NOT_AT_APPY_TIME.)
  374. --*/
  375. {
  376. CONFIGRET Status = CR_SUCCESS;
  377. WCHAR DeviceID[MAX_DEVICE_ID_LEN];
  378. ULONG ulLen = MAX_DEVICE_ID_LEN;
  379. PVOID hStringTable = NULL;
  380. handle_t hBinding = NULL;
  381. BOOL Success;
  382. PNP_VETO_TYPE vetoType, *pVetoType;
  383. WCHAR vetoName[MAX_DEVICE_ID_LEN], *pszVetoName;
  384. ULONG ulNameLength;
  385. try {
  386. //
  387. // validate parameters
  388. //
  389. if (INVALID_FLAGS(ulFlags, CM_DISABLE_BITS)) {
  390. Status = CR_INVALID_FLAG;
  391. goto Clean0;
  392. }
  393. if (dnDevInst == 0) {
  394. Status = CR_INVALID_DEVINST;
  395. goto Clean0;
  396. }
  397. //
  398. // setup rpc binding handle and string table handle
  399. //
  400. if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
  401. Status = CR_FAILURE;
  402. goto Clean0;
  403. }
  404. //
  405. // retrieve the device instance ID string associated with the devinst
  406. //
  407. Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
  408. if (Success == FALSE || INVALID_DEVINST(DeviceID)) {
  409. Status = CR_INVALID_DEVINST;
  410. goto Clean0;
  411. }
  412. if (ulFlags & CM_DISABLE_UI_NOT_OK) {
  413. vetoType = PNP_VetoTypeUnknown;
  414. pVetoType = &vetoType;
  415. vetoName[0] = L'\0';
  416. pszVetoName = &vetoName[0];
  417. ulNameLength = MAX_DEVICE_ID_LEN;
  418. } else {
  419. pVetoType = NULL;
  420. pszVetoName = NULL;
  421. ulNameLength = 0;
  422. }
  423. RpcTryExcept {
  424. //
  425. // call rpc service entry point
  426. //
  427. Status = PNP_DisableDevInst(
  428. hBinding, // rpc binding handle
  429. DeviceID, // device instance to create
  430. pVetoType,
  431. pszVetoName,
  432. ulNameLength,
  433. ulFlags); // requested minor action (not used)
  434. }
  435. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  436. KdPrintEx((DPFLTR_PNPMGR_ID,
  437. DBGF_ERRORS,
  438. "PNP_DisableDevInst caused an exception (%d)\n",
  439. RpcExceptionCode()));
  440. Status = MapRpcExceptionToCR(RpcExceptionCode());
  441. }
  442. RpcEndExcept
  443. Clean0:
  444. NOTHING;
  445. } except(EXCEPTION_EXECUTE_HANDLER) {
  446. Status = CR_FAILURE;
  447. }
  448. return Status;
  449. } // CM_Disable_DevNode_Ex
  450. CONFIGRET
  451. CM_Enable_DevNode_Ex(
  452. IN DEVINST dnDevInst,
  453. IN ULONG ulFlags,
  454. IN HMACHINE hMachine
  455. )
  456. /*++
  457. Routine Description:
  458. This routine enables a device instance.
  459. Parameters:
  460. dnDevNode Supplies the handle of the device instance to enable.
  461. ulFlags Must be zero.
  462. Return Value:
  463. If the function succeeds, the return value is CR_SUCCESS.
  464. If the function fails, the return value is one of the following:
  465. CR_INVALID_FLAG or
  466. CR_INVALID_DEVNODE.
  467. (Note, Windows 95 also may return CR_NOT_AT_APPY_TIME.)
  468. --*/
  469. {
  470. CONFIGRET Status = CR_SUCCESS;
  471. WCHAR DeviceID[MAX_DEVICE_ID_LEN];
  472. ULONG ulLen = MAX_DEVICE_ID_LEN;
  473. PVOID hStringTable = NULL;
  474. handle_t hBinding = NULL;
  475. BOOL Success;
  476. try {
  477. //
  478. // validate parameters
  479. //
  480. if (INVALID_FLAGS(ulFlags, 0)) {
  481. Status = CR_INVALID_FLAG;
  482. goto Clean0;
  483. }
  484. if (dnDevInst == 0) {
  485. Status = CR_INVALID_DEVINST;
  486. goto Clean0;
  487. }
  488. //
  489. // setup rpc binding handle and string table handle
  490. //
  491. if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
  492. Status = CR_FAILURE;
  493. goto Clean0;
  494. }
  495. //
  496. // retrieve the device instance ID string associated with the devinst
  497. //
  498. Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
  499. if (Success == FALSE || INVALID_DEVINST(DeviceID)) {
  500. Status = CR_INVALID_DEVINST;
  501. goto Clean0;
  502. }
  503. RpcTryExcept {
  504. //
  505. // call rpc service entry point
  506. //
  507. Status = PNP_DeviceInstanceAction(
  508. hBinding, // rpc binding handle
  509. PNP_DEVINST_ENABLE, // requested major action - ENABLE
  510. ulFlags, // requested minor action (not used)
  511. DeviceID, // device instance to create
  512. NULL); // (not used)
  513. }
  514. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  515. KdPrintEx((DPFLTR_PNPMGR_ID,
  516. DBGF_ERRORS,
  517. "PNP_DeviceInstanceAction caused an exception (%d)\n",
  518. RpcExceptionCode()));
  519. Status = MapRpcExceptionToCR(RpcExceptionCode());
  520. }
  521. RpcEndExcept
  522. Clean0:
  523. NOTHING;
  524. } except(EXCEPTION_EXECUTE_HANDLER) {
  525. Status = CR_FAILURE;
  526. }
  527. return Status;
  528. } // CM_Enable_DevNode_Ex
  529. CONFIGRET
  530. CM_Get_DevNode_Status_Ex(
  531. OUT PULONG pulStatus,
  532. OUT PULONG pulProblemNumber,
  533. IN DEVINST dnDevInst,
  534. IN ULONG ulFlags,
  535. IN HMACHINE hMachine
  536. )
  537. /*++
  538. Routine Description:
  539. This routine retrieves the status of a device instance.
  540. Parameters:
  541. pulStatus Supplies the address of the variable that receives the
  542. status flag of the device instance. Can be a combination
  543. of the DN_* values.
  544. pulProblemNumber Supplies the address of the variable that receives an
  545. identifier indicating the problem. Can be one of the
  546. CM_PROB_* values.
  547. dnDevNode Supplies the handle of the device instance for which
  548. to retrieve status.
  549. ulFlags Must be zero.
  550. Return Value:
  551. If the function succeeds, the return value is CR_SUCCESS.
  552. If the function fails, the return value is one of the following:
  553. CR_INVALID_DEVNODE,
  554. CR_INVALID_FLAG, or
  555. CR_INVALID_POINTER.
  556. --*/
  557. {
  558. CONFIGRET Status = CR_SUCCESS;
  559. WCHAR DeviceID [MAX_DEVICE_ID_LEN];
  560. ULONG ulLen = MAX_DEVICE_ID_LEN;
  561. PVOID hStringTable = NULL;
  562. handle_t hBinding = NULL;
  563. BOOL Success;
  564. try {
  565. //
  566. // validate parameters
  567. //
  568. if (dnDevInst == 0) {
  569. Status = CR_INVALID_DEVINST;
  570. goto Clean0;
  571. }
  572. if ((!ARGUMENT_PRESENT(pulStatus)) ||
  573. (!ARGUMENT_PRESENT(pulProblemNumber))) {
  574. Status = CR_INVALID_POINTER;
  575. goto Clean0;
  576. }
  577. if (INVALID_FLAGS(ulFlags, 0)) {
  578. Status = CR_INVALID_FLAG;
  579. goto Clean0;
  580. }
  581. //
  582. // setup rpc binding handle and string table handle
  583. //
  584. if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
  585. Status = CR_FAILURE;
  586. goto Clean0;
  587. }
  588. //
  589. // retrieve the device instance ID string associated with the devinst
  590. //
  591. Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
  592. if (Success == FALSE) {
  593. Status = CR_INVALID_DEVINST;
  594. goto Clean0;
  595. }
  596. RpcTryExcept {
  597. //
  598. // call rpc service entry point
  599. //
  600. Status = PNP_GetDeviceStatus(
  601. hBinding, // rpc binding handle
  602. DeviceID, // device instance to get status for
  603. pulStatus, // return StatusFlags here
  604. pulProblemNumber, // return Problem here
  605. ulFlags); // (not used)
  606. }
  607. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  608. KdPrintEx((DPFLTR_PNPMGR_ID,
  609. DBGF_ERRORS,
  610. "PNP_GetDeviceStatus caused an exception (%d)\n",
  611. RpcExceptionCode()));
  612. Status = MapRpcExceptionToCR(RpcExceptionCode());
  613. }
  614. RpcEndExcept
  615. Clean0:
  616. NOTHING;
  617. } except(EXCEPTION_EXECUTE_HANDLER) {
  618. Status = CR_FAILURE;
  619. }
  620. return Status;
  621. } // CM_Get_DevNode_Status_Ex
  622. CONFIGRET
  623. CM_Set_DevNode_Problem_Ex(
  624. IN DEVINST dnDevInst,
  625. IN ULONG ulProblem,
  626. IN ULONG ulFlags,
  627. IN HMACHINE hMachine
  628. )
  629. /*++
  630. Routine Description:
  631. This routine clears or set the problem of a device instance.
  632. Parameters:
  633. dnDevNode Supplies the handle of the device instance for which
  634. to set the problem.
  635. ulProblem Supplies the new problem value. Can be one of the
  636. CM_PROB_* values. If zero, the problem is cleared.
  637. ulFlags Must be zero.
  638. Return Value:
  639. If the function succeeds, the return value is CR_SUCCESS.
  640. If the function fails, the return value is one of the following:
  641. CR_INVALID_DEVNODE,
  642. CR_INVALID_FLAG.
  643. --*/
  644. {
  645. CONFIGRET Status = CR_SUCCESS;
  646. WCHAR DeviceID[MAX_DEVICE_ID_LEN];
  647. PVOID hStringTable = NULL;
  648. handle_t hBinding = NULL;
  649. ULONG ulLen = MAX_DEVICE_ID_LEN;
  650. BOOL Success;
  651. try {
  652. //
  653. // validate parameters
  654. //
  655. if (dnDevInst == 0) {
  656. Status = CR_INVALID_DEVINST;
  657. goto Clean0;
  658. }
  659. if (INVALID_FLAGS(ulFlags, CM_SET_DEVNODE_PROBLEM_BITS)) {
  660. Status = CR_INVALID_FLAG;
  661. goto Clean0;
  662. }
  663. //
  664. // setup rpc binding handle and string table handle
  665. //
  666. if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
  667. Status = CR_FAILURE;
  668. goto Clean0;
  669. }
  670. //
  671. // retrieve the device instance ID string associated with the devinst
  672. //
  673. Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
  674. if (Success == FALSE) {
  675. Status = CR_INVALID_DEVINST;
  676. goto Clean0;
  677. }
  678. RpcTryExcept {
  679. //
  680. // call rpc service entry point
  681. //
  682. Status = PNP_SetDeviceProblem(
  683. hBinding, // rpc binding handle
  684. DeviceID, // device instance
  685. ulProblem, // specifies new Problem
  686. ulFlags); // (not used)
  687. }
  688. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  689. KdPrintEx((DPFLTR_PNPMGR_ID,
  690. DBGF_ERRORS,
  691. "PNP_SetDeviceProblem caused an exception (%d)\n",
  692. RpcExceptionCode()));
  693. Status = MapRpcExceptionToCR(RpcExceptionCode());
  694. }
  695. RpcEndExcept
  696. Clean0:
  697. NOTHING;
  698. } except(EXCEPTION_EXECUTE_HANDLER) {
  699. Status = CR_FAILURE;
  700. }
  701. return Status;
  702. } // CM_Set_DevNode_Problem_Ex
  703. CONFIGRET
  704. CM_Reenumerate_DevNode_Ex(
  705. IN DEVINST dnDevInst,
  706. IN ULONG ulFlags,
  707. IN HMACHINE hMachine
  708. )
  709. /*++
  710. Routine Description:
  711. This routine causes the specified device instance to be enumerated
  712. (if it is enumerable).
  713. Parameters:
  714. dnDevNode Supplies the handle of the device instance to be enumerated.
  715. ulFlags Must be zero.
  716. Return Value:
  717. If the function succeeds, the return value is CR_SUCCESS.
  718. If the function fails, the return value is CR_INVALID_FLAG (i.e., the
  719. function does not fail). The device instance is not checked for validity.
  720. --*/
  721. {
  722. CONFIGRET Status = CR_SUCCESS;
  723. WCHAR DeviceID [MAX_DEVICE_ID_LEN];
  724. PVOID hStringTable = NULL;
  725. handle_t hBinding = NULL;
  726. ULONG ulLen = MAX_DEVICE_ID_LEN;
  727. BOOL Success;
  728. try {
  729. //
  730. // validate parameters
  731. //
  732. if (INVALID_FLAGS(ulFlags, CM_REENUMERATE_BITS)) {
  733. Status = CR_INVALID_FLAG;
  734. goto Clean0;
  735. }
  736. if (dnDevInst == 0) {
  737. Status = CR_INVALID_DEVINST;
  738. goto Clean0;
  739. }
  740. //
  741. // setup rpc binding handle and string table handle
  742. //
  743. if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
  744. Status = CR_FAILURE;
  745. goto Clean0;
  746. }
  747. //
  748. // retrieve the device instance ID string associated with the devinst
  749. //
  750. Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
  751. if (Success == FALSE || INVALID_DEVINST(DeviceID)) {
  752. Status = CR_INVALID_DEVINST;
  753. goto Clean0;
  754. }
  755. RpcTryExcept {
  756. //
  757. // call rpc service entry point
  758. //
  759. Status = PNP_DeviceInstanceAction(
  760. hBinding, // rpc binding handle
  761. PNP_DEVINST_REENUMERATE, // requested major action-REMOVESUBTREE
  762. ulFlags, // requested minor action
  763. DeviceID, // device instance subtree to remove
  764. NULL); // (not used)
  765. }
  766. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  767. KdPrintEx((DPFLTR_PNPMGR_ID,
  768. DBGF_ERRORS,
  769. "PNP_DeviceInstanceAction caused an exception (%d)\n",
  770. RpcExceptionCode()));
  771. Status = MapRpcExceptionToCR(RpcExceptionCode());
  772. }
  773. RpcEndExcept
  774. Clean0:
  775. NOTHING;
  776. } except(EXCEPTION_EXECUTE_HANDLER) {
  777. Status = CR_FAILURE;
  778. }
  779. return Status;
  780. } // CM_Reenumerate_DevNode_Ex
  781. CONFIGRET
  782. CM_Query_And_Remove_SubTree_ExW(
  783. IN DEVINST dnAncestor,
  784. OUT PPNP_VETO_TYPE pVetoType,
  785. OUT LPWSTR pszVetoName,
  786. IN ULONG ulNameLength,
  787. IN ULONG ulFlags,
  788. IN HMACHINE hMachine
  789. )
  790. /*++
  791. Routine Description:
  792. This routine checks whether a device instance and its progeny can be
  793. removed. If the query isn't vetoed then a remove is done. The replaces
  794. the old CM_Query_Remove_SubTree followed by CM_Remove_SubTree.
  795. Parameters:
  796. dnAncestor Supplies the handle of the device instance at the root of
  797. the subtree to be removed.
  798. ulFlags Specifies whether UI should be presented for
  799. this action. Can be one of the following values:
  800. CM_REMOVE_UI_OK - OK to present UI for query-removal.
  801. CM_REMOVE_UI_NOT_OK - Don't present UI for query-removal.
  802. CM_REMOVE_NO_RESTART - Don't attempt to restart the devnode.
  803. Return Value:
  804. If the function succeeds, the return value is CR_SUCCESS.
  805. If the function fails, the return value is one of the following:
  806. CR_INVALID_DEVNODE,
  807. CR_INVALID_FLAG,
  808. CR_REMOVE_VETOED. (Windows 95 may also return CR_NOT_AT_APPY_TIME.)
  809. --*/
  810. {
  811. CONFIGRET Status = CR_SUCCESS;
  812. WCHAR pDeviceID [MAX_DEVICE_ID_LEN];
  813. PVOID hStringTable = NULL;
  814. handle_t hBinding = NULL;
  815. ULONG ulLen = MAX_DEVICE_ID_LEN;
  816. try {
  817. //
  818. // validate parameters
  819. //
  820. if (dnAncestor == 0) {
  821. Status = CR_INVALID_DEVINST;
  822. goto Clean0;
  823. }
  824. if (INVALID_FLAGS(ulFlags, CM_REMOVE_BITS)) {
  825. Status = CR_INVALID_FLAG;
  826. goto Clean0;
  827. }
  828. //
  829. // setup rpc binding handle and string table handle
  830. //
  831. if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
  832. Status = CR_FAILURE;
  833. goto Clean0;
  834. }
  835. //
  836. // retrieve the device instance ID string associated with the devinst
  837. //
  838. pSetupStringTableStringFromIdEx(hStringTable, dnAncestor,pDeviceID,&ulLen);
  839. ASSERT(pDeviceID && *pDeviceID && IsLegalDeviceId(pDeviceID));
  840. if (pDeviceID == NULL || INVALID_DEVINST(pDeviceID)) {
  841. Status = CR_INVALID_DEVINST;
  842. goto Clean0;
  843. }
  844. if (ulNameLength == 0) {
  845. pszVetoName = NULL;
  846. }
  847. if (pszVetoName != NULL) {
  848. *pszVetoName = L'\0';
  849. }
  850. if (pVetoType != NULL) {
  851. *pVetoType = PNP_VetoTypeUnknown;
  852. }
  853. RpcTryExcept {
  854. //
  855. // call rpc service entry point
  856. //
  857. Status = PNP_QueryRemove(
  858. hBinding, // rpc binding handle
  859. pDeviceID, // device instance subtree to remove
  860. pVetoType,
  861. pszVetoName,
  862. ulNameLength,
  863. ulFlags);
  864. }
  865. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  866. KdPrintEx((DPFLTR_PNPMGR_ID,
  867. DBGF_ERRORS,
  868. "PNP_QueryRemove caused an exception (%d)\n",
  869. RpcExceptionCode()));
  870. Status = MapRpcExceptionToCR(RpcExceptionCode());
  871. }
  872. RpcEndExcept
  873. Clean0:
  874. NOTHING;
  875. } except(EXCEPTION_EXECUTE_HANDLER) {
  876. Status = CR_FAILURE;
  877. }
  878. return Status;
  879. } // CM_Query_And_Remove_SubTree_ExW
  880. CONFIGRET
  881. CM_Query_Remove_SubTree_Ex(
  882. IN DEVINST dnAncestor,
  883. IN ULONG ulFlags,
  884. IN HMACHINE hMachine
  885. )
  886. /*++
  887. Routine Description:
  888. This routine checks whether a device instance and its progeny can be
  889. removed. This API must be called before calling CM_Remove_SubTree to
  890. make sure applications prepare for the removal of the device or to
  891. give the applications a chance to deny the request to remove the device.
  892. If the removal happens ?surprise style? (i.e., there?s no advanced
  893. warning or chance to veto), then this API should not be called before
  894. calling CM_Remove_SubTree.
  895. Parameters:
  896. dnAncestor Supplies the handle of the device instance at the root of
  897. the subtree to be removed.
  898. ulFlags Specifies whether UI should be presented for
  899. this action. Can be one of the following values:
  900. CM_QUERY_REMOVE_UI_OK - OK to present UI for query-removal.
  901. CM_QUERY_REMOVE_UI_NOT_OK -Don't present UI for query-removal.
  902. Return Value:
  903. ** PRESENTLY, ALWAYS RETURNS CR_CALL_NOT_IMPLEMENTED **
  904. If the function succeeds, the return value is CR_SUCCESS.
  905. If the function fails, the return value is one of the following:
  906. CR_INVALID_DEVNODE,
  907. CR_INVALID_FLAG,
  908. CR_REMOVE_VETOED. (Windows 95 may also return CR_NOT_AT_APPY_TIME.)
  909. --*/
  910. {
  911. UNREFERENCED_PARAMETER(dnAncestor);
  912. UNREFERENCED_PARAMETER(ulFlags);
  913. UNREFERENCED_PARAMETER(hMachine);
  914. return CR_CALL_NOT_IMPLEMENTED;
  915. } // CM_Query_Remove_SubTree_Ex
  916. CONFIGRET
  917. CM_Remove_SubTree_Ex(
  918. IN DEVINST dnAncestor,
  919. IN ULONG ulFlags,
  920. IN HMACHINE hMachine
  921. )
  922. /*++
  923. Routine Description:
  924. This routine removes a device instance and its children from the
  925. running system. This API notifies each device instance in the subtree
  926. of the dnAncestor parameter of the device's removal. (On Windows NT,
  927. this means that each driver/service controlling a device in this
  928. subtree receives a device removal notification.)
  929. Parameters:
  930. dnAncestor Supplies the handle of the device instance that is being removed.
  931. ulFlags Must be either CM_REMOVE_UI_OK or CM_REMOVE_UI_NOT_OK.
  932. Return Value:
  933. ** PRESENTLY, ALWAYS RETURNS CR_CALL_NOT_IMPLEMENTED **
  934. If the function succeeds, the return value is CR_SUCCESS.
  935. If the function fails, the return value is one of the following:
  936. CR_INVALID_DEVNODE or
  937. CR_INVALID_FLAG.
  938. (Windows 95 may also return CR_NOT_AT_APPY_TIME.)
  939. --*/
  940. {
  941. UNREFERENCED_PARAMETER(dnAncestor);
  942. UNREFERENCED_PARAMETER(ulFlags);
  943. UNREFERENCED_PARAMETER(hMachine);
  944. return CR_CALL_NOT_IMPLEMENTED;
  945. } // CM_Remove_SubTree_Ex
  946. CONFIGRET
  947. CM_Uninstall_DevNode_Ex(
  948. IN DEVNODE dnDevInst,
  949. IN ULONG ulFlags,
  950. IN HMACHINE hMachine
  951. )
  952. /*++
  953. Routine Description:
  954. This routine uninstalls a device instance (i.e., deletes its registry
  955. key(s) in the Enum branch). This API can only be called for phantom
  956. device instances, and the handle supplied is invalid after the call.
  957. This API does not attempt to delete all possible storage locations
  958. associated with the device instance. It will do a recursive delete on
  959. the devnode key, so that any subkeys will be removed. It will also
  960. delete the devnode key (and any subkeys) located in the Enum branch
  961. of each hardware profile. It will not delete any software keys or user
  962. keys (CM_Delete_DevNode_Key must be called to do that before calling
  963. this API).
  964. Parameters:
  965. dnPhantom Handle of a phantom device instance to uninstall. This
  966. handle is typically retrieved by a call to CM_Locate_DevNode
  967. or CM_Create_DevNode.
  968. ulFlags Must be zero.
  969. Return Value:
  970. If the function succeeds, the return value is CR_SUCCESS.
  971. If the function fails, the return value is one of the following:
  972. CR_INVALID_DEVNODE,
  973. CR_INVALID_FLAG, or
  974. CR_REGISTRY_ERROR
  975. --*/
  976. {
  977. CONFIGRET Status = CR_SUCCESS;
  978. PVOID hStringTable = NULL;
  979. handle_t hBinding = NULL;
  980. ULONG ulLen = MAX_DEVICE_ID_LEN;
  981. WCHAR szParentKey[MAX_CM_PATH], szChildKey[MAX_CM_PATH],
  982. DeviceID[MAX_DEVICE_ID_LEN];
  983. BOOL Success;
  984. try {
  985. //
  986. // validate parameters
  987. //
  988. if (dnDevInst == 0) {
  989. Status = CR_INVALID_DEVINST;
  990. goto Clean0;
  991. }
  992. if (INVALID_FLAGS(ulFlags, 0)) {
  993. Status = CR_INVALID_FLAG;
  994. goto Clean0;
  995. }
  996. //
  997. // setup rpc binding handle and string table handle
  998. //
  999. if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
  1000. Status = CR_FAILURE;
  1001. goto Clean0;
  1002. }
  1003. //
  1004. // retrieve the device instance ID string associated with the devinst
  1005. //
  1006. Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
  1007. if (Success == FALSE || INVALID_DEVINST(DeviceID)) {
  1008. Status = CR_INVALID_DEVINST;
  1009. goto Clean0;
  1010. }
  1011. RpcTryExcept {
  1012. //
  1013. // call rpc service entry point
  1014. //
  1015. Status = PNP_UninstallDevInst(
  1016. hBinding, // rpc binding handle
  1017. DeviceID, // device instance to uninstall
  1018. ulFlags); // (unused)
  1019. }
  1020. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  1021. KdPrintEx((DPFLTR_PNPMGR_ID,
  1022. DBGF_ERRORS,
  1023. "PNP_UninstallDevInst caused an exception (%d)\n",
  1024. RpcExceptionCode()));
  1025. Status = MapRpcExceptionToCR(RpcExceptionCode());
  1026. }
  1027. RpcEndExcept
  1028. //------------------------------------------------------------------
  1029. // after deleting the main hw key and the config specific hw keys,
  1030. // cleanup the user hw key, which can only be done on the client
  1031. // side.
  1032. //------------------------------------------------------------------
  1033. //
  1034. // form the user hardware registry key path
  1035. //
  1036. Status = GetDevNodeKeyPath(hBinding, DeviceID,
  1037. CM_REGISTRY_HARDWARE | CM_REGISTRY_USER,
  1038. 0, szParentKey, szChildKey);
  1039. if (Status != CR_SUCCESS) {
  1040. goto Clean0;
  1041. }
  1042. //
  1043. // delete the specified private user key
  1044. //
  1045. Status = DeletePrivateKey(HKEY_CURRENT_USER, szParentKey, szChildKey);
  1046. Clean0:
  1047. NOTHING;
  1048. } except(EXCEPTION_EXECUTE_HANDLER) {
  1049. Status = CR_FAILURE;
  1050. }
  1051. return Status;
  1052. } // CM_Uninstall_DevNode_Ex
  1053. CONFIGRET
  1054. CM_Request_Device_Eject_ExW(
  1055. IN DEVNODE dnDevInst,
  1056. OUT PPNP_VETO_TYPE pVetoType,
  1057. OUT LPWSTR pszVetoName,
  1058. IN ULONG ulNameLength,
  1059. IN ULONG ulFlags,
  1060. IN HMACHINE hMachine
  1061. )
  1062. /*++
  1063. Routine Description:
  1064. Parameters:
  1065. dnDevInst Handle of a device instance. This handle is typically
  1066. retrieved by a call to CM_Locate_DevNode or CM_Create_DevNode.
  1067. ulFlags Must be zero.
  1068. Return Value:
  1069. If the function succeeds, the return value is CR_SUCCESS.
  1070. If the function fails, the return value is one of the following:
  1071. CR_INVALID_DEVNODE,
  1072. CR_INVALID_FLAG, or
  1073. CR_REGISTRY_ERROR
  1074. --*/
  1075. {
  1076. CONFIGRET Status = CR_SUCCESS;
  1077. PVOID hStringTable = NULL;
  1078. handle_t hBinding = NULL;
  1079. ULONG ulLen = MAX_DEVICE_ID_LEN;
  1080. WCHAR DeviceID[MAX_DEVICE_ID_LEN];
  1081. BOOL Success;
  1082. try {
  1083. //
  1084. // validate parameters
  1085. //
  1086. if (ulNameLength == 0) {
  1087. pszVetoName = NULL;
  1088. }
  1089. if (pszVetoName != NULL) {
  1090. *pszVetoName = L'\0';
  1091. }
  1092. if (pVetoType != NULL) {
  1093. *pVetoType = PNP_VetoTypeUnknown;
  1094. }
  1095. if (dnDevInst == 0) {
  1096. Status = CR_INVALID_DEVINST;
  1097. goto Clean0;
  1098. }
  1099. //
  1100. // no flags are currently valid
  1101. //
  1102. if (INVALID_FLAGS(ulFlags, 0)) {
  1103. Status = CR_INVALID_FLAG;
  1104. goto Clean0;
  1105. }
  1106. //
  1107. // setup rpc binding handle and string table handle
  1108. //
  1109. if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
  1110. Status = CR_FAILURE;
  1111. goto Clean0;
  1112. }
  1113. //
  1114. // retrieve the device instance ID string associated with the devinst
  1115. //
  1116. Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
  1117. if (Success == FALSE || INVALID_DEVINST(DeviceID)) {
  1118. Status = CR_INVALID_DEVINST;
  1119. goto Clean0;
  1120. }
  1121. RpcTryExcept {
  1122. //
  1123. // call rpc service entry point
  1124. //
  1125. Status = PNP_RequestDeviceEject(
  1126. hBinding, // rpc binding handle
  1127. DeviceID, // device instance subtree to remove
  1128. pVetoType,
  1129. pszVetoName,
  1130. ulNameLength,
  1131. ulFlags);
  1132. }
  1133. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  1134. KdPrintEx((DPFLTR_PNPMGR_ID,
  1135. DBGF_ERRORS,
  1136. "PNP_RequestDeviceEject caused an exception (%d)\n",
  1137. RpcExceptionCode()));
  1138. Status = MapRpcExceptionToCR(RpcExceptionCode());
  1139. }
  1140. RpcEndExcept
  1141. Clean0:
  1142. NOTHING;
  1143. } except(EXCEPTION_EXECUTE_HANDLER) {
  1144. Status = CR_FAILURE;
  1145. }
  1146. return Status;
  1147. } // CM_Request_Device_Eject_ExW
  1148. CONFIGRET
  1149. CM_Add_ID_ExW(
  1150. IN DEVINST dnDevInst,
  1151. IN PWSTR pszID,
  1152. IN ULONG ulFlags,
  1153. IN HMACHINE hMachine
  1154. )
  1155. /*++
  1156. Routine Description:
  1157. This routine adds a device ID to a device instance's HardwareID or
  1158. CompatibleIDs list.
  1159. Parameters:
  1160. dnDevInst Handle of a device instance. This handle is typically
  1161. retrieved by a call to CM_Locate_DevNode or CM_Create_DevNode.
  1162. pszID Supplies a pointer to a NULL-terminated string specifying
  1163. the ID to be added.
  1164. ulFlags Supplies flags for the ID. May be one of the following values:
  1165. ID Type Flags:
  1166. CM_ADD_ID_HARDWARE The specified ID is a hardware ID. Add
  1167. it to the device instance's HardwareID
  1168. list.
  1169. CM_ADD_ID_COMPATIBLE The specified ID is a compatible ID.
  1170. Add it to the device instance's
  1171. CompatibleIDs list.
  1172. Return Value:
  1173. If the function succeeds, the return value is CR_SUCCESS.
  1174. If the function fails, the return value is a CR error code.
  1175. --*/
  1176. {
  1177. CONFIGRET Status = CR_SUCCESS;
  1178. WCHAR DeviceID[MAX_DEVICE_ID_LEN];
  1179. PVOID hStringTable = NULL;
  1180. handle_t hBinding = NULL;
  1181. ULONG ulLen = MAX_DEVICE_ID_LEN;
  1182. BOOL Success;
  1183. try {
  1184. //
  1185. // validate parameters
  1186. //
  1187. if (dnDevInst == 0) {
  1188. Status = CR_INVALID_DEVINST;
  1189. goto Clean0;
  1190. }
  1191. if (!ARGUMENT_PRESENT(pszID)) {
  1192. Status = CR_INVALID_POINTER;
  1193. goto Clean0;
  1194. }
  1195. if (INVALID_FLAGS(ulFlags, CM_ADD_ID_BITS)) {
  1196. Status = CR_INVALID_FLAG;
  1197. goto Clean0;
  1198. }
  1199. //
  1200. // setup rpc binding handle and string table handle
  1201. //
  1202. if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
  1203. Status = CR_FAILURE;
  1204. goto Clean0;
  1205. }
  1206. //
  1207. // retrieve the device instance ID string associated with the devinst
  1208. //
  1209. Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
  1210. if (Success == FALSE || INVALID_DEVINST(DeviceID)) {
  1211. Status = CR_INVALID_DEVINST;
  1212. goto Clean0;
  1213. }
  1214. RpcTryExcept {
  1215. //
  1216. // call rpc service entry point
  1217. //
  1218. Status = PNP_AddID(
  1219. hBinding, // rpc binding handle
  1220. DeviceID, // device instance
  1221. pszID, // id to add
  1222. ulFlags); // hardware or compatible
  1223. }
  1224. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  1225. KdPrintEx((DPFLTR_PNPMGR_ID,
  1226. DBGF_ERRORS,
  1227. "PNP_AddID caused an exception (%d)\n",
  1228. RpcExceptionCode()));
  1229. Status = MapRpcExceptionToCR(RpcExceptionCode());
  1230. }
  1231. RpcEndExcept
  1232. Clean0:
  1233. NOTHING;
  1234. } except(EXCEPTION_EXECUTE_HANDLER) {
  1235. Status = CR_FAILURE;
  1236. }
  1237. return Status;
  1238. } // CM_Add_ID_ExW
  1239. CMAPI
  1240. CONFIGRET
  1241. CM_Register_Device_Driver_Ex(
  1242. IN DEVINST dnDevInst,
  1243. IN ULONG ulFlags,
  1244. IN HMACHINE hMachine
  1245. )
  1246. /*++
  1247. Routine Description:
  1248. This routine registers the device driver for the specified device.
  1249. Parameters:
  1250. dnDevInst Handle of a device instance. This handle is typically
  1251. retrieved by a call to CM_Locate_DevNode or CM_Create_DevNode.
  1252. ulFlags Supplies flags for register the driver. May be one of the
  1253. following values:
  1254. CM_REGISTER_DEVICE_DRIVER_STATIC
  1255. CM_REGISTER_DEVICE_DRIVER_DISABLEABLE
  1256. CM_REGISTER_DEVICE_DRIVER_REMOVABLE
  1257. Return Value:
  1258. If the function succeeds, the return value is CR_SUCCESS.
  1259. If the function fails, the return value is a CR error code.
  1260. --*/
  1261. {
  1262. CONFIGRET Status = CR_SUCCESS;
  1263. WCHAR DeviceID [MAX_DEVICE_ID_LEN];
  1264. PVOID hStringTable = NULL;
  1265. handle_t hBinding = NULL;
  1266. ULONG ulLen = MAX_DEVICE_ID_LEN;
  1267. BOOL Success;
  1268. try {
  1269. //
  1270. // validate parameters
  1271. //
  1272. if (dnDevInst == 0) {
  1273. Status = CR_INVALID_DEVINST;
  1274. goto Clean0;
  1275. }
  1276. if (INVALID_FLAGS(ulFlags, CM_REGISTER_DEVICE_DRIVER_BITS)) {
  1277. Status = CR_INVALID_FLAG;
  1278. goto Clean0;
  1279. }
  1280. //
  1281. // setup rpc binding handle and string table handle
  1282. //
  1283. if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
  1284. Status = CR_FAILURE;
  1285. goto Clean0;
  1286. }
  1287. //
  1288. // retrieve the device instance ID string associated with the devinst
  1289. //
  1290. Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
  1291. if (Success == FALSE || INVALID_DEVINST(DeviceID)) {
  1292. Status = CR_INVALID_DEVINST;
  1293. goto Clean0;
  1294. }
  1295. RpcTryExcept {
  1296. //
  1297. // call rpc service entry point
  1298. //
  1299. Status = PNP_RegisterDriver(
  1300. hBinding, // rpc binding handle
  1301. DeviceID, // device instance
  1302. ulFlags); // hardware or compatible
  1303. }
  1304. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  1305. KdPrintEx((DPFLTR_PNPMGR_ID,
  1306. DBGF_ERRORS,
  1307. "PNP_RegisterDriver caused an exception (%d)\n",
  1308. RpcExceptionCode()));
  1309. Status = MapRpcExceptionToCR(RpcExceptionCode());
  1310. }
  1311. RpcEndExcept
  1312. Clean0:
  1313. NOTHING;
  1314. } except(EXCEPTION_EXECUTE_HANDLER) {
  1315. Status = CR_FAILURE;
  1316. }
  1317. return Status;
  1318. } // CM_Register_Device_Driver_Ex
  1319. //-------------------------------------------------------------------
  1320. // Local Stubs
  1321. //-------------------------------------------------------------------
  1322. CONFIGRET
  1323. CM_Create_DevNodeW(
  1324. OUT PDEVINST pdnDevInst,
  1325. IN DEVINSTID_W pDeviceID,
  1326. IN DEVINST dnParent,
  1327. IN ULONG ulFlags
  1328. )
  1329. {
  1330. return CM_Create_DevNode_ExW(pdnDevInst, pDeviceID, dnParent,
  1331. ulFlags, NULL);
  1332. }
  1333. CONFIGRET
  1334. CM_Create_DevNodeA(
  1335. OUT PDEVINST pdnDevInst,
  1336. IN DEVINSTID_A pDeviceID,
  1337. IN DEVINST dnParent,
  1338. IN ULONG ulFlags
  1339. )
  1340. {
  1341. return CM_Create_DevNode_ExA(pdnDevInst, pDeviceID, dnParent,
  1342. ulFlags, NULL);
  1343. }
  1344. CONFIGRET
  1345. CM_Move_DevNode(
  1346. IN DEVINST dnFromDevInst,
  1347. IN DEVINST dnToDevInst,
  1348. IN ULONG ulFlags
  1349. )
  1350. {
  1351. return CM_Move_DevNode_Ex(dnFromDevInst, dnToDevInst, ulFlags, NULL);
  1352. }
  1353. CONFIGRET
  1354. CM_Setup_DevNode(
  1355. IN DEVINST dnDevInst,
  1356. IN ULONG ulFlags
  1357. )
  1358. {
  1359. return CM_Setup_DevNode_Ex(dnDevInst, ulFlags, NULL);
  1360. }
  1361. CONFIGRET
  1362. CM_Disable_DevNode(
  1363. IN DEVINST dnDevInst,
  1364. IN ULONG ulFlags
  1365. )
  1366. {
  1367. return CM_Disable_DevNode_Ex(dnDevInst, ulFlags, NULL);
  1368. }
  1369. CONFIGRET
  1370. CM_Enable_DevNode(
  1371. IN DEVINST dnDevInst,
  1372. IN ULONG ulFlags
  1373. )
  1374. {
  1375. return CM_Enable_DevNode_Ex(dnDevInst, ulFlags, NULL);
  1376. }
  1377. CONFIGRET
  1378. CM_Get_DevNode_Status(
  1379. OUT PULONG pulStatus,
  1380. OUT PULONG pulProblemNumber,
  1381. IN DEVINST dnDevInst,
  1382. IN ULONG ulFlags
  1383. )
  1384. {
  1385. return CM_Get_DevNode_Status_Ex(pulStatus, pulProblemNumber,
  1386. dnDevInst, ulFlags, NULL);
  1387. }
  1388. CONFIGRET
  1389. CM_Set_DevNode_Problem(
  1390. IN DEVINST dnDevInst,
  1391. IN ULONG ulProblem,
  1392. IN ULONG ulFlags
  1393. )
  1394. {
  1395. return CM_Set_DevNode_Problem_Ex(dnDevInst, ulProblem, ulFlags, NULL);
  1396. }
  1397. CONFIGRET
  1398. CM_Reenumerate_DevNode(
  1399. IN DEVINST dnDevInst,
  1400. IN ULONG ulFlags
  1401. )
  1402. {
  1403. return CM_Reenumerate_DevNode_Ex(dnDevInst, ulFlags, NULL);
  1404. }
  1405. CONFIGRET
  1406. CM_Query_And_Remove_SubTree(
  1407. IN DEVINST dnAncestor,
  1408. OUT PPNP_VETO_TYPE pVetoType,
  1409. OUT LPWSTR pszVetoName,
  1410. IN ULONG ulNameLength,
  1411. IN ULONG ulFlags
  1412. )
  1413. {
  1414. return CM_Query_And_Remove_SubTree_Ex( dnAncestor,
  1415. pVetoType,
  1416. pszVetoName,
  1417. ulNameLength,
  1418. ulFlags,
  1419. NULL);
  1420. }
  1421. CONFIGRET
  1422. CM_Query_And_Remove_SubTreeA(
  1423. IN DEVINST dnAncestor,
  1424. OUT PPNP_VETO_TYPE pVetoType,
  1425. OUT LPSTR pszVetoName,
  1426. IN ULONG ulNameLength,
  1427. IN ULONG ulFlags
  1428. )
  1429. {
  1430. return CM_Query_And_Remove_SubTree_ExA( dnAncestor,
  1431. pVetoType,
  1432. pszVetoName,
  1433. ulNameLength,
  1434. ulFlags,
  1435. NULL);
  1436. }
  1437. CONFIGRET
  1438. CM_Remove_SubTree(
  1439. IN DEVINST dnAncestor,
  1440. IN ULONG ulFlags
  1441. )
  1442. {
  1443. return CM_Remove_SubTree_Ex(dnAncestor, ulFlags, NULL);
  1444. }
  1445. CONFIGRET
  1446. CM_Uninstall_DevNode(
  1447. IN DEVNODE dnPhantom,
  1448. IN ULONG ulFlags
  1449. )
  1450. {
  1451. return CM_Uninstall_DevNode_Ex(dnPhantom, ulFlags, NULL);
  1452. }
  1453. CONFIGRET
  1454. CM_Add_IDW(
  1455. IN DEVINST dnDevInst,
  1456. IN PWSTR pszID,
  1457. IN ULONG ulFlags
  1458. )
  1459. {
  1460. return CM_Add_ID_ExW(dnDevInst, pszID, ulFlags, NULL);
  1461. }
  1462. CONFIGRET
  1463. CM_Add_IDA(
  1464. IN DEVINST dnDevInst,
  1465. IN PSTR pszID,
  1466. IN ULONG ulFlags
  1467. )
  1468. {
  1469. return CM_Add_ID_ExA(dnDevInst, pszID, ulFlags, NULL);
  1470. }
  1471. CMAPI
  1472. CONFIGRET
  1473. CM_Register_Device_Driver(
  1474. IN DEVINST dnDevInst,
  1475. IN ULONG ulFlags
  1476. )
  1477. {
  1478. return CM_Register_Device_Driver_Ex(dnDevInst, ulFlags, NULL);
  1479. }
  1480. CONFIGRET
  1481. CM_Query_Remove_SubTree(
  1482. IN DEVINST dnAncestor,
  1483. IN ULONG ulFlags
  1484. )
  1485. {
  1486. return CM_Query_Remove_SubTree_Ex(dnAncestor, ulFlags, NULL);
  1487. }
  1488. CONFIGRET
  1489. CM_Request_Device_EjectW(
  1490. IN DEVINST dnDevInst,
  1491. OUT PPNP_VETO_TYPE pVetoType,
  1492. OUT LPWSTR pszVetoName,
  1493. IN ULONG ulNameLength,
  1494. IN ULONG ulFlags
  1495. )
  1496. {
  1497. return CM_Request_Device_Eject_ExW(dnDevInst,
  1498. pVetoType,
  1499. pszVetoName,
  1500. ulNameLength,
  1501. ulFlags,
  1502. NULL);
  1503. }
  1504. CONFIGRET
  1505. CM_Request_Device_EjectA(
  1506. IN DEVNODE dnDevInst,
  1507. OUT PPNP_VETO_TYPE pVetoType,
  1508. OUT LPSTR pszVetoName,
  1509. IN ULONG ulNameLength,
  1510. IN ULONG ulFlags
  1511. )
  1512. {
  1513. return CM_Request_Device_Eject_ExA( dnDevInst,
  1514. pVetoType,
  1515. pszVetoName,
  1516. ulNameLength,
  1517. ulFlags,
  1518. NULL);
  1519. }
  1520. //-------------------------------------------------------------------
  1521. // ANSI STUBS
  1522. //-------------------------------------------------------------------
  1523. CONFIGRET
  1524. CM_Add_ID_ExA(
  1525. IN DEVINST dnDevInst,
  1526. IN PSTR pszID,
  1527. IN ULONG ulFlags,
  1528. IN HMACHINE hMachine
  1529. )
  1530. {
  1531. CONFIGRET Status = CR_SUCCESS;
  1532. PWSTR pUniID = NULL;
  1533. if (pSetupCaptureAndConvertAnsiArg(pszID, &pUniID) == NO_ERROR) {
  1534. Status = CM_Add_ID_ExW(dnDevInst,
  1535. pUniID,
  1536. ulFlags,
  1537. hMachine);
  1538. pSetupFree(pUniID);
  1539. } else {
  1540. Status = CR_INVALID_POINTER;
  1541. }
  1542. return Status;
  1543. } // CM_Add_ID_ExA
  1544. CONFIGRET
  1545. CM_Create_DevNode_ExA(
  1546. OUT PDEVINST pdnDevInst,
  1547. IN DEVINSTID_A pDeviceID,
  1548. IN DEVINST dnParent,
  1549. IN ULONG ulFlags,
  1550. IN HMACHINE hMachine
  1551. )
  1552. {
  1553. CONFIGRET Status = CR_SUCCESS;
  1554. PWSTR pUniDeviceID = NULL;
  1555. if (pSetupCaptureAndConvertAnsiArg(pDeviceID, &pUniDeviceID) == NO_ERROR) {
  1556. Status = CM_Create_DevNode_ExW(pdnDevInst,
  1557. pUniDeviceID,
  1558. dnParent,
  1559. ulFlags,
  1560. hMachine);
  1561. pSetupFree(pUniDeviceID);
  1562. } else {
  1563. Status = CR_INVALID_DEVICE_ID;
  1564. }
  1565. return Status;
  1566. } // CM_Create_DevNode_ExA
  1567. CONFIGRET
  1568. CM_Query_And_Remove_SubTree_ExA(
  1569. IN DEVINST dnAncestor,
  1570. OUT PPNP_VETO_TYPE pVetoType,
  1571. OUT LPSTR pszVetoName,
  1572. IN ULONG ulNameLength,
  1573. IN ULONG ulFlags,
  1574. IN HMACHINE hMachine
  1575. )
  1576. {
  1577. CONFIGRET Status = CR_SUCCESS;
  1578. PWSTR pUniVetoName = NULL;
  1579. ULONG ulAnsiBufferLen;
  1580. //
  1581. // validate essential parameters only
  1582. //
  1583. if ((!ARGUMENT_PRESENT(pszVetoName)) && (ulNameLength != 0)) {
  1584. return CR_INVALID_POINTER;
  1585. }
  1586. if (ulNameLength != 0) {
  1587. //
  1588. // pass a Unicode buffer instead and convert back to caller's
  1589. // ANSI buffer on return
  1590. //
  1591. pUniVetoName = pSetupMalloc(MAX_VETO_NAME_LENGTH*sizeof(WCHAR));
  1592. if (pUniVetoName == NULL) {
  1593. return CR_OUT_OF_MEMORY;
  1594. }
  1595. }
  1596. //
  1597. // call the wide version
  1598. //
  1599. Status = CM_Query_And_Remove_SubTree_ExW(dnAncestor,
  1600. pVetoType,
  1601. pUniVetoName,
  1602. MAX_VETO_NAME_LENGTH,
  1603. ulFlags,
  1604. hMachine);
  1605. //
  1606. // We should never return a veto name longer than MAX_VETO_NAME_LENGTH.
  1607. //
  1608. ASSERT(Status != CR_BUFFER_SMALL);
  1609. if (Status == CR_REMOVE_VETOED) {
  1610. //
  1611. // convert the unicode buffer to an ANSI string and copy to the caller's
  1612. // buffer
  1613. //
  1614. ulAnsiBufferLen = ulNameLength;
  1615. Status = PnPUnicodeToMultiByte(pUniVetoName,
  1616. (lstrlenW(pUniVetoName)+1)*sizeof(WCHAR),
  1617. pszVetoName,
  1618. &ulAnsiBufferLen);
  1619. }
  1620. if (pUniVetoName != NULL) {
  1621. pSetupFree(pUniVetoName);
  1622. }
  1623. return Status;
  1624. } // CM_Query_And_Remove_SubTree_ExA
  1625. CONFIGRET
  1626. CM_Request_Device_Eject_ExA(
  1627. IN DEVNODE dnDevInst,
  1628. OUT PPNP_VETO_TYPE pVetoType,
  1629. OUT LPSTR pszVetoName,
  1630. IN ULONG ulNameLength,
  1631. IN ULONG ulFlags,
  1632. IN HMACHINE hMachine
  1633. )
  1634. {
  1635. CONFIGRET Status = CR_SUCCESS;
  1636. PWSTR pUniVetoName = NULL;
  1637. ULONG ulAnsiBufferLen;
  1638. //
  1639. // validate essential parameters only
  1640. //
  1641. if ((!ARGUMENT_PRESENT(pszVetoName)) && (ulNameLength != 0)) {
  1642. return CR_INVALID_POINTER;
  1643. }
  1644. if (ulNameLength != 0) {
  1645. //
  1646. // pass a Unicode buffer instead and convert back to caller's
  1647. // ANSI buffer on return
  1648. //
  1649. pUniVetoName = pSetupMalloc(MAX_VETO_NAME_LENGTH*sizeof(WCHAR));
  1650. if (pUniVetoName == NULL) {
  1651. return CR_OUT_OF_MEMORY;
  1652. }
  1653. }
  1654. //
  1655. // call the wide version
  1656. //
  1657. Status = CM_Request_Device_Eject_ExW(dnDevInst,
  1658. pVetoType,
  1659. pUniVetoName,
  1660. MAX_VETO_NAME_LENGTH,
  1661. ulFlags,
  1662. hMachine);
  1663. //
  1664. // We should never return a veto name longer than MAX_VETO_NAME_LENGTH.
  1665. //
  1666. ASSERT(Status != CR_BUFFER_SMALL);
  1667. if (Status == CR_REMOVE_VETOED) {
  1668. //
  1669. // convert the unicode buffer to an ANSI string and copy to the caller's
  1670. // buffer
  1671. //
  1672. ulAnsiBufferLen = ulNameLength;
  1673. Status = PnPUnicodeToMultiByte(pUniVetoName,
  1674. (lstrlenW(pUniVetoName)+1)*sizeof(WCHAR),
  1675. pszVetoName,
  1676. &ulAnsiBufferLen);
  1677. }
  1678. if (pUniVetoName != NULL) {
  1679. pSetupFree(pUniVetoName);
  1680. }
  1681. return Status;
  1682. } // CM_Request_Device_Eject_ExA
  1683.