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.

711 lines
17 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. rmisc.c
  5. Abstract:
  6. This module contains the server-side misc configuration manager routines.
  7. PNP_GetVersion
  8. PNP_GetVersionInternal
  9. PNP_GetGlobalState
  10. PNP_SetActiveService
  11. PNP_QueryArbitratorFreeData
  12. PNP_QueryArbitratorFreeSize
  13. PNP_InitDetection
  14. PNP_RunDetection
  15. PNP_Connect
  16. PNP_Disconnect
  17. PNP_GetBlockedDriverInfo
  18. The following routines are used by the RPC server stubs to allocate and free memory.
  19. MIDL_user_allocate
  20. MIDL_user_free
  21. Author:
  22. Paula Tomlinson (paulat) 6-28-1995
  23. Environment:
  24. User-mode only.
  25. Revision History:
  26. 28-June-1995 paulat
  27. Creation and initial implementation.
  28. --*/
  29. //
  30. // includes
  31. //
  32. #include "precomp.h"
  33. #pragma hdrstop
  34. #include "umpnpi.h"
  35. #include "umpnpdat.h"
  36. //
  37. // global data
  38. //
  39. extern DWORD CurrentServiceState; // current state of the PlugPlay service - DO NOT MODIFY
  40. CONFIGRET
  41. PNP_GetVersion(
  42. IN handle_t hBinding,
  43. IN OUT WORD * pVersion
  44. )
  45. /*++
  46. Routine Description:
  47. This is the RPC server entry point, it returns the version
  48. number for the server-side component.
  49. Arguments:
  50. hBinding Not used.
  51. Return Value:
  52. Return the version number, with the major version in the high byte and
  53. the minor version number in the low byte.
  54. --*/
  55. {
  56. CONFIGRET Status = CR_SUCCESS;
  57. UNREFERENCED_PARAMETER(hBinding);
  58. try {
  59. *pVersion = (WORD)PNP_VERSION;
  60. } except(EXCEPTION_EXECUTE_HANDLER) {
  61. Status = CR_FAILURE;
  62. }
  63. return Status;
  64. } // PNP_GetVersion
  65. CONFIGRET
  66. PNP_GetVersionInternal(
  67. IN handle_t hBinding,
  68. IN OUT WORD * pwVersion
  69. )
  70. /*++
  71. Routine Description:
  72. This is the RPC server entry point, it returns the internal version
  73. number for the server-side component.
  74. Arguments:
  75. hBinding Not used.
  76. pwVersion Receives the internal cfgmgr32 version number, returns the
  77. internal server version number, with the major version in the
  78. high byte and the minor version number in the low byte.
  79. Return Value:
  80. Return CR_SUCCESS if the function succeeds, otherwise it returns one
  81. of the CR_* errors.
  82. --*/
  83. {
  84. CONFIGRET Status = CR_SUCCESS;
  85. UNREFERENCED_PARAMETER(hBinding);
  86. try {
  87. *pwVersion = (WORD)PNP_VERSION_INTERNAL;
  88. } except(EXCEPTION_EXECUTE_HANDLER) {
  89. Status = CR_FAILURE;
  90. }
  91. return Status;
  92. } // PNP_GetVersionInternal
  93. CONFIGRET
  94. PNP_GetGlobalState(
  95. IN handle_t hBinding,
  96. OUT PULONG pulState,
  97. IN ULONG ulFlags
  98. )
  99. /*++
  100. Routine Description:
  101. This is the RPC server entry point, it returns the Global State of the
  102. Configuration Manager.
  103. Arguments:
  104. hBinding Not used.
  105. pulState Returns the current global state.
  106. ulFlags Not used, must be zero.
  107. Return Value:
  108. Return CR_SUCCESS if the function succeeds, otherwise it returns one
  109. of the CR_* errors.
  110. --*/
  111. {
  112. CONFIGRET Status = CR_SUCCESS;
  113. UNREFERENCED_PARAMETER(hBinding);
  114. try {
  115. //
  116. // validate parameters
  117. //
  118. if (INVALID_FLAGS(ulFlags, 0)) {
  119. Status = CR_INVALID_FLAG;
  120. goto Clean0;
  121. }
  122. //
  123. // The following CM global state flags are always set.
  124. //
  125. *pulState =
  126. CM_GLOBAL_STATE_CAN_DO_UI |
  127. CM_GLOBAL_STATE_SERVICES_AVAILABLE;
  128. //
  129. // If the service is shutting down, specify the corresponding CM global
  130. // state flag.
  131. //
  132. if ((CurrentServiceState == SERVICE_STOP_PENDING) ||
  133. (CurrentServiceState == SERVICE_STOPPED)) {
  134. *pulState |= CM_GLOBAL_STATE_SHUTTING_DOWN;
  135. }
  136. Clean0:
  137. NOTHING;
  138. } except(EXCEPTION_EXECUTE_HANDLER) {
  139. Status = CR_FAILURE;
  140. }
  141. return Status;
  142. } // PNP_GetGlobalState
  143. CONFIGRET
  144. PNP_SetActiveService(
  145. IN handle_t hBinding,
  146. IN LPCWSTR pszService,
  147. IN ULONG ulFlags
  148. )
  149. /*++
  150. Routine Description:
  151. This routine is currently not an rpc routine, it is called directly
  152. and privately by the service controller.
  153. Arguments:
  154. hBinding RPC binding handle, not used.
  155. pszService Specifies the service name.
  156. ulFlags Either PNP_SERVICE_STARTED or PNP_SERVICE_STOPPED.
  157. Return Value:
  158. Return CR_SUCCESS if the function succeeds, otherwise it returns one
  159. of the CR_* errors.
  160. --*/
  161. {
  162. CONFIGRET Status = CR_SUCCESS;
  163. ULONG ulSize = 0;
  164. LPWSTR pDeviceList = NULL, pszDevice = NULL;
  165. HKEY hKey = NULL, hControlKey = NULL;
  166. WCHAR RegStr[MAX_PATH];
  167. UNREFERENCED_PARAMETER(hBinding);
  168. try {
  169. //
  170. // validate parameters
  171. //
  172. if (pszService == NULL) {
  173. Status = CR_INVALID_POINTER;
  174. goto Clean0;
  175. }
  176. if ((ulFlags != PNP_SERVICE_STOPPED) &&
  177. (ulFlags != PNP_SERVICE_STARTED)) {
  178. Status = CR_INVALID_FLAG;
  179. goto Clean0;
  180. }
  181. //
  182. // not handling stops right now, everything beyond here assumes
  183. // the service is starting (or at least it attempted to start)
  184. //
  185. if (ulFlags == PNP_SERVICE_STOPPED) {
  186. Status = CR_SUCCESS;
  187. goto Clean0;
  188. }
  189. //
  190. // retreive the list of devices that this service is controlling
  191. //
  192. Status = PNP_GetDeviceListSize(NULL, pszService, &ulSize,
  193. CM_GETIDLIST_FILTER_SERVICE);
  194. if (Status != CR_SUCCESS) {
  195. goto Clean0;
  196. }
  197. pDeviceList = HeapAlloc(ghPnPHeap, 0, ulSize * sizeof(WCHAR));
  198. if (pDeviceList == NULL) {
  199. Status = CR_OUT_OF_MEMORY;
  200. goto Clean0;
  201. }
  202. Status = PNP_GetDeviceList(NULL, pszService, pDeviceList, &ulSize,
  203. CM_GETIDLIST_FILTER_SERVICE);
  204. if (Status != CR_SUCCESS) {
  205. goto Clean0;
  206. }
  207. //
  208. // set the ActiveService value for each device
  209. //
  210. for (pszDevice = pDeviceList;
  211. *pszDevice;
  212. pszDevice += lstrlen(pszDevice) + 1) {
  213. if (FAILED(StringCchPrintf(
  214. RegStr,
  215. SIZECHARS(RegStr),
  216. L"%s\\%s",
  217. pszRegPathEnum,
  218. pszDevice))) {
  219. continue;
  220. }
  221. //
  222. // open the device instance key
  223. //
  224. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, RegStr, 0, KEY_ALL_ACCESS,
  225. &hKey) == ERROR_SUCCESS) {
  226. //
  227. // open/create the volatile Control key
  228. //
  229. if (RegCreateKeyEx(hKey, pszRegKeyDeviceControl, 0, NULL,
  230. REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL,
  231. &hControlKey, NULL) == ERROR_SUCCESS) {
  232. RegSetValueEx(hControlKey, pszRegValueActiveService,
  233. 0, REG_SZ, (LPBYTE)pszService,
  234. (lstrlen(pszService) + 1) * sizeof(WCHAR));
  235. //
  236. // set the statusflag to DN_STARTED
  237. //
  238. SetDeviceStatus(pszDevice, DN_STARTED, 0);
  239. RegCloseKey(hControlKey);
  240. hControlKey = NULL;
  241. }
  242. RegCloseKey(hKey);
  243. hKey = NULL;
  244. }
  245. }
  246. Clean0:
  247. NOTHING;
  248. } except(EXCEPTION_EXECUTE_HANDLER) {
  249. Status = CR_FAILURE;
  250. }
  251. if (pDeviceList != NULL) {
  252. HeapFree(ghPnPHeap, 0, pDeviceList);
  253. }
  254. if (hKey != NULL) {
  255. RegCloseKey(hKey);
  256. }
  257. return Status;
  258. } // PNP_SetActiveService
  259. //--------------------------------------------------------------------
  260. // Stub server side CM routines - not implemented yet
  261. //--------------------------------------------------------------------
  262. CONFIGRET
  263. PNP_QueryArbitratorFreeData(
  264. IN handle_t hBinding,
  265. OUT LPBYTE pData,
  266. IN ULONG ulDataLen,
  267. IN LPCWSTR pszDeviceID,
  268. IN RESOURCEID ResourceID,
  269. IN ULONG ulFlags
  270. )
  271. {
  272. UNREFERENCED_PARAMETER(hBinding);
  273. UNREFERENCED_PARAMETER(pData);
  274. UNREFERENCED_PARAMETER(ulDataLen);
  275. UNREFERENCED_PARAMETER(pszDeviceID);
  276. UNREFERENCED_PARAMETER(ResourceID);
  277. UNREFERENCED_PARAMETER(ulFlags);
  278. return CR_CALL_NOT_IMPLEMENTED;
  279. } // PNP_QueryArbitratorFreeData
  280. CONFIGRET
  281. PNP_QueryArbitratorFreeSize(
  282. IN handle_t hBinding,
  283. OUT PULONG pulSize,
  284. IN LPCWSTR pszDeviceID,
  285. IN RESOURCEID ResourceID,
  286. IN ULONG ulFlags
  287. )
  288. {
  289. CONFIGRET Status;
  290. UNREFERENCED_PARAMETER(hBinding);
  291. UNREFERENCED_PARAMETER(pszDeviceID);
  292. UNREFERENCED_PARAMETER(ResourceID);
  293. UNREFERENCED_PARAMETER(ulFlags);
  294. try {
  295. if (ARGUMENT_PRESENT(pulSize)) {
  296. *pulSize = 0;
  297. }
  298. Status = CR_CALL_NOT_IMPLEMENTED;
  299. } except(EXCEPTION_EXECUTE_HANDLER) {
  300. Status = CR_FAILURE;
  301. }
  302. return Status;
  303. } // PNP_QueryArbitratorFreeSize
  304. //---------------------------------------------------------------------------
  305. // Debugging interface - initiate detection through private debug interface
  306. //---------------------------------------------------------------------------
  307. CONFIGRET
  308. PNP_InitDetection(
  309. handle_t hBinding
  310. )
  311. /*++
  312. Routine Description:
  313. This routine is a private debugging interface to initiate device detection.
  314. Arguments:
  315. hBinding - RPC binding handle.
  316. Return Value:
  317. Currently returns CR_CALL_NOT_IMPLEMENTED.
  318. Notes:
  319. Previously, this routine would kick off the InitializePnPManager thread on
  320. checked builds only.
  321. Presumably, this dates way back to a time when this routine actually sought
  322. out non-configured devices and initiated installation on them (as is
  323. currently done at the start of the ThreadProc_DeviceInstall thread procedure
  324. routine).
  325. Since InitializePnPManager no longer does this, so this behavior has been
  326. removed altogether. It is currently never valid to perform initialization
  327. more than once, however this routine may be used to implement detection of
  328. non-configured devices.
  329. --*/
  330. {
  331. //
  332. // Verify client "execute" access
  333. //
  334. if (!VerifyClientAccess(hBinding,
  335. PLUGPLAY_EXECUTE)) {
  336. return CR_ACCESS_DENIED;
  337. }
  338. //
  339. // Verify client privilege
  340. //
  341. if (!VerifyClientPrivilege(hBinding,
  342. SE_LOAD_DRIVER_PRIVILEGE,
  343. L"Plug and Play Action (not implemeted)")) {
  344. return CR_ACCESS_DENIED;
  345. }
  346. return CR_CALL_NOT_IMPLEMENTED;
  347. } // PNP_InitDetection
  348. CONFIGRET
  349. PNP_RunDetection(
  350. IN handle_t hBinding,
  351. IN ULONG ulFlags
  352. )
  353. {
  354. UNREFERENCED_PARAMETER(ulFlags);
  355. //
  356. // Verify client "execute" access
  357. //
  358. if (!VerifyClientAccess(hBinding,
  359. PLUGPLAY_EXECUTE)) {
  360. return CR_ACCESS_DENIED;
  361. }
  362. //
  363. // Verify client privilege
  364. //
  365. if (!VerifyClientPrivilege(hBinding,
  366. SE_LOAD_DRIVER_PRIVILEGE,
  367. L"Plug and Play Action (not implemeted)")) {
  368. return CR_ACCESS_DENIED;
  369. }
  370. return CR_CALL_NOT_IMPLEMENTED;
  371. } // PNP_RunDetection
  372. CONFIGRET
  373. PNP_Connect(
  374. IN PNP_HANDLE UNCServerName
  375. )
  376. {
  377. //
  378. // Note that although this routine is listed in the PNP RPC interface, it
  379. // uses automatic binding, and does not reference any implicit binding handle
  380. // (which is how the interface has come to be defined). As such, it is not
  381. // callable through the existing PNP RPC interface.
  382. //
  383. UNREFERENCED_PARAMETER(UNCServerName);
  384. return CR_CALL_NOT_IMPLEMENTED;
  385. } // PNP_Connect
  386. CONFIGRET
  387. PNP_Disconnect(
  388. IN PNP_HANDLE UNCServerName
  389. )
  390. {
  391. //
  392. // Note that although this routine is listed in the PNP RPC interface, it
  393. // uses automatic binding, and does not reference any implicit binding handle
  394. // (which is how the interface has come to be defined). As such, it is not
  395. // callable through the existing PNP RPC interface.
  396. //
  397. UNREFERENCED_PARAMETER(UNCServerName);
  398. return CR_CALL_NOT_IMPLEMENTED;
  399. } // PNP_Disconnect
  400. CONFIGRET
  401. PNP_GetBlockedDriverInfo(
  402. IN handle_t hBinding,
  403. OUT LPBYTE Buffer,
  404. OUT PULONG pulTransferLen,
  405. IN OUT PULONG pulLength,
  406. IN ULONG ulFlags
  407. )
  408. /*++
  409. Routine Description:
  410. This is the RPC server entry point for the CMP_GetBlockedDriverInfo routine.
  411. Arguments:
  412. hBinding - RPC binding handle, not used.
  413. Buffer - Supplies the address of the buffer that receives the
  414. list. Can be NULL when simply retrieving data size.
  415. pulTransferLen - Used by stubs, indicates how much data (in bytes) to
  416. copy back into user buffer.
  417. pulLength - Parameter passed in by caller, on entry it contains the
  418. size (in bytes) of the buffer, on exit it contains either
  419. the number of bytes transferred to the caller's buffer (if
  420. a transfer occured) or else the size of buffer required to
  421. hold the list.
  422. ulFlags Not used, must be zero.
  423. Return Value:
  424. Return CR_SUCCESS if the function succeeds, otherwise it returns one of the
  425. CR_* errors.
  426. --*/
  427. {
  428. CONFIGRET Status = CR_SUCCESS;
  429. NTSTATUS ntStatus;
  430. PLUGPLAY_CONTROL_BLOCKED_DRIVER_DATA controlData;
  431. UNREFERENCED_PARAMETER(hBinding);
  432. try {
  433. //
  434. // Validate parameters
  435. //
  436. if ((!ARGUMENT_PRESENT(pulTransferLen)) ||
  437. (!ARGUMENT_PRESENT(pulLength))) {
  438. Status = CR_INVALID_POINTER;
  439. goto Clean0;
  440. }
  441. if ((!ARGUMENT_PRESENT(Buffer)) && (*pulLength != 0)) {
  442. Status = CR_INVALID_POINTER;
  443. goto Clean0;
  444. }
  445. if (INVALID_FLAGS(ulFlags, 0)) {
  446. Status = CR_INVALID_FLAG;
  447. goto Clean0;
  448. }
  449. //
  450. // We should never have both arguments pointing to the same memory...
  451. //
  452. ASSERT(pulTransferLen != pulLength);
  453. //
  454. // ...but if we do, fail the call.
  455. //
  456. if (pulTransferLen == pulLength) {
  457. Status = CR_INVALID_POINTER;
  458. goto Clean0;
  459. }
  460. //
  461. // Retrieve the blocked driver list via kernel-mode.
  462. //
  463. memset(&controlData, 0, sizeof(PLUGPLAY_CONTROL_BLOCKED_DRIVER_DATA));
  464. controlData.Buffer = Buffer;
  465. controlData.BufferLength = *pulLength;
  466. controlData.Flags = ulFlags;
  467. ntStatus = NtPlugPlayControl(PlugPlayControlGetBlockedDriverList,
  468. &controlData,
  469. sizeof(controlData));
  470. if (NT_SUCCESS(ntStatus)) {
  471. *pulTransferLen = *pulLength; // Transfer everything back
  472. *pulLength = controlData.BufferLength; // Length of valid data
  473. } else if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
  474. *pulTransferLen = 0; // Nothing to transfer
  475. *pulLength = controlData.BufferLength;
  476. Status = CR_BUFFER_SMALL;
  477. } else {
  478. *pulLength = *pulTransferLen = 0; // Nothing to transfer
  479. Status = MapNtStatusToCmError(ntStatus);
  480. }
  481. Clean0:
  482. NOTHING;
  483. } except(EXCEPTION_EXECUTE_HANDLER) {
  484. Status = CR_FAILURE;
  485. }
  486. return Status;
  487. } // PNP_GetBlockedDriverInfo
  488. void __RPC_FAR * __RPC_USER
  489. MIDL_user_allocate(
  490. size_t cBytes
  491. )
  492. {
  493. return HeapAlloc(ghPnPHeap, 0, cBytes);
  494. } // MIDL_user_allocate
  495. void __RPC_USER
  496. MIDL_user_free(
  497. void __RPC_FAR * pBuffer
  498. )
  499. {
  500. HeapFree(ghPnPHeap, 0, pBuffer);
  501. } // MIDL_user_free