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.

1783 lines
47 KiB

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