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.

1914 lines
52 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. misc.c
  5. Abstract:
  6. This module contains miscellaneous Configuration Manager API routines.
  7. CM_Get_Version
  8. CM_Is_Version_Available
  9. CM_Connect_Machine
  10. CM_Disconnect_Machine
  11. CM_Get_Global_State
  12. CM_Run_Detection
  13. CM_Query_Arbitrator_Free_Data
  14. CM_Query_Resource_Conflicts
  15. CM_Query_Arbitrator_Free_Size
  16. CMP_Report_LogOn
  17. CMP_Init_Detection
  18. CMP_WaitServicesAvailable
  19. CMP_WaitNoPendingInstallEvents
  20. CMP_GetBlockedDriverInfo
  21. Author:
  22. Paula Tomlinson (paulat) 6-20-1995
  23. Environment:
  24. User mode only.
  25. Revision History:
  26. 20-Jun-1995 paulat
  27. Creation and initial implementation.
  28. --*/
  29. //
  30. // includes
  31. //
  32. #include "precomp.h"
  33. #pragma hdrstop
  34. #include "cfgi.h"
  35. #include "pnpipc.h"
  36. //
  37. // global data
  38. //
  39. extern PVOID hLocalStringTable; // NOT MODIFIED BY THESE PROCEDURES
  40. extern WCHAR LocalMachineNameNetBIOS[]; // NOT MODIFIED BY THESE PROCEDURES
  41. extern WCHAR LocalMachineNameDnsFullyQualified[];// NOT MODIFIED BY THESE PROCEDURES
  42. #define NUM_LOGON_RETRIES 30
  43. //
  44. // Private prototypes
  45. //
  46. CONFIGRET
  47. IsRemoteServiceRunning(
  48. IN LPCWSTR UNCServerName,
  49. IN LPCWSTR ServiceName
  50. );
  51. WORD
  52. CM_Get_Version_Ex(
  53. IN HMACHINE hMachine
  54. )
  55. /*++
  56. Routine Description:
  57. This routine retrieves the version number of the Configuration Manager APIs.
  58. Arguments:
  59. hMachine - Machine handle returned from CM_Connect_Machine or NULL.
  60. Return value:
  61. The function returns the major revision number in the high byte and the
  62. minor revision number in the low byte. For example, version 4.0 of
  63. Configuration Manager returns 0x0400.
  64. --*/
  65. {
  66. CONFIGRET Status = CR_SUCCESS;
  67. WORD wVersion = (WORD)CFGMGR32_VERSION;
  68. handle_t hBinding = NULL;
  69. //
  70. // setup rpc binding handle
  71. //
  72. if (!PnPGetGlobalHandles(hMachine, NULL, &hBinding)) {
  73. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  74. return wVersion = 0;
  75. }
  76. //
  77. // No special privileges are required by the server
  78. //
  79. RpcTryExcept {
  80. //
  81. // call rpc service entry point
  82. //
  83. Status = PNP_GetVersion(
  84. hBinding, // rpc machine name
  85. &wVersion); // server side version
  86. }
  87. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  88. KdPrintEx((DPFLTR_PNPMGR_ID,
  89. DBGF_WARNINGS,
  90. "PNP_GetVersion caused an exception (%d)\n",
  91. RpcExceptionCode()));
  92. SetLastError(RpcExceptionCode());
  93. wVersion = 0;
  94. }
  95. RpcEndExcept
  96. return wVersion;
  97. } // CM_Get_Version_Ex
  98. BOOL
  99. CM_Is_Version_Available_Ex(
  100. IN WORD wVersion,
  101. IN HMACHINE hMachine
  102. )
  103. /*++
  104. Routine Description:
  105. This routine returns whether a specific version of the Configuration Manager
  106. APIs are available.
  107. Arguments:
  108. wVersion - Version to query.
  109. hMachine - Machine to connect to.
  110. Return value:
  111. The function returns TRUE if the version of the Configuration Manager APIs is
  112. equal to or greater than the specified version.
  113. --*/
  114. {
  115. handle_t hBinding = NULL;
  116. WORD wVersionInternal;
  117. //
  118. // version 0x0400 is available on all servers, by definition.
  119. //
  120. if (wVersion <= (WORD)0x0400) {
  121. return TRUE;
  122. }
  123. //
  124. // setup rpc binding handle
  125. //
  126. if (!PnPGetGlobalHandles(hMachine, NULL, &hBinding)) {
  127. return FALSE;
  128. }
  129. //
  130. // retrieve the internal server version.
  131. //
  132. if (!PnPGetVersion(hMachine, &wVersionInternal)) {
  133. return FALSE;
  134. }
  135. //
  136. // versions up to and including the internal server version are available.
  137. //
  138. return (wVersion <= wVersionInternal);
  139. } // CM_Is_Version_Available_Ex
  140. CONFIGRET
  141. CM_Connect_MachineW(
  142. IN PCWSTR UNCServerName,
  143. OUT PHMACHINE phMachine
  144. )
  145. /*++
  146. Routine Description:
  147. This routine connects to the machine specified and returns a handle that
  148. is then passed to future calls to the Ex versions of the CM routines.
  149. This allows callers to get device information on remote machines.
  150. Arguments:
  151. UNCServerName - Specifies the UNC name of the remote machine to connect to.
  152. phMachine - Specifies the address of a variable to receive a handle to
  153. the connected machine.
  154. Return value:
  155. If the function succeeds, it returns CR_SUCCESS, otherwise it returns one
  156. of the CR_* error codes.
  157. --*/
  158. {
  159. CONFIGRET Status = CR_SUCCESS;
  160. WORD wVersion = 0, wVersionInternal;
  161. PPNP_MACHINE pMachine = NULL;
  162. size_t UNCServerNameLen;
  163. try {
  164. //
  165. // validate parameters
  166. //
  167. if (!ARGUMENT_PRESENT(phMachine)) {
  168. Status = CR_INVALID_POINTER;
  169. goto Clean0;
  170. }
  171. *phMachine = NULL;
  172. //
  173. // if machine name specified, check for UNC format
  174. //
  175. if ((ARGUMENT_PRESENT(UNCServerName)) &&
  176. (UNCServerName[0] != L'\0')) {
  177. //
  178. // Check that the length in not any longer than the longest possible
  179. // name we can possibly save, including the NULL terminating
  180. // character.
  181. //
  182. if (FAILED(StringCchLength(
  183. UNCServerName,
  184. MAX_PATH + 3,
  185. &UNCServerNameLen))) {
  186. Status = CR_INVALID_MACHINENAME;
  187. goto Clean0;
  188. }
  189. ASSERT(UNCServerNameLen < (MAX_PATH + 3));
  190. //
  191. // Check that the machine name is a UNC name.
  192. //
  193. if ((UNCServerNameLen < 3) ||
  194. (UNCServerName[0] != L'\\') ||
  195. (UNCServerName[1] != L'\\')) {
  196. Status = CR_INVALID_MACHINENAME;
  197. goto Clean0;
  198. }
  199. }
  200. //
  201. // allocate memory for the machine structure and initialize it
  202. //
  203. pMachine = (PPNP_MACHINE)pSetupMalloc(sizeof(PNP_MACHINE));
  204. if(!pMachine) {
  205. Status = CR_OUT_OF_MEMORY;
  206. goto Clean0;
  207. }
  208. if ((!ARGUMENT_PRESENT(UNCServerName)) ||
  209. (UNCServerName[0] == L'\0') ||
  210. (!lstrcmpi(UNCServerName, LocalMachineNameNetBIOS)) ||
  211. (!lstrcmpi(UNCServerName, LocalMachineNameDnsFullyQualified))) {
  212. //----------------------------------------------------------
  213. // If no machine name was passed in or the machine name
  214. // matches the local name, use local machine info rather
  215. // than creating a new binding.
  216. //----------------------------------------------------------
  217. PnPGetGlobalHandles(NULL,
  218. &pMachine->hStringTable,
  219. &pMachine->hBindingHandle);
  220. if (!ARGUMENT_PRESENT(UNCServerName)) {
  221. if (FAILED(StringCchCopy(
  222. pMachine->szMachineName,
  223. SIZECHARS(pMachine->szMachineName),
  224. LocalMachineNameNetBIOS))) {
  225. Status = CR_INVALID_MACHINENAME;
  226. goto Clean0;
  227. }
  228. } else {
  229. if (FAILED(StringCchCopy(
  230. pMachine->szMachineName,
  231. SIZECHARS(pMachine->szMachineName),
  232. UNCServerName))) {
  233. Status = CR_INVALID_MACHINENAME;
  234. goto Clean0;
  235. }
  236. }
  237. } else {
  238. //
  239. // First, make sure that the RemoteRegistry service is running on
  240. // the remote machine, since RemoteRegistry is required for several
  241. // cfgmgr32/setupapi services.
  242. //
  243. Status = IsRemoteServiceRunning(UNCServerName,
  244. L"RemoteRegistry");
  245. if (Status != CR_SUCCESS) {
  246. goto Clean0;
  247. }
  248. //-------------------------------------------------------------
  249. // A remote machine name was specified so explicitly force a
  250. // new binding for this machine.
  251. //-------------------------------------------------------------
  252. pMachine->hBindingHandle =
  253. (PVOID)PNP_HANDLE_bind((PNP_HANDLE)UNCServerName);
  254. if (pMachine->hBindingHandle == NULL) {
  255. if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY) {
  256. Status = CR_OUT_OF_MEMORY;
  257. } else if (GetLastError() == ERROR_INVALID_COMPUTERNAME) {
  258. Status = CR_INVALID_MACHINENAME;
  259. } else {
  260. Status = CR_FAILURE;
  261. }
  262. goto Clean0;
  263. }
  264. //
  265. // initialize a string table for use with this connection to
  266. // the remote machine
  267. //
  268. pMachine->hStringTable = pSetupStringTableInitialize();
  269. if (pMachine->hStringTable == NULL) {
  270. Status = CR_OUT_OF_MEMORY;
  271. goto Clean0;
  272. }
  273. //
  274. // Add a priming string (see dll entrypt in main.c for details)
  275. //
  276. pSetupStringTableAddString(pMachine->hStringTable,
  277. PRIMING_STRING,
  278. STRTAB_CASE_SENSITIVE);
  279. //
  280. // save the machine name
  281. //
  282. if (FAILED(StringCchCopy(
  283. pMachine->szMachineName,
  284. SIZECHARS(pMachine->szMachineName),
  285. UNCServerName))) {
  286. Status = CR_INVALID_MACHINENAME;
  287. goto Clean0;
  288. }
  289. }
  290. //
  291. // test the binding by calling the simplest RPC call (good way
  292. // for the caller to know whether the service is actually
  293. // running)
  294. //
  295. //
  296. // No special privileges are required by the server
  297. //
  298. RpcTryExcept {
  299. //
  300. // call rpc service entry point
  301. //
  302. Status = PNP_GetVersion(
  303. pMachine->hBindingHandle,
  304. &wVersion);
  305. }
  306. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  307. KdPrintEx((DPFLTR_PNPMGR_ID,
  308. DBGF_WARNINGS,
  309. "PNP_GetVersion caused an exception (%d)\n",
  310. RpcExceptionCode()));
  311. Status = MapRpcExceptionToCR(RpcExceptionCode());
  312. }
  313. RpcEndExcept
  314. if (Status == CR_SUCCESS) {
  315. //
  316. // we got the standard version alright, now try to determine the
  317. // internal version of the server. initialize the version supplied
  318. // to the internal version of the client.
  319. //
  320. wVersionInternal = (WORD)CFGMGR32_VERSION_INTERNAL;
  321. //
  322. // No special privileges are required by the server
  323. //
  324. RpcTryExcept {
  325. //
  326. // call rpc service entry point
  327. //
  328. Status = PNP_GetVersionInternal(
  329. pMachine->hBindingHandle,
  330. &wVersionInternal);
  331. }
  332. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  333. //
  334. // rpc exception may occur if the interface does not exist on
  335. // the server, indicating a server version prior to NT 5.1.
  336. //
  337. KdPrintEx((DPFLTR_PNPMGR_ID,
  338. DBGF_WARNINGS,
  339. "PNP_GetVersionInternal caused an exception (%d)\n",
  340. RpcExceptionCode()));
  341. Status = MapRpcExceptionToCR(RpcExceptionCode());
  342. }
  343. RpcEndExcept
  344. if (Status == CR_SUCCESS) {
  345. //
  346. // PNP_GetVersionInternal exists on NT 5.1 and later.
  347. //
  348. ASSERT(wVersionInternal >= (WORD)0x0501);
  349. //
  350. // use the real internal version of the server instead of the
  351. // static version returned by PNP_GetVersion.
  352. //
  353. wVersion = wVersionInternal;
  354. }
  355. //
  356. // no matter what happened while trying to retrieve the internal
  357. // version of the server, we were successful before this.
  358. //
  359. Status = CR_SUCCESS;
  360. }
  361. if (Status == CR_SUCCESS) {
  362. pMachine->ulSignature = (ULONG)MACHINE_HANDLE_SIGNATURE;
  363. pMachine->wVersion = wVersion;
  364. *phMachine = (HMACHINE)pMachine;
  365. }
  366. Clean0:
  367. NOTHING;
  368. } except(EXCEPTION_EXECUTE_HANDLER) {
  369. Status = CR_FAILURE;
  370. //
  371. // Reference the following variables so the compiler will respect
  372. // statement ordering w.r.t. their assignment.
  373. //
  374. pMachine = pMachine;
  375. }
  376. if ((Status != CR_SUCCESS) && (pMachine != NULL)) {
  377. pSetupFree(pMachine);
  378. }
  379. return Status;
  380. } // CM_Connect_MachineW
  381. CONFIGRET
  382. CM_Disconnect_Machine(
  383. IN HMACHINE hMachine
  384. )
  385. /*++
  386. Routine Description:
  387. This routine disconnects from a machine that was previously connected to
  388. with the CM_Connect_Machine call.
  389. Arguments:
  390. hMachine - Specifies a machine handle previously returned by a call to
  391. CM_Connect_Machine.
  392. Return value:
  393. If the function succeeds, it returns CR_SUCCESS, otherwise it returns one
  394. of the CR_* error codes.
  395. --*/
  396. {
  397. CONFIGRET Status = CR_SUCCESS;
  398. PPNP_MACHINE pMachine = NULL;
  399. try {
  400. //
  401. // validate parameters
  402. //
  403. if (hMachine == NULL) {
  404. Status = CR_INVALID_POINTER;
  405. goto Clean0;
  406. }
  407. pMachine = (PPNP_MACHINE)hMachine;
  408. if (pMachine->ulSignature != (ULONG)MACHINE_HANDLE_SIGNATURE) {
  409. Status = CR_INVALID_POINTER;
  410. goto Clean0;
  411. }
  412. //
  413. // only free the machine info if it's not the local machine
  414. //
  415. if (pMachine->hStringTable != hLocalStringTable) {
  416. //
  417. // free the rpc binding for this remote machine
  418. //
  419. PNP_HANDLE_unbind((PNP_HANDLE)pMachine->szMachineName,
  420. (handle_t)pMachine->hBindingHandle);
  421. //
  422. // release the string table
  423. //
  424. pSetupStringTableDestroy(pMachine->hStringTable);
  425. }
  426. //
  427. // invalidate the signature so we never try to free it again.
  428. //
  429. pMachine->ulSignature = 0;
  430. //
  431. // free the memory for the PNP_MACHINE struct
  432. //
  433. pSetupFree(pMachine);
  434. Clean0:
  435. NOTHING;
  436. } except(EXCEPTION_EXECUTE_HANDLER) {
  437. Status = CR_FAILURE;
  438. }
  439. return Status;
  440. } // CM_Disconnect_Machine
  441. CONFIGRET
  442. CM_Get_Global_State_Ex(
  443. OUT PULONG pulState,
  444. IN ULONG ulFlags,
  445. IN HMACHINE hMachine
  446. )
  447. /*++
  448. Routine Description:
  449. This routine retrieves the global state of the configuration manager.
  450. Parameters:
  451. pulState Supplies the address of the variable that receives the
  452. Configuration Managers state. May be a combination of the
  453. following values:
  454. Configuration Manager Global State Flags:
  455. CM_GLOBAL_STATE_CAN_DO_UI
  456. Can UI be initiated? [TBD: On NT, this may relate to
  457. whether anyone is logged in]
  458. CM_GLOBAL_STATE_SERVICES_AVAILABLE
  459. Are the CM APIs available? (on Windows NT this is always set)
  460. CM_GLOBAL_STATE_SHUTTING_DOWN
  461. The Configuration Manager is shutting down.
  462. [TBD: Does this only happen at shutdown/restart time?]
  463. CM_GLOBAL_STATE_DETECTION_PENDING
  464. The Configuration Manager is about to initiate some
  465. sort of detection.
  466. Windows 95 also defines the following additional flag:
  467. CM_GLOBAL_STATE_ON_BIG_STACK
  468. [TBD: What should this be defaulted to for NT?]
  469. ulFlags Not used, must be zero.
  470. Return Value:
  471. If the function succeeds, the return value is CR_SUCCESS.
  472. If the function fails, the return value is a CR error code.
  473. --*/
  474. {
  475. CONFIGRET Status = CR_SUCCESS;
  476. handle_t hBinding = NULL;
  477. try {
  478. //
  479. // validate parameters
  480. //
  481. if (!ARGUMENT_PRESENT(pulState)) {
  482. Status = CR_INVALID_POINTER;
  483. goto Clean0;
  484. }
  485. if (INVALID_FLAGS(ulFlags, 0)) {
  486. Status = CR_INVALID_FLAG;
  487. goto Clean0;
  488. }
  489. //
  490. // setup rpc binding handle (don't need string table handle)
  491. //
  492. if (!PnPGetGlobalHandles(hMachine, NULL, &hBinding)) {
  493. Status = CR_FAILURE;
  494. goto Clean0;
  495. }
  496. //
  497. // No special privileges are required by the server
  498. //
  499. RpcTryExcept {
  500. //
  501. // call rpc service entry point
  502. //
  503. Status = PNP_GetGlobalState(
  504. hBinding, // rpc binding handle
  505. pulState, // returns global state
  506. ulFlags); // not used
  507. }
  508. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  509. KdPrintEx((DPFLTR_PNPMGR_ID,
  510. DBGF_ERRORS,
  511. "PNP_GetGlobalState caused an exception (%d)\n",
  512. RpcExceptionCode()));
  513. Status = MapRpcExceptionToCR(RpcExceptionCode());
  514. }
  515. RpcEndExcept
  516. Clean0:
  517. NOTHING;
  518. } except(EXCEPTION_EXECUTE_HANDLER) {
  519. Status = CR_FAILURE;
  520. }
  521. return Status;
  522. } // CM_Get_Global_State_Ex
  523. CONFIGRET
  524. CM_Run_Detection_Ex(
  525. IN ULONG ulFlags,
  526. IN HMACHINE hMachine
  527. )
  528. /*++
  529. Routine Description:
  530. This routine loads and executes a detection module.
  531. Parameters:
  532. ulFlags - Specifies the reason for the detection. Can be one of the
  533. following values:
  534. Detection Flags:
  535. CM_DETECT_NEW_PROFILE - Run detection for a new hardware
  536. profile.
  537. CM_DETECT_CRASHED - Previously attempted detection crashed.
  538. (Windows 95 defines the following two unused flags as well:
  539. CM_DETECT_HWPROF_FIRST_BOOT and CM_DETECT_RUN.)
  540. Return Value:
  541. If the function succeeds, the return value is CR_SUCCESS.
  542. If the function fails, the return value is CR_INVALID_FLAG.
  543. --*/
  544. {
  545. CONFIGRET Status = CR_SUCCESS;
  546. handle_t hBinding = NULL;
  547. HANDLE hToken;
  548. ULONG ulPrivilege;
  549. try {
  550. //
  551. // validate parameters
  552. //
  553. if (INVALID_FLAGS(ulFlags, CM_DETECT_BITS)) {
  554. Status = CR_INVALID_FLAG;
  555. goto Clean0;
  556. }
  557. //
  558. // setup rpc binding handle (don't need string table handle)
  559. //
  560. if (!PnPGetGlobalHandles(hMachine, NULL, &hBinding)) {
  561. Status = CR_FAILURE;
  562. goto Clean0;
  563. }
  564. //
  565. // Enable privileges required by the server
  566. //
  567. ulPrivilege = SE_LOAD_DRIVER_PRIVILEGE;
  568. hToken = PnPEnablePrivileges(&ulPrivilege, 1);
  569. RpcTryExcept {
  570. //
  571. // call rpc service entry point
  572. //
  573. Status = PNP_RunDetection(
  574. hBinding,
  575. ulFlags); // not used
  576. }
  577. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  578. KdPrintEx((DPFLTR_PNPMGR_ID,
  579. DBGF_ERRORS,
  580. "PNP_RunDetection caused an exception (%d)\n",
  581. RpcExceptionCode()));
  582. Status = MapRpcExceptionToCR(RpcExceptionCode());
  583. }
  584. RpcEndExcept
  585. //
  586. // Restore previous privileges
  587. //
  588. PnPRestorePrivileges(hToken);
  589. Clean0:
  590. NOTHING;
  591. } except(EXCEPTION_EXECUTE_HANDLER) {
  592. Status = CR_FAILURE;
  593. }
  594. return Status;
  595. } // CM_Run_Detection_Ex
  596. CONFIGRET
  597. CM_Query_Arbitrator_Free_Data_Ex(
  598. OUT PVOID pData,
  599. IN ULONG DataLen,
  600. IN DEVINST dnDevInst,
  601. IN RESOURCEID ResourceID,
  602. IN ULONG ulFlags,
  603. IN HMACHINE hMachine
  604. )
  605. /*++
  606. Routine Description:
  607. This routine returns information about available resources of a
  608. particular type. If the given size is not large enough, this API
  609. truncates the data and returns CR_BUFFER_SMALL. To determine the
  610. buffer size needed to receive all the available resource information,
  611. use the CM_Query_Arbitrator_Free_Size API.
  612. Parameters:
  613. pData Supplies the address of the buffer that receives information
  614. on the available resources for the resource type specified
  615. by ResourceID.
  616. DataLen Supplies the size, in bytes, of the data buffer.
  617. dnDevNode Supplies the handle of the device instance associated with
  618. the arbitrator. This is only meaningful for local
  619. arbitrators--for global arbitrators, specify the root device
  620. instance or NULL. On Windows NT, this parameter must
  621. specify either the Root device instance or NULL.
  622. ResourceID Supplies the type of the resource. Can be one of the ResType
  623. values listed in Section 2.1.2.1.. (This API returns
  624. CR_INVALID_RESOURCEID if this value is ResType_All or
  625. ResType_None.)
  626. ulFlags Must be zero.
  627. Return Value:
  628. If the function succeeds, the return value is CR_SUCCESS.
  629. If the function fails, the return value is one of the following:
  630. CR_BUFFER_SMALL,
  631. CR_FAILURE,
  632. CR_INVALID_DEVNODE,
  633. CR_INVALID_FLAG,
  634. CR_INVALID_POINTER, or
  635. CR_INVALID_RESOURCEID.
  636. (Windows 95 may also return CR_NO_ARBITRATOR.)
  637. --*/
  638. {
  639. CONFIGRET Status = CR_SUCCESS;
  640. WCHAR pDeviceID [MAX_DEVICE_ID_LEN];
  641. PVOID hStringTable = NULL;
  642. handle_t hBinding = NULL;
  643. ULONG ulLen = MAX_DEVICE_ID_LEN;
  644. BOOL Success;
  645. try {
  646. //
  647. // validate parameters
  648. //
  649. if (dnDevInst == 0) {
  650. Status = CR_INVALID_DEVINST;
  651. goto Clean0;
  652. }
  653. if ((!ARGUMENT_PRESENT(pData)) || (DataLen == 0)) {
  654. Status = CR_INVALID_POINTER;
  655. goto Clean0;
  656. }
  657. if (INVALID_FLAGS(ulFlags, CM_QUERY_ARBITRATOR_BITS)) {
  658. Status = CR_INVALID_FLAG;
  659. goto Clean0;
  660. }
  661. if (ResourceID > ResType_MAX && ResourceID != ResType_ClassSpecific) {
  662. Status = CR_INVALID_RESOURCEID;
  663. goto Clean0;
  664. }
  665. //
  666. // setup rpc binding handle (don't need string table handle)
  667. //
  668. if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
  669. Status = CR_FAILURE;
  670. goto Clean0;
  671. }
  672. //
  673. // retrieve the device instance ID string associated with the devinst
  674. //
  675. Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,pDeviceID,&ulLen);
  676. if (Success == FALSE || INVALID_DEVINST(pDeviceID)) {
  677. Status = CR_INVALID_DEVINST;
  678. goto Clean0;
  679. }
  680. //
  681. // No special privileges are required by the server
  682. //
  683. RpcTryExcept {
  684. //
  685. // call rpc service entry point
  686. //
  687. Status = PNP_QueryArbitratorFreeData(
  688. hBinding,
  689. pData,
  690. DataLen,
  691. pDeviceID,
  692. ResourceID,
  693. ulFlags); // not used
  694. }
  695. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  696. KdPrintEx((DPFLTR_PNPMGR_ID,
  697. DBGF_ERRORS,
  698. "PNP_QueryArbitratorFreeData caused an exception (%d)\n",
  699. RpcExceptionCode()));
  700. Status = MapRpcExceptionToCR(RpcExceptionCode());
  701. }
  702. RpcEndExcept
  703. Clean0:
  704. NOTHING;
  705. } except(EXCEPTION_EXECUTE_HANDLER) {
  706. Status = CR_FAILURE;
  707. }
  708. return Status;
  709. } // CM_Query_Arbitrator_Free_Data_Ex
  710. #if 0
  711. CONFIGRET
  712. WINAPI
  713. CM_Query_Resource_Conflicts_Ex(
  714. IN DEVINST dnDevInst,
  715. IN RESOURCEID ResourceID,
  716. IN PCVOID ResourceData,
  717. IN ULONG ResourceLen,
  718. IN OUT PVOID pData,
  719. IN OUT PULONG pulDataLen,
  720. IN ULONG ulFlags
  721. )
  722. /*++
  723. Routine Description:
  724. This routine returns a list of devnodes that own resources that would
  725. conflict with the specified resource. If there are no conflicts, the
  726. returned list is NULL. If the caller supplied buffer is not large enough,
  727. CR_BUFFER_SMALL is returned and pulDataLen contains the required buffer
  728. size.
  729. Parameters:
  730. dnDevInst Supplies the handle of the device instance associated with
  731. the arbitrator. This is only meaningful for local
  732. arbitrators--for global arbitrators, specify the root device
  733. instance or NULL. On Windows NT, this parameter must
  734. specify either the Root device instance or NULL. ???
  735. ResourceID Supplies the type of the resource. Can be one of the ResType
  736. values listed in Section 2.1.2.1.. (This API returns
  737. CR_INVALID_RESOURCEID if this value is ResType_All or
  738. ResType_None.)
  739. ResourceData Supplies the adress of an IO_DES, MEM_DES, DMA_DES, IRQ_DES,
  740. etc, structure, depending on the given resource type.
  741. ResourceLen Supplies the size, in bytes, of the structure pointed to
  742. by ResourceData.
  743. pData Supplies the address of the buffer that receives information
  744. on the available resources for the resource type specified
  745. by ResourceID.
  746. pulDataLen Supplies the size, in bytes, of the data buffer.
  747. ulFlags Must be zero.
  748. Return Value:
  749. If the function succeeds, the return value is CR_SUCCESS.
  750. If the function fails, the return value is one of the following:
  751. CR_BUFFER_SMALL,
  752. CR_FAILURE,
  753. CR_INVALID_DEVNODE,
  754. CR_INVALID_FLAG,
  755. CR_INVALID_POINTER, or
  756. CR_INVALID_RESOURCEID.
  757. (Windows 95 may also return CR_NO_ARBITRATOR.)
  758. --*/
  759. {
  760. CONFIGRET Status = CR_SUCCESS;
  761. WCHAR pDeviceID [MAX_DEVICE_ID_LEN];
  762. PVOID hStringTable = NULL;
  763. handle_t hBinding = NULL;
  764. ULONG ulLen = MAX_DEVICE_ID_LEN;
  765. BOOL Success;
  766. try {
  767. //
  768. // validate parameters
  769. //
  770. if (dnDevInst == 0) {
  771. Status = CR_INVALID_DEVINST;
  772. goto Clean0;
  773. }
  774. if ((!ARGUMENT_PRESENT(pData)) ||
  775. (!ARGUMENT_PRESENT(pulDataLen)) ||
  776. (*pulDataLen == 0)) {
  777. Status = CR_INVALID_POINTER;
  778. goto Clean0;
  779. }
  780. if (INVALID_FLAGS(ulFlags, CM_QUERY_ARBITRATOR_BITS)) {
  781. Status = CR_INVALID_FLAG;
  782. goto Clean0;
  783. }
  784. if (ResourceID > ResType_MAX && ResourceID != ResType_ClassSpecific) {
  785. Status = CR_INVALID_RESOURCEID;
  786. goto Clean0;
  787. }
  788. //
  789. // setup rpc binding handle (don't need string table handle)
  790. //
  791. if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
  792. Status = CR_FAILURE;
  793. goto Clean0;
  794. }
  795. //
  796. // retrieve the device instance ID string associated with the devinst
  797. //
  798. Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,pDeviceID,&ulLen);
  799. if (Success == FALSE || INVALID_DEVINST(pDeviceID)) {
  800. Status = CR_INVALID_DEVINST;
  801. goto Clean0;
  802. }
  803. //
  804. // No special privileges are required by the server
  805. //
  806. RpcTryExcept {
  807. //
  808. // call rpc service entry point
  809. //
  810. Status = PNP_QueryArbitratorFreeData(
  811. hBinding,
  812. pData,
  813. DataLen,
  814. pDeviceID,
  815. ResourceID,
  816. ulFlags); // not used
  817. }
  818. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  819. KdPrintEx((DPFLTR_PNPMGR_ID,
  820. DBGF_ERRORS,
  821. "PNP_QueryArbitratorFreeData caused an exception (%d)\n",
  822. RpcExceptionCode()));
  823. Status = MapRpcExceptionToCR(RpcExceptionCode());
  824. }
  825. RpcEndExcept
  826. Clean0:
  827. NOTHING;
  828. } except(EXCEPTION_EXECUTE_HANDLER) {
  829. Status = CR_FAILURE;
  830. }
  831. return Status;
  832. } // CM_Query_Resource_Conflicts_Ex
  833. #endif
  834. CONFIGRET
  835. CM_Query_Arbitrator_Free_Size_Ex(
  836. OUT PULONG pulSize,
  837. IN DEVINST dnDevInst,
  838. IN RESOURCEID ResourceID,
  839. IN ULONG ulFlags,
  840. IN HMACHINE hMachine
  841. )
  842. /*++
  843. Routine Description:
  844. This routine retrieves the size of the available resource information
  845. that would be returned in a call to the CM_Query_Arbitrator_Free_Data
  846. API.
  847. Parameters:
  848. pulSize Supplies the address of the variable that receives the size,
  849. in bytes, that is required to hold the available resource
  850. information.
  851. dnDevNode Supplies the handle of the device instance associated with
  852. the arbitrator. This is only meaningful for local
  853. arbitrators--for global arbitrators, specify the root
  854. device instance or NULL. On Windows NT, this parameter
  855. must specify either the Root device instance or NULL.
  856. ResourceID Supplies the type of the resource. Can be one of the
  857. ResType values listed in Section 2.1.2.1.. (This API returns
  858. CR_INVALID_RESOURCEID if this value is ResType_All or
  859. ResType_None.)
  860. ulFlags CM_QUERY_ARBITRATOR_BITS.
  861. Return Value:
  862. If the function succeeds, the return value is CR_SUCCESS.
  863. If the function fails, the return value is one of the following:
  864. CR_FAILURE,
  865. CR_INVALID_DEVNODE,
  866. CR_INVALID_FLAG,
  867. CR_INVALID_POINTER, or
  868. CR_INVALID_RESOURCEID.
  869. (Windows 95 may also return CR_NO_ARBITRATOR.)
  870. --*/
  871. {
  872. CONFIGRET Status = CR_SUCCESS;
  873. WCHAR pDeviceID [MAX_DEVICE_ID_LEN];
  874. PVOID hStringTable = NULL;
  875. handle_t hBinding = NULL;
  876. ULONG ulLen = MAX_DEVICE_ID_LEN;
  877. BOOL Success;
  878. try {
  879. //
  880. // validate parameters
  881. //
  882. if (dnDevInst == 0) {
  883. Status = CR_INVALID_DEVINST;
  884. goto Clean0;
  885. }
  886. if (!ARGUMENT_PRESENT(pulSize)) {
  887. Status = CR_INVALID_POINTER;
  888. goto Clean0;
  889. }
  890. if (INVALID_FLAGS(ulFlags, CM_QUERY_ARBITRATOR_BITS)) {
  891. Status = CR_INVALID_FLAG;
  892. goto Clean0;
  893. }
  894. if (ResourceID > ResType_MAX && ResourceID != ResType_ClassSpecific) {
  895. Status = CR_INVALID_RESOURCEID;
  896. goto Clean0;
  897. }
  898. //
  899. // setup rpc binding handle (don't need string table handle)
  900. //
  901. if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
  902. Status = CR_FAILURE;
  903. goto Clean0;
  904. }
  905. //
  906. // retrieve the device instance ID string associated with the devinst
  907. //
  908. Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,pDeviceID,&ulLen);
  909. if (Success == FALSE || INVALID_DEVINST(pDeviceID)) {
  910. Status = CR_INVALID_DEVINST;
  911. goto Clean0;
  912. }
  913. //
  914. // No special privileges are required by the server
  915. //
  916. RpcTryExcept {
  917. //
  918. // call rpc service entry point
  919. //
  920. Status = PNP_QueryArbitratorFreeSize(
  921. hBinding,
  922. pulSize,
  923. pDeviceID,
  924. ResourceID,
  925. ulFlags); // not used
  926. }
  927. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  928. KdPrintEx((DPFLTR_PNPMGR_ID,
  929. DBGF_ERRORS,
  930. "PNP_QueryArbitratorFreeSize caused an exception (%d)\n",
  931. RpcExceptionCode()));
  932. Status = MapRpcExceptionToCR(RpcExceptionCode());
  933. }
  934. RpcEndExcept
  935. Clean0:
  936. NOTHING;
  937. } except(EXCEPTION_EXECUTE_HANDLER) {
  938. Status = CR_FAILURE;
  939. }
  940. return Status;
  941. } // CM_Query_Arbitrator_Free_Size_Ex
  942. //-------------------------------------------------------------------
  943. // Private CM routines
  944. //-------------------------------------------------------------------
  945. CONFIGRET
  946. CMP_Report_LogOn(
  947. IN ULONG ulPrivateID,
  948. IN DWORD ProcessID
  949. )
  950. /*++
  951. Routine Description:
  952. This is a private routine to notify the PlugPlay service that an interactive
  953. user has logged in. It is currently only called by userinit.exe.
  954. Parameters:
  955. ulPrivateID -
  956. Specifies the value of the private id.
  957. ProcessID -
  958. Specifies the process id of the calling process. Currently, this
  959. routine is only called by userinit.exe.
  960. Return Value:
  961. If the function succeeds, the return value is CR_SUCCESS.
  962. If the function fails, the return value is one of the following:
  963. CR_FAILURE,
  964. CR_INVALID_DATA
  965. --*/
  966. {
  967. CONFIGRET Status = CR_SUCCESS;
  968. handle_t hBinding = NULL;
  969. DWORD Retries = 0;
  970. UNREFERENCED_PARAMETER(ProcessID);
  971. try {
  972. //
  973. // validate parameters
  974. //
  975. if (ulPrivateID != 0x07020420) {
  976. Status = CR_INVALID_DATA;
  977. goto Clean0;
  978. }
  979. //
  980. // setup rpc binding handle (don't need string table handle)
  981. // this is always to the local server, by definition
  982. //
  983. if (!PnPGetGlobalHandles(NULL, NULL, &hBinding)) {
  984. Status = CR_FAILURE;
  985. goto Clean0;
  986. }
  987. for (Retries = 0; Retries < NUM_LOGON_RETRIES; Retries++) {
  988. RpcTryExcept {
  989. //
  990. // call rpc service entry point
  991. //
  992. Status = PNP_ReportLogOn(
  993. hBinding, // rpc binding handle
  994. FALSE, // Is Admin? (not used by server)
  995. GetCurrentProcessId()); // calling process id
  996. }
  997. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  998. KdPrintEx((DPFLTR_PNPMGR_ID,
  999. DBGF_ERRORS,
  1000. "PNP_ReportLogOn caused an exception (%d)\n",
  1001. RpcExceptionCode()));
  1002. Status = MapRpcExceptionToCR(RpcExceptionCode());
  1003. }
  1004. RpcEndExcept
  1005. if ((Status == CR_NO_CM_SERVICES) ||
  1006. (Status == CR_REMOTE_COMM_FAILURE)) {
  1007. KdPrintEx((DPFLTR_PNPMGR_ID,
  1008. DBGF_ERRORS,
  1009. "PlugPlay services not available (%d), retrying...\n",
  1010. Status));
  1011. //
  1012. // This is some error related to the service not being
  1013. // available, wait and try again.
  1014. //
  1015. Sleep(5000);
  1016. continue;
  1017. } else {
  1018. //
  1019. // Some other error, the service may never be available so bail
  1020. // out now.
  1021. //
  1022. break;
  1023. }
  1024. }
  1025. Clean0:
  1026. NOTHING;
  1027. } except(EXCEPTION_EXECUTE_HANDLER) {
  1028. Status = CR_FAILURE;
  1029. }
  1030. return Status;
  1031. } // CMP_Report_LogOn
  1032. CONFIGRET
  1033. CMP_Init_Detection(
  1034. IN ULONG ulPrivateID
  1035. )
  1036. {
  1037. CONFIGRET Status = CR_SUCCESS;
  1038. handle_t hBinding = NULL;
  1039. HANDLE hToken;
  1040. ULONG ulPrivilege;
  1041. try {
  1042. //
  1043. // validate parameters
  1044. //
  1045. if (ulPrivateID != 0x07020420) {
  1046. Status = CR_INVALID_DATA;
  1047. goto Clean0;
  1048. }
  1049. //
  1050. // setup rpc binding handle (don't need string table handle)
  1051. // this is always to the local server, by definition
  1052. //
  1053. if (!PnPGetGlobalHandles(NULL, NULL, &hBinding)) {
  1054. Status = CR_FAILURE;
  1055. goto Clean0;
  1056. }
  1057. //
  1058. // Enable privileges required by the server
  1059. //
  1060. ulPrivilege = SE_LOAD_DRIVER_PRIVILEGE;
  1061. hToken = PnPEnablePrivileges(&ulPrivilege, 1);
  1062. RpcTryExcept {
  1063. //
  1064. // call rpc service entry point
  1065. //
  1066. Status = PNP_InitDetection(
  1067. hBinding); // rpc binding handle
  1068. }
  1069. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  1070. KdPrintEx((DPFLTR_PNPMGR_ID,
  1071. DBGF_ERRORS,
  1072. "PNP_InitDetection caused an exception (%d)\n",
  1073. RpcExceptionCode()));
  1074. Status = MapRpcExceptionToCR(RpcExceptionCode());
  1075. }
  1076. RpcEndExcept
  1077. //
  1078. // Restore previous privileges
  1079. //
  1080. PnPRestorePrivileges(hToken);
  1081. Clean0:
  1082. NOTHING;
  1083. } except(EXCEPTION_EXECUTE_HANDLER) {
  1084. Status = CR_FAILURE;
  1085. }
  1086. return Status;
  1087. } // CMP_Init_Detection
  1088. CONFIGRET
  1089. CMP_WaitServicesAvailable(
  1090. IN HMACHINE hMachine
  1091. )
  1092. /*++
  1093. Routine Description:
  1094. This routine determines whether the user-mode pnp manager server side
  1095. (umpnpmgr) is up and running yet (providing the PNP_Xxx side of the
  1096. config manager apis).
  1097. Parameters:
  1098. hMachine - private (opaque) cm machine handle. If NULL, the call refers
  1099. to the local machine.
  1100. Return Value:
  1101. If the service is avialable upon return then CR_SUCCESS is returned.
  1102. If some other failure occurs, CR_FAILURE is returned.
  1103. --*/
  1104. {
  1105. CONFIGRET Status = CR_NO_CM_SERVICES;
  1106. handle_t hBinding = NULL;
  1107. WORD wVersion;
  1108. try {
  1109. //
  1110. // setup rpc binding handle (don't need string table handle)
  1111. //
  1112. if (!PnPGetGlobalHandles(hMachine, NULL, &hBinding)) {
  1113. Status = CR_FAILURE;
  1114. goto Clean0;
  1115. }
  1116. while ((Status == CR_NO_CM_SERVICES) ||
  1117. (Status == CR_MACHINE_UNAVAILABLE) ||
  1118. (Status == CR_REMOTE_COMM_FAILURE)) {
  1119. //
  1120. // No special privileges are required by the server
  1121. //
  1122. RpcTryExcept {
  1123. //
  1124. // call rpc service entry point
  1125. //
  1126. Status = PNP_GetVersion(
  1127. hBinding, // rpc machine name
  1128. &wVersion); // server size version
  1129. }
  1130. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  1131. KdPrintEx((DPFLTR_PNPMGR_ID,
  1132. DBGF_WARNINGS,
  1133. "PNP_GetVersion caused an exception (%d)\n",
  1134. RpcExceptionCode()));
  1135. Status = MapRpcExceptionToCR(RpcExceptionCode());
  1136. }
  1137. RpcEndExcept
  1138. if (Status == CR_SUCCESS) {
  1139. //
  1140. // Service is avilable now, return success.
  1141. //
  1142. goto Clean0;
  1143. }
  1144. if ((Status == CR_NO_CM_SERVICES) ||
  1145. (Status == CR_MACHINE_UNAVAILABLE) ||
  1146. (Status == CR_REMOTE_COMM_FAILURE)) {
  1147. //
  1148. // This is some error related to the service not being
  1149. // available, wait and try again.
  1150. //
  1151. Sleep(5000);
  1152. } else {
  1153. //
  1154. // Some other error, the service may never be avaiable
  1155. // so bail out now.
  1156. //
  1157. Status = CR_FAILURE;
  1158. goto Clean0;
  1159. }
  1160. }
  1161. Clean0:
  1162. NOTHING;
  1163. } except(EXCEPTION_EXECUTE_HANDLER) {
  1164. Status = CR_FAILURE;
  1165. }
  1166. return Status;
  1167. } // CMP_WaitServicesAvailable
  1168. DWORD
  1169. CMP_WaitNoPendingInstallEvents(
  1170. IN DWORD dwTimeout
  1171. )
  1172. /*++
  1173. Routine Description:
  1174. This routine waits until there are no pending device install events.
  1175. If a timeout value is specified then it will return either when no
  1176. install events are pending or when the timeout period has expired,
  1177. whichever comes first. This routine is intended to be called after
  1178. user-logon, only.
  1179. NOTE: New install events can occur at anytime, this routine just
  1180. indicates that there are no install events at this moment.
  1181. Parameters:
  1182. dwTimeout - Specifies the time-out interval, in milliseconds. The function
  1183. returns if the interval elapses, even if there are still pending
  1184. install events. If dwTimeout is zero, the function just tests whether
  1185. there are pending install events and returns immediately. If
  1186. dwTimeout is INFINITE, the function's time-out interval never elapses.
  1187. Return Value:
  1188. If the function succeeds, the return value indicates the event that caused
  1189. the function to return. If the function fails, the return value is
  1190. WAIT_FAILED. To get extended error information, call GetLastError.
  1191. The return value on success is one of the following values:
  1192. WAIT_ABANDONED The specified object is a mutex object that was not
  1193. released by the thread that owned the mutex object before
  1194. the owning thread terminated. Ownership of the mutex
  1195. object is granted to the calling thread, and the mutex is
  1196. set to nonsignaled.
  1197. WAIT_OBJECT_0 The state of the specified object is signaled.
  1198. WAIT_TIMEOUT The time-out interval elapsed, and the object's state is
  1199. nonsignaled.
  1200. --*/
  1201. {
  1202. DWORD Status = WAIT_FAILED;
  1203. HANDLE hEvent = NULL;
  1204. try {
  1205. hEvent = OpenEvent(SYNCHRONIZE, FALSE, PNP_NO_INSTALL_EVENTS);
  1206. if (hEvent == NULL) {
  1207. Status = WAIT_FAILED;
  1208. } else {
  1209. Status = WaitForSingleObject(hEvent, dwTimeout);
  1210. }
  1211. } except(EXCEPTION_EXECUTE_HANDLER) {
  1212. Status = WAIT_FAILED;
  1213. }
  1214. if (hEvent) {
  1215. CloseHandle(hEvent);
  1216. }
  1217. return Status;
  1218. } // CMP_WaitNoPendingInstallEvents
  1219. CONFIGRET
  1220. CMP_GetBlockedDriverInfo(
  1221. OUT LPBYTE Buffer,
  1222. IN OUT PULONG pulLength,
  1223. IN ULONG ulFlags,
  1224. IN HMACHINE hMachine
  1225. )
  1226. /*++
  1227. Routine Description:
  1228. This routine retrieves the list of drivers that have been blocked from
  1229. loading on the system since boot.
  1230. Arguments:
  1231. Buffer - Supplies the address of the buffer that receives the list of
  1232. drivers that have been blocked from loading on the system. Can
  1233. be NULL when simply retrieving data size.
  1234. pulLength - Supplies the address of the variable that contains the size, in
  1235. bytes, of the buffer. If the variable is initially zero, the
  1236. API replaces it with the buffer size needed to receive all the
  1237. data. In this case, the Buffer parameter is ignored.
  1238. ulFlags - Must be zero.
  1239. hMachine - Machine handle returned from CM_Connect_Machine or NULL.
  1240. Return value:
  1241. If the function succeeds, it returns CR_SUCCESS, otherwise it returns one of
  1242. the CR_* error codes.
  1243. --*/
  1244. {
  1245. CONFIGRET Status;
  1246. ULONG ulTransferLen;
  1247. BYTE NullBuffer = 0;
  1248. handle_t hBinding = NULL;
  1249. try {
  1250. //
  1251. // validate parameters
  1252. //
  1253. if (!ARGUMENT_PRESENT(pulLength)) {
  1254. Status = CR_INVALID_POINTER;
  1255. goto Clean0;
  1256. }
  1257. if ((!ARGUMENT_PRESENT(Buffer)) && (*pulLength != 0)) {
  1258. Status = CR_INVALID_POINTER;
  1259. goto Clean0;
  1260. }
  1261. if (INVALID_FLAGS(ulFlags, 0)) {
  1262. Status = CR_INVALID_FLAG;
  1263. goto Clean0;
  1264. }
  1265. //
  1266. // setup rpc binding handle (don't need string table handle)
  1267. //
  1268. if (!PnPGetGlobalHandles(hMachine, NULL, &hBinding)) {
  1269. Status = CR_FAILURE;
  1270. goto Clean0;
  1271. }
  1272. //
  1273. // NOTE: The ulTransferLen variable is just used to control
  1274. // how much data is marshalled via rpc between address spaces.
  1275. // ulTransferLen should be set on entry to the size of the Buffer.
  1276. // The last parameter should also be the size of the Buffer on entry
  1277. // and on exit contains either the amount transferred (if a transfer
  1278. // occured) or the amount required, this value should be passed back
  1279. // in the callers pulLength parameter.
  1280. //
  1281. ulTransferLen = *pulLength;
  1282. if (!ARGUMENT_PRESENT(Buffer)) {
  1283. Buffer = &NullBuffer;
  1284. }
  1285. //
  1286. // No special privileges are required by the server
  1287. //
  1288. RpcTryExcept {
  1289. //
  1290. // call rpc service entry point
  1291. //
  1292. Status = PNP_GetBlockedDriverInfo(
  1293. hBinding, // rpc binding handle
  1294. Buffer, // receives blocked driver info
  1295. &ulTransferLen, // input/output buffer size
  1296. pulLength, // bytes copied (or bytes required)
  1297. ulFlags); // not used
  1298. }
  1299. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  1300. KdPrintEx((DPFLTR_PNPMGR_ID,
  1301. DBGF_WARNINGS,
  1302. "PNP_GetBlockedDriverInfo caused an exception (%d)\n",
  1303. RpcExceptionCode()));
  1304. Status = MapRpcExceptionToCR(RpcExceptionCode());
  1305. }
  1306. RpcEndExcept
  1307. Clean0:
  1308. NOTHING;
  1309. } except(EXCEPTION_EXECUTE_HANDLER) {
  1310. Status = CR_FAILURE;
  1311. }
  1312. return Status;
  1313. } // CMP_GetBlockedDriverInfo
  1314. CONFIGRET
  1315. CMP_GetServerSideDeviceInstallFlags(
  1316. IN PULONG pulSSDIFlags,
  1317. IN ULONG ulFlags,
  1318. IN HMACHINE hMachine
  1319. )
  1320. /*++
  1321. Routine Description:
  1322. This routine retrieves the server side device install flags.
  1323. Arguments:
  1324. pulSSDIFlags - Pointer to a ULONG that receives the server side device
  1325. install flags.
  1326. ulFlags - Must be zero.
  1327. hMachine - Machine handle returned from CM_Connect_Machine or NULL.
  1328. Return value:
  1329. If the function succeeds, it returns CR_SUCCESS, otherwise it returns one of
  1330. the CR_* error codes.
  1331. --*/
  1332. {
  1333. CONFIGRET Status;
  1334. handle_t hBinding = NULL;
  1335. try {
  1336. //
  1337. // validate parameters
  1338. //
  1339. if (!ARGUMENT_PRESENT(pulSSDIFlags)) {
  1340. Status = CR_INVALID_POINTER;
  1341. goto Clean0;
  1342. }
  1343. if (INVALID_FLAGS(ulFlags, 0)) {
  1344. Status = CR_INVALID_FLAG;
  1345. goto Clean0;
  1346. }
  1347. //
  1348. // setup rpc binding handle (don't need string table handle)
  1349. //
  1350. if (!PnPGetGlobalHandles(hMachine, NULL, &hBinding)) {
  1351. Status = CR_FAILURE;
  1352. goto Clean0;
  1353. }
  1354. //
  1355. // No special privileges are required by the server
  1356. //
  1357. RpcTryExcept {
  1358. //
  1359. // call rpc service entry point
  1360. //
  1361. Status = PNP_GetServerSideDeviceInstallFlags(
  1362. hBinding, // rpc binding handle
  1363. pulSSDIFlags, // receives server side device install flags
  1364. ulFlags); // not used
  1365. }
  1366. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  1367. KdPrintEx((DPFLTR_PNPMGR_ID,
  1368. DBGF_WARNINGS,
  1369. "PNP_GetServerSideDeviceInstallFlags caused an exception (%d)\n",
  1370. RpcExceptionCode()));
  1371. Status = MapRpcExceptionToCR(RpcExceptionCode());
  1372. }
  1373. RpcEndExcept
  1374. Clean0:
  1375. NOTHING;
  1376. } except(EXCEPTION_EXECUTE_HANDLER) {
  1377. Status = CR_FAILURE;
  1378. }
  1379. return Status;
  1380. } // CMP_GetServerSideDeviceInstallFlags
  1381. //-------------------------------------------------------------------
  1382. // Local Stubs
  1383. //-------------------------------------------------------------------
  1384. WORD
  1385. CM_Get_Version(
  1386. VOID
  1387. )
  1388. {
  1389. return CM_Get_Version_Ex(NULL);
  1390. }
  1391. BOOL
  1392. CM_Is_Version_Available(
  1393. IN WORD wVersion
  1394. )
  1395. {
  1396. return CM_Is_Version_Available_Ex(wVersion, NULL);
  1397. }
  1398. CONFIGRET
  1399. CM_Get_Global_State(
  1400. OUT PULONG pulState,
  1401. IN ULONG ulFlags
  1402. )
  1403. {
  1404. return CM_Get_Global_State_Ex(pulState, ulFlags, NULL);
  1405. }
  1406. CONFIGRET
  1407. CM_Query_Arbitrator_Free_Data(
  1408. OUT PVOID pData,
  1409. IN ULONG DataLen,
  1410. IN DEVINST dnDevInst,
  1411. IN RESOURCEID ResourceID,
  1412. IN ULONG ulFlags
  1413. )
  1414. {
  1415. return CM_Query_Arbitrator_Free_Data_Ex(pData, DataLen, dnDevInst,
  1416. ResourceID, ulFlags, NULL);
  1417. }
  1418. CONFIGRET
  1419. CM_Query_Arbitrator_Free_Size(
  1420. OUT PULONG pulSize,
  1421. IN DEVINST dnDevInst,
  1422. IN RESOURCEID ResourceID,
  1423. IN ULONG ulFlags
  1424. )
  1425. {
  1426. return CM_Query_Arbitrator_Free_Size_Ex(pulSize, dnDevInst, ResourceID,
  1427. ulFlags, NULL);
  1428. }
  1429. CONFIGRET
  1430. CM_Run_Detection(
  1431. IN ULONG ulFlags
  1432. )
  1433. {
  1434. return CM_Run_Detection_Ex(ulFlags, NULL);
  1435. }
  1436. //-------------------------------------------------------------------
  1437. // ANSI Stubs
  1438. //-------------------------------------------------------------------
  1439. CONFIGRET
  1440. CM_Connect_MachineA(
  1441. IN PCSTR UNCServerName,
  1442. OUT PHMACHINE phMachine
  1443. )
  1444. {
  1445. CONFIGRET Status = CR_SUCCESS;
  1446. PWSTR pUniName = NULL;
  1447. if ((!ARGUMENT_PRESENT(UNCServerName)) ||
  1448. (UNCServerName[0] == '\0')) {
  1449. //
  1450. // no explicit name specified, so assume local machine and
  1451. // nothing to translate
  1452. //
  1453. Status = CM_Connect_MachineW(pUniName,
  1454. phMachine);
  1455. } else if (pSetupCaptureAndConvertAnsiArg(UNCServerName, &pUniName) == NO_ERROR) {
  1456. Status = CM_Connect_MachineW(pUniName,
  1457. phMachine);
  1458. pSetupFree(pUniName);
  1459. } else {
  1460. Status = CR_INVALID_DATA;
  1461. }
  1462. return Status;
  1463. } // CM_Connect_MachineA