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.

2360 lines
67 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. dcapi.c
  5. Abstract:
  6. WMI data consumer api set
  7. Author:
  8. 16-Jan-1997 AlanWar
  9. Revision History:
  10. --*/
  11. #include "wmiump.h"
  12. #ifndef MEMPHIS
  13. #include <aclapi.h>
  14. #endif
  15. ULONG
  16. WMIAPI
  17. WmiOpenBlock(
  18. IN GUID *DataBlockGuid,
  19. IN ULONG DesiredAccess,
  20. OUT WMIHANDLE *DataBlockHandle
  21. )
  22. /*+++
  23. Routine Description:
  24. This routine prepares for accessing data items contained within the data
  25. block represented by the guid passed. If successful it returns a handle
  26. that can be used to query and set data blocks maintained by data providers
  27. that have registered the guid. Any data providers that had registered the
  28. guid as expensive will receive a request to enable collection of data for
  29. the guid if collection was not previously enabled.
  30. Arguments:
  31. DataBlockGuid - Pointer to guid that represents the data block
  32. DesiredAccess - Specifies the type of access to the object. Not used on
  33. Windows 98
  34. *DataBlockHandle - If successful returns a handle to the data block
  35. Return Value:
  36. Returns ERROR_SUCCESS or an error code.
  37. ---*/
  38. {
  39. ULONG Status;
  40. HANDLE KernelHandle;
  41. GUID Guid;
  42. ULONG Ioctl;
  43. WmipInitProcessHeap();
  44. //
  45. // Validate the passed parameters
  46. //
  47. if ((DataBlockGuid == NULL) ||
  48. (DataBlockHandle == NULL))
  49. {
  50. SetLastError(ERROR_INVALID_PARAMETER);
  51. return(ERROR_INVALID_PARAMETER);
  52. }
  53. if ((DesiredAccess & WMIGUID_NOTIFICATION) &&
  54. ((DesiredAccess & (WMIGUID_QUERY | WMIGUID_SET | WMIGUID_EXECUTE)) != 0))
  55. {
  56. //
  57. // If you want to open the guid for notifications then it cannot
  58. // be opened for query and set operations
  59. //
  60. SetLastError(ERROR_INVALID_PARAMETER);
  61. return(ERROR_INVALID_PARAMETER);
  62. }
  63. try
  64. {
  65. *DataBlockHandle = NULL;
  66. Guid = *DataBlockGuid;
  67. } except(EXCEPTION_EXECUTE_HANDLER) {
  68. SetLastError(ERROR_INVALID_PARAMETER);
  69. return(ERROR_INVALID_PARAMETER);
  70. }
  71. if (DesiredAccess == 0)
  72. {
  73. DesiredAccess = ( WMIGUID_QUERY | WMIGUID_SET | WMIGUID_EXECUTE );
  74. }
  75. //
  76. // Obtain a handle for the guid only if it is registered
  77. //
  78. if (DesiredAccess & WMIGUID_NOTIFICATION)
  79. {
  80. //
  81. // Opening a handle strictly for notifications
  82. //
  83. Ioctl = IOCTL_WMI_OPEN_GUID_FOR_EVENTS;
  84. } else {
  85. //
  86. // Otherwise we assume that opening for query/set
  87. //
  88. Ioctl = IOCTL_WMI_OPEN_GUID_FOR_QUERYSET;
  89. }
  90. Status = WmipOpenKernelGuid(&Guid,
  91. DesiredAccess,
  92. &KernelHandle,
  93. Ioctl);
  94. if (Status == ERROR_SUCCESS)
  95. {
  96. //
  97. // if we were able to open the guid then try to return the handle
  98. //
  99. try
  100. {
  101. *DataBlockHandle = KernelHandle;
  102. } except(EXCEPTION_EXECUTE_HANDLER) {
  103. CloseHandle(KernelHandle);
  104. Status = ERROR_INVALID_PARAMETER;
  105. }
  106. }
  107. SetLastError(Status);
  108. return(Status);
  109. }
  110. ULONG
  111. WMIAPI
  112. WmiCloseBlock(
  113. IN WMIHANDLE DataBlockHandle
  114. )
  115. /*+++
  116. Routine Description:
  117. This routine terminates all access to the data block managed by the
  118. data block handle passed and free any resources associated with it. Any
  119. data providers that were providing data blocks for this handle and were
  120. marked as expensive to collect will receive a collection disable request
  121. if this is the last handle to the data block to close.
  122. Arguments:
  123. DataBlockHandle - Handle of data block to which access is closed
  124. Return Value:
  125. Returns ERROR_SUCCESS or an error code.
  126. ---*/
  127. {
  128. ULONG Status;
  129. BOOL Ok;
  130. WmipInitProcessHeap();
  131. try
  132. {
  133. Ok = CloseHandle(DataBlockHandle);
  134. } except(EXCEPTION_EXECUTE_HANDLER) {
  135. //
  136. // We may get an invalid handle exception and if so we catch it here
  137. // and just return an error
  138. //
  139. return(ERROR_INVALID_HANDLE);
  140. }
  141. if (Ok)
  142. {
  143. Status = ERROR_SUCCESS;
  144. } else {
  145. Status = GetLastError();
  146. }
  147. return(Status);
  148. }
  149. ULONG
  150. WMIAPI
  151. WmiQueryAllDataA(
  152. IN WMIHANDLE DataBlockHandle,
  153. IN OUT ULONG *BufferSize,
  154. OUT LPVOID Buffer
  155. )
  156. /*++
  157. Routine Description:
  158. ANSI thunk to WMIQueryAllDataW
  159. NOTE: This api will not translate any unicode strings in the data block
  160. from unicode to ANSI, but will translate the InstanceName string.
  161. --*/
  162. {
  163. ULONG Status;
  164. Status = WmiQueryAllDataW(DataBlockHandle,
  165. BufferSize,
  166. Buffer);
  167. if (Status == ERROR_SUCCESS)
  168. {
  169. Status = WmipConvertWADToAnsi((PWNODE_ALL_DATA)Buffer);
  170. }
  171. return(Status);
  172. }
  173. ULONG
  174. WMIAPI
  175. WmiQueryAllDataW(
  176. IN WMIHANDLE DataBlockHandle,
  177. IN OUT ULONG *InOutBufferSize,
  178. OUT LPVOID OutBuffer
  179. )
  180. /*+++
  181. Routine Description:
  182. This routine allows a data consumer to query for all data items of
  183. all instances of a data block. WMI will call all data providers that
  184. registered for the guid represented by DataBlockHandle with a query all
  185. data request. Each data provider will fill a WNODE_ALL_DATA with all
  186. of its instances of the data block. WMI will link each of the
  187. WNODE_ALL_DATA structures by placing the offset from the current
  188. WNODE_ALL_DATA struccture to the next WNODE_ALL_DATA in the Linkage
  189. field in the WNODE_HEADER. A value of 0 in the Linkage field indicates
  190. that the WNODE_ALL_DATA is the last in the chain.
  191. Arguments:
  192. DataBlockHandle - Handle to data block being queried
  193. *InOutBufferSize - on entry has the maximum size available in Buffer.
  194. If ERROR_BUFFER_TOO_SMALL is returned then returns the size
  195. of buffer needed to return data. The minimum valid buffer
  196. size that can be passed is sizeof(WNODE_TOO_SMALL).
  197. OutBuffer - If ERROR_SUCCESS is returned then the buffer contains a
  198. WNODE_ALL_DATA for the data block.
  199. Return Value:
  200. Returns ERROR_SUCCESS or an error code.
  201. ---*/
  202. {
  203. ULONG SizeNeeded;
  204. PWNODE_HEADER Wnode;
  205. WNODE_ALL_DATA WnodeAllData;
  206. PWNODE_TOO_SMALL WnodeTooSmall = (PWNODE_TOO_SMALL)&WnodeAllData;
  207. ULONG Status;
  208. LPVOID Buffer;
  209. ULONG RetSize;
  210. ULONG BufferSize;
  211. LPVOID BufferAllocated;
  212. WmipInitProcessHeap();
  213. //
  214. // Validate passed Parameters
  215. //
  216. try
  217. {
  218. BufferSize = *InOutBufferSize;
  219. } except(EXCEPTION_EXECUTE_HANDLER) {
  220. SetLastError(ERROR_INVALID_PARAMETER);
  221. return(ERROR_INVALID_PARAMETER);
  222. }
  223. if (BufferSize >= 0x80000000)
  224. {
  225. SetLastError(ERROR_INVALID_PARAMETER);
  226. return(ERROR_INVALID_PARAMETER);
  227. }
  228. //
  229. // If Buffer is not specified or is too small then we can only return
  230. // the size needed.
  231. //
  232. if ((OutBuffer == NULL) || (BufferSize < sizeof(WNODE_ALL_DATA)))
  233. {
  234. Buffer = (LPVOID)WnodeTooSmall;
  235. BufferSize = sizeof(WNODE_ALL_DATA);
  236. BufferAllocated = NULL;
  237. } else {
  238. Buffer = WmipAlloc(BufferSize);
  239. if (Buffer == NULL)
  240. {
  241. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  242. return(ERROR_NOT_ENOUGH_MEMORY);
  243. }
  244. BufferAllocated = Buffer;
  245. }
  246. //
  247. // Build the wnode and pass down to KM for execution
  248. //
  249. Wnode = (PWNODE_HEADER)Buffer;
  250. WmipBuildWnodeHeader(Wnode,
  251. sizeof(WNODE_HEADER),
  252. WNODE_FLAG_ALL_DATA,
  253. DataBlockHandle);
  254. Status = WmipSendWmiRequest(
  255. WMI_GET_ALL_DATA,
  256. Wnode,
  257. sizeof(WNODE_HEADER),
  258. Wnode,
  259. BufferSize,
  260. &RetSize);
  261. if ((Status == ERROR_SUCCESS) &&
  262. ( (RetSize < sizeof(WNODE_HEADER)) ||
  263. (RetSize < Wnode->BufferSize)))
  264. {
  265. //
  266. // If we return success, but the output size is incorrect then we
  267. // flag an error. If this occurs then it indicates some problem
  268. // in the WMI KM code.
  269. //
  270. WmipAssert(FALSE);
  271. Status = ERROR_WMI_DP_FAILED;
  272. }
  273. if (Status == ERROR_SUCCESS)
  274. {
  275. if (Wnode->Flags & WNODE_FLAG_INTERNAL)
  276. {
  277. //
  278. // If this is an internal guid, try the call internally
  279. //
  280. Wnode->Flags &= ~WNODE_FLAG_INTERNAL;
  281. Status = WmipInternalProvider(WmiGetAllData,
  282. Wnode,
  283. BufferSize,
  284. Wnode,
  285. &RetSize);
  286. if (Status != ERROR_SUCCESS)
  287. {
  288. goto done;
  289. }
  290. }
  291. if (Wnode->Flags & WNODE_FLAG_TOO_SMALL)
  292. {
  293. //
  294. // There is not enough room to complete the query so we
  295. // remember how much the data provider needs and then add
  296. // in how much WMI needs for the instance names.
  297. SizeNeeded = ((PWNODE_TOO_SMALL)Wnode)->SizeNeeded;
  298. Status = ERROR_INSUFFICIENT_BUFFER;
  299. } else {
  300. //
  301. // We had enough room so report the size we used
  302. //
  303. SizeNeeded = RetSize;
  304. if (Wnode == (PWNODE_HEADER)WnodeTooSmall)
  305. {
  306. Status = ERROR_INSUFFICIENT_BUFFER;
  307. }
  308. }
  309. //
  310. // Copy back into the caller's buffer the BufferSize and the Buffer
  311. //
  312. try
  313. {
  314. *InOutBufferSize = SizeNeeded;
  315. if ((Status == ERROR_SUCCESS) &&
  316. (Wnode != (PWNODE_HEADER)WnodeTooSmall))
  317. {
  318. memcpy(OutBuffer, Buffer, SizeNeeded);
  319. Status = ERROR_SUCCESS;
  320. }
  321. } except(EXCEPTION_EXECUTE_HANDLER) {
  322. Status = ERROR_INVALID_PARAMETER;
  323. }
  324. }
  325. done:
  326. if (BufferAllocated != NULL)
  327. {
  328. WmipFree(BufferAllocated);
  329. }
  330. SetLastError(Status);
  331. return(Status);
  332. }
  333. ULONG
  334. WMIAPI
  335. WmiQueryAllDataMultipleA(
  336. IN WMIHANDLE *HandleList,
  337. IN ULONG HandleCount,
  338. IN OUT ULONG *InOutBufferSize,
  339. OUT LPVOID OutBuffer
  340. )
  341. {
  342. ULONG Status;
  343. WmipInitProcessHeap();
  344. Status = WmiQueryAllDataMultipleW(HandleList,
  345. HandleCount,
  346. InOutBufferSize,
  347. OutBuffer);
  348. if ((Status == ERROR_SUCCESS) && (*InOutBufferSize > 0))
  349. {
  350. Status = WmipConvertWADToAnsi((PWNODE_ALL_DATA)OutBuffer);
  351. }
  352. return(Status);
  353. }
  354. ULONG
  355. WMIAPI
  356. WmiQueryAllDataMultipleW(
  357. IN WMIHANDLE *HandleList,
  358. IN ULONG HandleCount,
  359. IN OUT ULONG *InOutBufferSize,
  360. OUT LPVOID OutBuffer
  361. )
  362. {
  363. PWMIQADMULTIPLE QadMultiple;
  364. ULONG RetSize;
  365. ULONG QadMultipleSize;
  366. ULONG i;
  367. ULONG OutBufferSize;
  368. ULONG Status;
  369. WNODE_TOO_SMALL WnodeTooSmall;
  370. PWNODE_HEADER Wnode;
  371. WmipInitProcessHeap();
  372. if ((HandleCount != 0) && (HandleCount < QUERYMULIPLEHANDLELIMIT))
  373. {
  374. QadMultipleSize = sizeof(WMIQADMULTIPLE) +
  375. ((HandleCount-1) * sizeof(HANDLE3264));
  376. QadMultiple = WmipAlloc(QadMultipleSize);
  377. if (QadMultiple != NULL)
  378. {
  379. QadMultiple->HandleCount = HandleCount;
  380. try
  381. {
  382. for (i = 0; i < HandleCount; i++)
  383. {
  384. WmipSetHandle3264(QadMultiple->Handles[i], HandleList[i]);
  385. }
  386. OutBufferSize = *InOutBufferSize;
  387. } except(EXCEPTION_EXECUTE_HANDLER) {
  388. WmipFree(QadMultiple);
  389. SetLastError(ERROR_NOACCESS);
  390. return(ERROR_NOACCESS);
  391. }
  392. if (OutBufferSize < sizeof(WNODE_ALL_DATA))
  393. {
  394. Wnode = (PWNODE_HEADER)&WnodeTooSmall;
  395. OutBufferSize = sizeof(WNODE_TOO_SMALL);
  396. } else {
  397. Wnode = (PWNODE_HEADER)OutBuffer;
  398. }
  399. Status = WmipSendWmiKMRequest(NULL,
  400. IOCTL_WMI_QAD_MULTIPLE,
  401. QadMultiple,
  402. QadMultipleSize,
  403. Wnode,
  404. OutBufferSize,
  405. &RetSize,
  406. NULL);
  407. WmipFree(QadMultiple);
  408. if (Status == ERROR_SUCCESS)
  409. {
  410. if (Wnode->Flags & WNODE_FLAG_TOO_SMALL)
  411. {
  412. RetSize = ((PWNODE_TOO_SMALL)(Wnode))->SizeNeeded;
  413. Status = ERROR_INSUFFICIENT_BUFFER;
  414. } else if (Wnode == (PWNODE_HEADER)&WnodeTooSmall) {
  415. Status = ERROR_INSUFFICIENT_BUFFER;
  416. }
  417. try
  418. {
  419. *InOutBufferSize = RetSize;
  420. } except(EXCEPTION_EXECUTE_HANDLER) {
  421. Status = ERROR_NOACCESS;
  422. }
  423. }
  424. } else {
  425. Status = ERROR_NOT_ENOUGH_MEMORY;
  426. }
  427. } else {
  428. Status = ERROR_INVALID_PARAMETER;
  429. }
  430. SetLastError(Status);
  431. return(Status);
  432. }
  433. ULONG
  434. WMIAPI
  435. WmiQuerySingleInstanceA(
  436. IN WMIHANDLE DataBlockHandle,
  437. IN LPCSTR InstanceName,
  438. IN OUT ULONG *BufferSize,
  439. OUT LPVOID Buffer
  440. )
  441. /*++
  442. Routine Description:
  443. ANSI thunk to WMIQuerySingleInstanceW
  444. NOTE: This api will not translate any unicode strings in the data block
  445. from unicode to ANSI, but will translate the InstanceName string.
  446. --*/
  447. {
  448. LPWSTR InstanceNameUnicode;
  449. ULONG Status;
  450. PWNODE_SINGLE_INSTANCE Wnode;
  451. PWCHAR Ptr;
  452. WmipInitProcessHeap();
  453. InstanceNameUnicode = NULL;
  454. Status = AnsiToUnicode(InstanceName, &InstanceNameUnicode);
  455. if (Status == ERROR_SUCCESS)
  456. {
  457. Status = WmiQuerySingleInstanceW(DataBlockHandle,
  458. InstanceNameUnicode,
  459. BufferSize,
  460. Buffer);
  461. if (Status == ERROR_SUCCESS)
  462. {
  463. //
  464. // Convert Instance name from unicode back to ANSI. We assume
  465. // that the ansi size will never be larger than the unicode size
  466. // so we can convert in place.
  467. Wnode = (PWNODE_SINGLE_INSTANCE)Buffer;
  468. Ptr = (PWCHAR)(((PUCHAR)Buffer) + Wnode->OffsetInstanceName);
  469. Status = WmipCountedUnicodeToCountedAnsi(Ptr, (PCHAR)Ptr);
  470. if (Status != ERROR_SUCCESS)
  471. {
  472. SetLastError(Status);
  473. } else {
  474. Wnode->WnodeHeader.Flags |= WNODE_FLAG_ANSI_INSTANCENAMES;
  475. }
  476. }
  477. if (InstanceNameUnicode != NULL)
  478. {
  479. WmipFree(InstanceNameUnicode);
  480. }
  481. }
  482. return(Status);
  483. }
  484. ULONG
  485. WMIAPI
  486. WmiQuerySingleInstanceW(
  487. IN WMIHANDLE DataBlockHandle,
  488. IN LPCWSTR InstanceName,
  489. IN OUT ULONG *InOutBufferSize,
  490. OUT LPVOID OutBuffer
  491. )
  492. /*+++
  493. Routine Description:
  494. This routine will query a single data provider for the values of a single
  495. instance of the data block represented by the DataBlockHandle. WMI will
  496. determine the appropriate data provider to which to send a query single
  497. instance request and if successful return a WNODE_SINGLE_INSTANCE to
  498. the caller.
  499. Arguments:
  500. DataBlockHandle - Handle to data block to query
  501. InstanceName - name of the instance for which data is being queried
  502. *BufferSize - on entry has the maximum size available in pBuffer. If
  503. ERROR_BUFFER_TOO_SMALL is returned then returns the size of
  504. buffer needed to return data. The minimum valid buffer
  505. size that can be passed is sizeof(WNODE_TOO_SMALL).
  506. Buffer - If ERROR_SUCCESS is returned then the buffer contains a
  507. WNODE_SINGLE_ITEM for the data block.
  508. Return Value:
  509. Returns ERROR_SUCCESS or an error code.
  510. ---*/
  511. {
  512. PWNODE_SINGLE_INSTANCE Wnode;
  513. ULONG Status, ReturnStatus;
  514. PWCHAR WnodePtr;
  515. ULONG BufferNeeded;
  516. ULONG BufferSize;
  517. LPVOID Buffer;
  518. ULONG RetSize;
  519. ULONG InstanceNameLen;
  520. WmipInitProcessHeap();
  521. //
  522. // Validate input parameters
  523. //
  524. if ((InstanceName == NULL) ||
  525. (InOutBufferSize == NULL))
  526. {
  527. SetLastError(ERROR_INVALID_PARAMETER);
  528. return(ERROR_INVALID_PARAMETER);
  529. }
  530. //
  531. // Calculate the size of the buffer needed to build the WNODE to send
  532. // to the driver. We add up the WNODE_SINGLE_INSTANCE header, the
  533. // instance name length and text and pad it out to an 8 byte boundry
  534. //
  535. try
  536. {
  537. InstanceNameLen = wcslen(InstanceName) * sizeof(WCHAR);
  538. BufferSize = *InOutBufferSize;
  539. } except(EXCEPTION_EXECUTE_HANDLER) {
  540. SetLastError(ERROR_INVALID_PARAMETER);
  541. return(ERROR_INVALID_PARAMETER);
  542. }
  543. //
  544. // Make sure we have a resonable buffer size
  545. //
  546. if (BufferSize >= 0x80000000)
  547. {
  548. SetLastError(ERROR_INVALID_PARAMETER);
  549. return(ERROR_INVALID_PARAMETER);
  550. }
  551. BufferNeeded = (FIELD_OFFSET(WNODE_SINGLE_INSTANCE,
  552. VariableData) +
  553. InstanceNameLen +
  554. sizeof(USHORT) + 7) & ~7;
  555. //
  556. // if user passed a NULL buffer or one that is smaller than the
  557. // size needed to hold the WNODE then we allocate a small buffer on
  558. // its behalf and call to obtain the size needed.
  559. if ((OutBuffer == NULL) ||
  560. (BufferSize < BufferNeeded))
  561. {
  562. BufferSize = BufferNeeded;
  563. }
  564. Buffer = WmipAlloc(BufferSize);
  565. if (Buffer == NULL)
  566. {
  567. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  568. return(ERROR_NOT_ENOUGH_MEMORY);
  569. }
  570. //
  571. // Build WNODE we want to send to the DP
  572. //
  573. Wnode = (PWNODE_SINGLE_INSTANCE)Buffer;
  574. memset(Wnode, 0, FIELD_OFFSET(WNODE_SINGLE_INSTANCE,
  575. VariableData));
  576. WmipBuildWnodeHeader(&Wnode->WnodeHeader,
  577. BufferNeeded,
  578. WNODE_FLAG_SINGLE_INSTANCE,
  579. DataBlockHandle);
  580. Wnode->OffsetInstanceName = FIELD_OFFSET(WNODE_SINGLE_INSTANCE,
  581. VariableData);
  582. Wnode->DataBlockOffset = BufferNeeded;
  583. //
  584. // Copy InstanceName into the WnodeSingleInstance for the query.
  585. //
  586. WnodePtr = (PWCHAR)OffsetToPtr(Wnode, Wnode->OffsetInstanceName);
  587. *WnodePtr++ = (USHORT)InstanceNameLen;
  588. try
  589. {
  590. memcpy(WnodePtr, InstanceName, InstanceNameLen);
  591. } except(EXCEPTION_EXECUTE_HANDLER) {
  592. WmipFree(Buffer);
  593. SetLastError(ERROR_INVALID_PARAMETER);
  594. return(ERROR_INVALID_PARAMETER);
  595. }
  596. Status = WmipSendWmiRequest(
  597. WMI_GET_SINGLE_INSTANCE,
  598. (PWNODE_HEADER)Wnode,
  599. BufferNeeded,
  600. Wnode,
  601. BufferSize,
  602. &RetSize);
  603. if (Status == ERROR_SUCCESS)
  604. {
  605. //
  606. // Successful return, we either have success or a buffer too small
  607. //
  608. if ((RetSize < sizeof(WNODE_HEADER) ||
  609. ((RetSize >= sizeof(ULONG)) &&
  610. (RetSize < Wnode->WnodeHeader.BufferSize))))
  611. {
  612. //
  613. // if we get an incosistent WNODE back this may indicate a
  614. // problem with the WMI KM code
  615. //
  616. Status = ERROR_WMI_DP_FAILED;
  617. WmipAssert(FALSE);
  618. } else {
  619. if (Wnode->WnodeHeader.Flags & WNODE_FLAG_INTERNAL)
  620. {
  621. //
  622. // If this is an internal guid, try the call internally
  623. //
  624. Wnode->WnodeHeader.Flags &= ~WNODE_FLAG_INTERNAL;
  625. Wnode->WnodeHeader.BufferSize = BufferNeeded;
  626. Status = WmipInternalProvider( WmiGetSingleInstance,
  627. (PWNODE_HEADER)Wnode,
  628. BufferSize,
  629. Wnode,
  630. &RetSize);
  631. if (Status != ERROR_SUCCESS)
  632. {
  633. goto done;
  634. }
  635. }
  636. if (Wnode->WnodeHeader.Flags & WNODE_FLAG_TOO_SMALL)
  637. {
  638. //
  639. // Our buffer was too small so try to return the size needed
  640. //
  641. Status = ERROR_INSUFFICIENT_BUFFER;
  642. try
  643. {
  644. *InOutBufferSize = ((PWNODE_TOO_SMALL)Wnode)->SizeNeeded;
  645. } except(EXCEPTION_EXECUTE_HANDLER) {
  646. Status = ERROR_INVALID_PARAMETER;
  647. }
  648. } else {
  649. //
  650. // We have a result from our query so we just copy back
  651. // the results.
  652. //
  653. try
  654. {
  655. if (*InOutBufferSize >= RetSize)
  656. {
  657. memcpy(OutBuffer, Wnode, RetSize);
  658. } else {
  659. Status = ERROR_INSUFFICIENT_BUFFER;
  660. }
  661. *InOutBufferSize = RetSize;
  662. } except(EXCEPTION_EXECUTE_HANDLER) {
  663. Status = ERROR_INVALID_PARAMETER;
  664. }
  665. }
  666. }
  667. }
  668. done:
  669. WmipFree(Buffer);
  670. SetLastError(Status);
  671. return(Status);
  672. }
  673. ULONG
  674. WMIAPI
  675. WmiQuerySingleInstanceMultipleW(
  676. IN WMIHANDLE *HandleList,
  677. IN LPCWSTR *InstanceNames,
  678. IN ULONG HandleCount,
  679. IN OUT ULONG *InOutBufferSize,
  680. OUT LPVOID OutBuffer
  681. )
  682. {
  683. ULONG Status;
  684. WNODE_TOO_SMALL WnodeTooSmall;
  685. ULONG i;
  686. ULONG OutBufferSize;
  687. ULONG QsiMultipleSize;
  688. ULONG Len;
  689. PWMIQSIMULTIPLE QsiMultiple;
  690. PWNODE_HEADER Wnode;
  691. ULONG RetSize;
  692. HANDLE Handle;
  693. WmipInitProcessHeap();
  694. if ((HandleCount != 0) && (HandleCount < QUERYMULIPLEHANDLELIMIT))
  695. {
  696. QsiMultipleSize = sizeof(WMIQSIMULTIPLE) +
  697. ((HandleCount-1)*sizeof(WMIQSIINFO));
  698. QsiMultiple = WmipAlloc(QsiMultipleSize);
  699. if (QsiMultiple != NULL)
  700. {
  701. try
  702. {
  703. OutBufferSize = *InOutBufferSize;
  704. QsiMultiple->QueryCount = HandleCount;
  705. for (i = 0; i < HandleCount; i++)
  706. {
  707. Handle = HandleList[i];
  708. WmipSetHandle3264(QsiMultiple->QsiInfo[i].Handle, Handle);
  709. #if defined(_WIN64)
  710. QsiMultiple->QsiInfo[i].InstanceName.Buffer = (PWSTR)InstanceNames[i];
  711. #else
  712. QsiMultiple->QsiInfo[i].InstanceName.Dummy = (ULONG64)(IntToPtr(PtrToInt(InstanceNames[i])));
  713. #endif
  714. Len = wcslen(InstanceNames[i]) * sizeof(WCHAR);
  715. QsiMultiple->QsiInfo[i].InstanceName.Length = (USHORT)Len;
  716. QsiMultiple->QsiInfo[i].InstanceName.MaximumLength = (USHORT)Len;
  717. }
  718. } except(EXCEPTION_EXECUTE_HANDLER) {
  719. WmipFree(QsiMultiple);
  720. SetLastError(ERROR_NOACCESS);
  721. return(ERROR_NOACCESS);
  722. }
  723. if (OutBufferSize < sizeof(WNODE_TOO_SMALL))
  724. {
  725. Wnode = (PWNODE_HEADER)&WnodeTooSmall;
  726. OutBufferSize = sizeof(WNODE_TOO_SMALL);
  727. } else {
  728. Wnode = (PWNODE_HEADER)OutBuffer;
  729. }
  730. Status = WmipSendWmiKMRequest(NULL,
  731. IOCTL_WMI_QSI_MULTIPLE,
  732. QsiMultiple,
  733. QsiMultipleSize,
  734. Wnode,
  735. OutBufferSize,
  736. &RetSize,
  737. NULL);
  738. WmipFree(QsiMultiple);
  739. if (Status == ERROR_SUCCESS)
  740. {
  741. if (Wnode->Flags & WNODE_FLAG_TOO_SMALL)
  742. {
  743. RetSize = ((PWNODE_TOO_SMALL)(Wnode))->SizeNeeded;
  744. Status = ERROR_INSUFFICIENT_BUFFER;
  745. }
  746. try
  747. {
  748. *InOutBufferSize = RetSize;
  749. } except(EXCEPTION_EXECUTE_HANDLER) {
  750. Status = ERROR_NOACCESS;
  751. }
  752. }
  753. } else {
  754. Status = ERROR_NOT_ENOUGH_MEMORY;
  755. }
  756. } else {
  757. Status = ERROR_INVALID_PARAMETER;
  758. }
  759. SetLastError(Status);
  760. return(Status);
  761. }
  762. ULONG
  763. WMIAPI
  764. WmiQuerySingleInstanceMultipleA(
  765. IN WMIHANDLE *HandleList,
  766. IN LPCSTR *InstanceNames,
  767. IN ULONG HandleCount,
  768. IN OUT ULONG *InOutBufferSize,
  769. OUT LPVOID OutBuffer
  770. )
  771. {
  772. ULONG Status;
  773. ULONG Linkage;
  774. PWNODE_SINGLE_INSTANCE Wnode;
  775. PWCHAR Ptr;
  776. PWCHAR *UnicodeInstanceNames;
  777. ULONG UnicodeInstanceNamesSize;
  778. ULONG i;
  779. WmipInitProcessHeap();
  780. if ((HandleCount != 0) && (HandleCount < QUERYMULIPLEHANDLELIMIT))
  781. {
  782. UnicodeInstanceNamesSize = HandleCount * sizeof(PWCHAR);
  783. UnicodeInstanceNames = WmipAlloc(UnicodeInstanceNamesSize);
  784. if (UnicodeInstanceNames != NULL)
  785. {
  786. memset(UnicodeInstanceNames, 0, UnicodeInstanceNamesSize);
  787. for (i = 0; i < HandleCount; i++)
  788. {
  789. Status = AnsiToUnicode(InstanceNames[i],
  790. &UnicodeInstanceNames[i]);
  791. if (Status != ERROR_SUCCESS)
  792. {
  793. goto Cleanup;
  794. }
  795. }
  796. Status = WmiQuerySingleInstanceMultipleW(HandleList,
  797. UnicodeInstanceNames,
  798. HandleCount,
  799. InOutBufferSize,
  800. OutBuffer);
  801. if ((Status == ERROR_SUCCESS) && (*InOutBufferSize > 0))
  802. {
  803. Linkage = 1;
  804. Wnode = (PWNODE_SINGLE_INSTANCE)OutBuffer;
  805. while ((Status == ERROR_SUCCESS) && (Linkage != 0))
  806. {
  807. Ptr = (PWCHAR)OffsetToPtr(Wnode, Wnode->OffsetInstanceName);
  808. Status = WmipCountedUnicodeToCountedAnsi(Ptr, (PCHAR)Ptr);
  809. Linkage = Wnode->WnodeHeader.Linkage;
  810. Wnode = (PWNODE_SINGLE_INSTANCE)OffsetToPtr(Wnode, Linkage);
  811. }
  812. }
  813. Cleanup:
  814. for (i = 0; i < HandleCount; i++)
  815. {
  816. if (UnicodeInstanceNames[i] != NULL)
  817. {
  818. if (UnicodeInstanceNames[i] != NULL)
  819. {
  820. WmipFree(UnicodeInstanceNames[i]);
  821. }
  822. }
  823. }
  824. WmipFree(UnicodeInstanceNames);
  825. } else {
  826. Status = ERROR_NOT_ENOUGH_MEMORY;
  827. }
  828. } else {
  829. Status = ERROR_INVALID_PARAMETER;
  830. }
  831. SetLastError(Status);
  832. return(Status);
  833. }
  834. ULONG
  835. WMIAPI
  836. WmiSetSingleInstanceA(
  837. IN WMIHANDLE DataBlockHandle,
  838. IN LPCSTR InstanceName,
  839. IN ULONG Version,
  840. IN ULONG ValueBufferSize,
  841. IN LPVOID ValueBuffer
  842. )
  843. /*++
  844. Routine Description:
  845. ANSI thunk to WMISetSingleInstanceW
  846. NOTE: This api will not translate any fields in the returned WNODE
  847. from unicode to ANSI.
  848. --*/
  849. {
  850. ULONG Status;
  851. LPWSTR InstanceNameUnicode;
  852. WmipInitProcessHeap();
  853. InstanceNameUnicode = NULL;
  854. Status = AnsiToUnicode(InstanceName, &InstanceNameUnicode);
  855. if (Status == ERROR_SUCCESS)
  856. {
  857. Status = WmiSetSingleInstanceW(DataBlockHandle,
  858. InstanceNameUnicode,
  859. Version,
  860. ValueBufferSize,
  861. ValueBuffer);
  862. if (InstanceNameUnicode != NULL)
  863. {
  864. WmipFree(InstanceNameUnicode);
  865. }
  866. }
  867. return(Status);
  868. }
  869. ULONG
  870. WMIAPI
  871. WmiSetSingleInstanceW(
  872. IN WMIHANDLE DataBlockHandle,
  873. IN LPCWSTR InstanceName,
  874. IN ULONG Version,
  875. IN ULONG ValueBufferSize,
  876. IN LPVOID ValueBuffer
  877. )
  878. /*+++
  879. Routine Description:
  880. This routine will send a set single instance request to the appropriate
  881. data provider to request changing all data items for a single instances
  882. of a data block. A data provider is free to silently ignore any change
  883. requests or only change some data items within an instance.
  884. Arguments:
  885. DataBlockHandle - Handle to data block
  886. InstanceName - name of the instance for which data is being set
  887. Version - specifies the version of the data block being passed in
  888. ValueBuffer
  889. ValueBufferSize - on entry has the size of the data block containing the
  890. new values for the instance of the data block passed in
  891. ValueBuffer
  892. ValueBuffer - passes new values for instance
  893. Return Value:
  894. Returns ERROR_SUCCESS or an error code.
  895. ---*/
  896. {
  897. PWNODE_SINGLE_INSTANCE Wnode;
  898. ULONG InstanceNameLen;
  899. ULONG Status;
  900. PWCHAR WnodePtr;
  901. ULONG BufferSize;
  902. ULONG RetSize;
  903. WmipInitProcessHeap();
  904. //
  905. // Validate input parameters
  906. if ((InstanceName == NULL) ||
  907. (ValueBuffer == NULL))
  908. {
  909. SetLastError(ERROR_INVALID_PARAMETER);
  910. return(ERROR_INVALID_PARAMETER);
  911. }
  912. try
  913. {
  914. InstanceNameLen = wcslen(InstanceName) * sizeof(WCHAR);
  915. } except(EXCEPTION_EXECUTE_HANDLER) {
  916. SetLastError(ERROR_INVALID_PARAMETER);
  917. return(ERROR_INVALID_PARAMETER);
  918. }
  919. //
  920. // The WNODE_SINGLE_INSTANCE that we need to send to the data provider
  921. // must be large enough to hold the WNODE, the instance name of the
  922. // item being set, padding so that the data block is on a 8 byte
  923. // boundry and space for the new data block.
  924. BufferSize = FIELD_OFFSET(WNODE_SINGLE_INSTANCE, VariableData) +
  925. InstanceNameLen + sizeof(USHORT) + ValueBufferSize + 7;
  926. Wnode = WmipAlloc(BufferSize);
  927. if (Wnode == NULL)
  928. {
  929. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  930. return(ERROR_NOT_ENOUGH_MEMORY);
  931. }
  932. //
  933. // Build WNODE we want to send to the DP
  934. //
  935. memset(Wnode, 0, FIELD_OFFSET(WNODE_SINGLE_INSTANCE, VariableData));
  936. WmipBuildWnodeHeader(&Wnode->WnodeHeader,
  937. BufferSize,
  938. WNODE_FLAG_SINGLE_INSTANCE,
  939. DataBlockHandle);
  940. Wnode->WnodeHeader.Version = Version;
  941. Wnode->SizeDataBlock = ValueBufferSize;
  942. Wnode->OffsetInstanceName = FIELD_OFFSET(WNODE_SINGLE_INSTANCE,
  943. VariableData);
  944. WnodePtr = (PWCHAR)OffsetToPtr(Wnode, Wnode->OffsetInstanceName);
  945. *WnodePtr++ = (USHORT)InstanceNameLen;
  946. Wnode->DataBlockOffset = (Wnode->OffsetInstanceName +
  947. InstanceNameLen + sizeof(USHORT) + 7) & ~7;
  948. try
  949. {
  950. memcpy(WnodePtr, InstanceName, InstanceNameLen);
  951. memcpy((PCHAR)Wnode + Wnode->DataBlockOffset,
  952. ValueBuffer,
  953. ValueBufferSize);
  954. } except(EXCEPTION_EXECUTE_HANDLER) {
  955. WmipFree(Wnode);
  956. SetLastError(ERROR_INVALID_PARAMETER);
  957. return(ERROR_INVALID_PARAMETER);
  958. }
  959. //
  960. // Send down the set request and reprot the results
  961. //
  962. Status = WmipSendWmiRequest(
  963. WMI_SET_SINGLE_INSTANCE,
  964. (PWNODE_HEADER)Wnode,
  965. BufferSize,
  966. Wnode,
  967. ValueBufferSize,
  968. &RetSize);
  969. WmipFree(Wnode);
  970. SetLastError(Status);
  971. return(Status);
  972. }
  973. ULONG
  974. WMIAPI
  975. WmiSetSingleItemA(
  976. IN WMIHANDLE DataBlockHandle,
  977. IN LPCSTR InstanceName,
  978. IN ULONG DataItemId,
  979. IN ULONG Version,
  980. IN ULONG ValueBufferSize,
  981. IN LPVOID ValueBuffer
  982. )
  983. /*++
  984. Routine Description:
  985. ANSI thunk to WMISetSingleItemA
  986. NOTE: This api will not translate any fields in the returned WNODE
  987. from unicode to ANSI.
  988. --*/
  989. {
  990. ULONG Status;
  991. LPWSTR InstanceNameUnicode;
  992. WmipInitProcessHeap();
  993. InstanceNameUnicode = NULL;
  994. Status = AnsiToUnicode(InstanceName, &InstanceNameUnicode);
  995. if (Status == ERROR_SUCCESS)
  996. {
  997. Status = WmiSetSingleItemW(DataBlockHandle,
  998. InstanceNameUnicode,
  999. DataItemId,
  1000. Version,
  1001. ValueBufferSize,
  1002. ValueBuffer);
  1003. if (InstanceNameUnicode != NULL)
  1004. {
  1005. WmipFree(InstanceNameUnicode);
  1006. }
  1007. }
  1008. return(Status);
  1009. }
  1010. ULONG
  1011. WMIAPI
  1012. WmiSetSingleItemW(
  1013. IN WMIHANDLE DataBlockHandle,
  1014. IN LPCWSTR InstanceName,
  1015. IN ULONG DataItemId,
  1016. IN ULONG Version,
  1017. IN ULONG ValueBufferSize,
  1018. IN LPVOID ValueBuffer
  1019. )
  1020. /*+++
  1021. Routine Description:
  1022. This routine will send a set single item request to the appropriate data
  1023. provider to request changing a specific data item within a specific
  1024. instance of a data block. A data provider can silently ignore a change
  1025. request.
  1026. Arguments:
  1027. DataBlockHandle - Handle to data block
  1028. InstanceName - name of the instance for which data is being set
  1029. Version - specifies the version of the data block being passed in
  1030. ValueBuffer
  1031. DataItemId - Data item id of item to set
  1032. ValueBufferSize - on entry has the size of the new value for the
  1033. data item which is passed in pBuffer.
  1034. ValueBuffer - passes new value for data item
  1035. Return Value:
  1036. Returns ERROR_SUCCESS or an error code.
  1037. ---*/
  1038. {
  1039. PWNODE_SINGLE_ITEM Wnode;
  1040. ULONG InstanceNameLen;
  1041. ULONG Status;
  1042. PBYTE WnodeBuffer;
  1043. PWCHAR WnodePtr;
  1044. ULONG BufferSize;
  1045. ULONG RetSize;
  1046. WmipInitProcessHeap();
  1047. //
  1048. // Validate passed parameters
  1049. //
  1050. if ((InstanceName == NULL) ||
  1051. (ValueBuffer == NULL))
  1052. {
  1053. SetLastError(ERROR_INVALID_PARAMETER);
  1054. return(ERROR_INVALID_PARAMETER);
  1055. }
  1056. try
  1057. {
  1058. InstanceNameLen = wcslen(InstanceName) * sizeof(WCHAR);
  1059. } except(EXCEPTION_EXECUTE_HANDLER) {
  1060. SetLastError(ERROR_INVALID_PARAMETER);
  1061. return(ERROR_INVALID_PARAMETER);
  1062. }
  1063. BufferSize = FIELD_OFFSET(WNODE_SINGLE_ITEM, VariableData) +
  1064. InstanceNameLen + sizeof(USHORT) +
  1065. ValueBufferSize + 7;
  1066. Wnode = WmipAlloc(BufferSize);
  1067. if (Wnode == NULL)
  1068. {
  1069. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1070. return(ERROR_NOT_ENOUGH_MEMORY);
  1071. }
  1072. //
  1073. // Build WNODE we want to send to the DP
  1074. memset(Wnode, 0, FIELD_OFFSET(WNODE_SINGLE_ITEM, VariableData));
  1075. WmipBuildWnodeHeader(&Wnode->WnodeHeader,
  1076. BufferSize,
  1077. WNODE_FLAG_SINGLE_ITEM,
  1078. DataBlockHandle);
  1079. Wnode->WnodeHeader.Version = Version;
  1080. Wnode->ItemId = DataItemId;
  1081. Wnode->SizeDataItem = ValueBufferSize;
  1082. Wnode->OffsetInstanceName = FIELD_OFFSET(WNODE_SINGLE_ITEM,VariableData);
  1083. Wnode->DataBlockOffset = (Wnode->OffsetInstanceName +
  1084. InstanceNameLen + sizeof(USHORT) + 7) & ~7;
  1085. WnodePtr = (PWCHAR)OffsetToPtr(Wnode, Wnode->OffsetInstanceName);
  1086. *WnodePtr++ = (USHORT)InstanceNameLen;
  1087. try
  1088. {
  1089. memcpy(WnodePtr, InstanceName, InstanceNameLen);
  1090. memcpy((PCHAR)Wnode + Wnode->DataBlockOffset,
  1091. ValueBuffer,
  1092. ValueBufferSize);
  1093. } except(EXCEPTION_EXECUTE_HANDLER) {
  1094. Status = ERROR_INVALID_PARAMETER;
  1095. WmipFree(Wnode);
  1096. SetLastError(Status);
  1097. return(Status);
  1098. }
  1099. //
  1100. // Send down the request and report the result
  1101. //
  1102. Status = WmipSendWmiRequest(
  1103. WMI_SET_SINGLE_ITEM,
  1104. (PWNODE_HEADER)Wnode,
  1105. BufferSize,
  1106. Wnode,
  1107. ValueBufferSize,
  1108. &RetSize);
  1109. WmipFree(Wnode);
  1110. SetLastError(Status);
  1111. return(Status);
  1112. }
  1113. ULONG
  1114. WMIAPI
  1115. WmiExecuteMethodA(
  1116. IN WMIHANDLE MethodDataBlockHandle,
  1117. IN LPCSTR MethodInstanceName,
  1118. IN ULONG MethodId,
  1119. IN ULONG InputValueBufferSize,
  1120. IN LPVOID InputValueBuffer,
  1121. IN OUT ULONG *OutputBufferSize,
  1122. OUT PVOID OutputBuffer
  1123. )
  1124. /*++
  1125. Routine Description:
  1126. ANSI thunk to WmiExecuteMethodW
  1127. NOTE: This api will not translate any fields in the returned WNODE
  1128. from unicode to ANSI.
  1129. --*/
  1130. {
  1131. ULONG Status;
  1132. LPWSTR MethodInstanceNameUnicode;
  1133. LPWSTR InputInstanceNameUnicode;
  1134. PWCHAR Ptr;
  1135. WmipInitProcessHeap();
  1136. if (MethodInstanceName == NULL)
  1137. {
  1138. return(ERROR_INVALID_PARAMETER);
  1139. }
  1140. MethodInstanceNameUnicode = NULL;
  1141. Status = AnsiToUnicode(MethodInstanceName,
  1142. &MethodInstanceNameUnicode);
  1143. if (Status == ERROR_SUCCESS)
  1144. {
  1145. Status = WmiExecuteMethodW(MethodDataBlockHandle,
  1146. MethodInstanceNameUnicode,
  1147. MethodId,
  1148. InputValueBufferSize,
  1149. InputValueBuffer,
  1150. OutputBufferSize,
  1151. OutputBuffer);
  1152. if (MethodInstanceNameUnicode != NULL)
  1153. {
  1154. WmipFree(MethodInstanceNameUnicode);
  1155. }
  1156. }
  1157. return(Status);
  1158. }
  1159. ULONG
  1160. WMIAPI
  1161. WmiExecuteMethodW(
  1162. IN WMIHANDLE MethodDataBlockHandle,
  1163. IN LPCWSTR MethodInstanceName,
  1164. IN ULONG MethodId,
  1165. IN ULONG InputValueBufferSize,
  1166. IN LPVOID InputValueBuffer,
  1167. IN OUT ULONG *OutputBufferSize,
  1168. OUT PVOID OutputBuffer
  1169. )
  1170. /*+++
  1171. Routine Description:
  1172. This routine will invoke a method on a WMI data provider. A method is a
  1173. call to have the data provider do something rather than a query or a
  1174. set. A WNODE_SINGLE_INSTANCE is built as the input parameters to a
  1175. method and a WNODE_SINGLE_INSTANCE is returned as output from a method.
  1176. Arguments:
  1177. MethodDataBlockHandle - Handle to data block that contains method
  1178. MethodInstanceName - Name of instance of data block on which the method
  1179. should be executed.
  1180. MethodId - Id value that specifies which method within the guid to
  1181. execute.
  1182. InputValueBufferSize - on entry has the size of the data block containing the
  1183. values for the instance of the data block passed in
  1184. ValueBuffer that serves as the input parameters
  1185. InputValueBuffer - passes new values for instance that serves as the
  1186. input parameters. This can be NULL if there is no input
  1187. *OutputBufferSize - on entry has the maxiumum size in bytes that can be
  1188. written into Buffer and on return contains the actual
  1189. number of bytes written into Buffer. This can be NULL
  1190. if no output is expected to be returned, however if output
  1191. is returned the caller will not know how large a buffer
  1192. is needed to return it.
  1193. OutputBuffer - buffer in which to return the output WNODE_SINGLE_INSTANCE.
  1194. This can be NULL if there is no output WNODE or the
  1195. caller wants to determine the size needed for the
  1196. output WNODE.
  1197. Return Value:
  1198. Returns ERROR_SUCCESS or an error code.
  1199. ---*/
  1200. {
  1201. PWNODE_METHOD_ITEM MethodWnode;
  1202. PWNODE_HEADER WnodeHeader;
  1203. ULONG MethodInstanceNameLen;
  1204. ULONG MethodWnodeSize, MethodWnodeOffset;
  1205. ULONG Status;
  1206. ULONG BufferSize;
  1207. PWCHAR InstanceNamePtr;
  1208. ULONG OutSize;
  1209. PUCHAR DataPtr;
  1210. ULONG BaseMethodWnodeSize;
  1211. ULONG RetSize;
  1212. WmipInitProcessHeap();
  1213. //
  1214. // Validate input parameters
  1215. if ((MethodInstanceName == NULL) ||
  1216. ((InputValueBuffer == NULL) &&
  1217. (InputValueBufferSize != 0)))
  1218. {
  1219. //
  1220. // All input parameters must be specifies or all input parameters
  1221. // must NOT be specified.
  1222. SetLastError(ERROR_INVALID_PARAMETER);
  1223. return(ERROR_INVALID_PARAMETER);
  1224. }
  1225. //
  1226. // Caller can pass a NULL output buffer when he only wants to get the
  1227. // size needed for the output buffer or the method returns a void.
  1228. //
  1229. if (OutputBuffer == NULL)
  1230. {
  1231. BufferSize = 0;
  1232. } else {
  1233. if (OutputBufferSize != NULL)
  1234. {
  1235. try
  1236. {
  1237. BufferSize = *OutputBufferSize;
  1238. } except(EXCEPTION_EXECUTE_HANDLER) {
  1239. SetLastError(ERROR_INVALID_PARAMETER);
  1240. return(ERROR_INVALID_PARAMETER);
  1241. }
  1242. if (BufferSize >= 0x80000000)
  1243. {
  1244. SetLastError(ERROR_INVALID_PARAMETER);
  1245. return(ERROR_INVALID_PARAMETER);
  1246. }
  1247. } else {
  1248. //
  1249. // OutputBuffer is specified, but OutBufferSize is not specified
  1250. //
  1251. SetLastError(ERROR_INVALID_PARAMETER);
  1252. return(ERROR_INVALID_PARAMETER);
  1253. }
  1254. }
  1255. try
  1256. {
  1257. MethodInstanceNameLen = wcslen(MethodInstanceName) *
  1258. sizeof(WCHAR);
  1259. } except(EXCEPTION_EXECUTE_HANDLER) {
  1260. SetLastError(ERROR_INVALID_PARAMETER);
  1261. return(ERROR_INVALID_PARAMETER);
  1262. }
  1263. //
  1264. // We need to allocate a buffer that is large enough for the
  1265. // WNODE_METHOD_ITEM that contains the method call and any data passed
  1266. // into the method
  1267. //
  1268. // Compute the size of the WNODE that can be returned from the provider
  1269. BaseMethodWnodeSize = (FIELD_OFFSET(WNODE_METHOD_ITEM, VariableData) +
  1270. MethodInstanceNameLen + sizeof(USHORT) + 7) & ~7;
  1271. OutSize = BaseMethodWnodeSize + BufferSize;
  1272. //
  1273. // Make sure we allocate enough room for the larger of the input or
  1274. // output buffers.
  1275. if (InputValueBufferSize > BufferSize)
  1276. {
  1277. BufferSize = InputValueBufferSize;
  1278. }
  1279. MethodWnodeSize = BaseMethodWnodeSize + BufferSize;
  1280. MethodWnode = (PWNODE_METHOD_ITEM)WmipAlloc(MethodWnodeSize);
  1281. if (MethodWnode == NULL)
  1282. {
  1283. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1284. return(ERROR_NOT_ENOUGH_MEMORY);
  1285. }
  1286. //
  1287. // Build WNODE_METHOD_ITEM containing method being called
  1288. //
  1289. memset(MethodWnode, 0, FIELD_OFFSET(WNODE_METHOD_ITEM, VariableData));
  1290. MethodWnode->MethodId = MethodId;
  1291. MethodWnode->OffsetInstanceName = FIELD_OFFSET(WNODE_METHOD_ITEM,
  1292. VariableData);
  1293. MethodWnode->DataBlockOffset = BaseMethodWnodeSize;
  1294. InstanceNamePtr = (PWCHAR)OffsetToPtr(MethodWnode,
  1295. MethodWnode->OffsetInstanceName);
  1296. *InstanceNamePtr++ = (USHORT)MethodInstanceNameLen;
  1297. try
  1298. {
  1299. memcpy(InstanceNamePtr,
  1300. MethodInstanceName,
  1301. MethodInstanceNameLen);
  1302. } except(EXCEPTION_EXECUTE_HANDLER) {
  1303. WmipFree(MethodWnode);
  1304. SetLastError(ERROR_INVALID_PARAMETER);
  1305. return(ERROR_INVALID_PARAMETER);
  1306. }
  1307. if (InputValueBuffer != NULL)
  1308. {
  1309. MethodWnode->SizeDataBlock = InputValueBufferSize;
  1310. DataPtr = (PUCHAR)OffsetToPtr(MethodWnode,
  1311. MethodWnode->DataBlockOffset);
  1312. try
  1313. {
  1314. memcpy(DataPtr, InputValueBuffer, InputValueBufferSize);
  1315. } except(EXCEPTION_EXECUTE_HANDLER) {
  1316. WmipFree(MethodWnode);
  1317. SetLastError(ERROR_INVALID_PARAMETER);
  1318. return(ERROR_INVALID_PARAMETER);
  1319. }
  1320. }
  1321. WmipBuildWnodeHeader(&MethodWnode->WnodeHeader,
  1322. MethodWnode->DataBlockOffset +
  1323. MethodWnode->SizeDataBlock,
  1324. WNODE_FLAG_METHOD_ITEM,
  1325. MethodDataBlockHandle);
  1326. Status = WmipSendWmiRequest(
  1327. WMI_EXECUTE_METHOD,
  1328. (PWNODE_HEADER)MethodWnode,
  1329. MethodWnode->WnodeHeader.BufferSize,
  1330. MethodWnode,
  1331. OutSize,
  1332. &RetSize);
  1333. if ((Status == ERROR_SUCCESS) &&
  1334. ((RetSize < sizeof(WNODE_TOO_SMALL) ||
  1335. ((RetSize >= sizeof(ULONG)) &&
  1336. (RetSize < MethodWnode->WnodeHeader.BufferSize)))))
  1337. {
  1338. Status = ERROR_WMI_DP_FAILED;
  1339. WmipAssert(FALSE);
  1340. }
  1341. if (Status == ERROR_SUCCESS)
  1342. {
  1343. WnodeHeader = (PWNODE_HEADER)MethodWnode;
  1344. if (WnodeHeader->Flags & WNODE_FLAG_TOO_SMALL)
  1345. {
  1346. Status = ERROR_INSUFFICIENT_BUFFER;
  1347. if (OutputBufferSize != NULL)
  1348. {
  1349. try
  1350. {
  1351. *OutputBufferSize = ((PWNODE_TOO_SMALL)WnodeHeader)->SizeNeeded -
  1352. BaseMethodWnodeSize;
  1353. } except(EXCEPTION_EXECUTE_HANDLER) {
  1354. Status = ERROR_INVALID_PARAMETER;
  1355. }
  1356. }
  1357. } else {
  1358. //
  1359. // Success, return results to caller
  1360. //
  1361. try
  1362. {
  1363. if (OutputBufferSize != NULL)
  1364. {
  1365. if (*OutputBufferSize >= MethodWnode->SizeDataBlock)
  1366. {
  1367. if (OutputBuffer != NULL)
  1368. {
  1369. DataPtr = (PUCHAR)OffsetToPtr(MethodWnode,
  1370. MethodWnode->DataBlockOffset);
  1371. memcpy(OutputBuffer,
  1372. DataPtr,
  1373. MethodWnode->SizeDataBlock);
  1374. }
  1375. } else {
  1376. Status = ERROR_INSUFFICIENT_BUFFER;
  1377. }
  1378. *OutputBufferSize = MethodWnode->SizeDataBlock;
  1379. } else if (MethodWnode->SizeDataBlock != 0) {
  1380. Status = ERROR_INSUFFICIENT_BUFFER;
  1381. }
  1382. } except(EXCEPTION_EXECUTE_HANDLER) {
  1383. Status = ERROR_INVALID_PARAMETER;
  1384. }
  1385. }
  1386. }
  1387. WmipFree(MethodWnode);
  1388. SetLastError(Status);
  1389. return(Status);
  1390. }
  1391. void
  1392. WMIAPI
  1393. WmiFreeBuffer(
  1394. IN PVOID Buffer
  1395. )
  1396. /*+++
  1397. Routine Description:
  1398. This routine frees a buffer allocated by WMI. This routine is typically
  1399. used by applications that receive events via the Window message
  1400. notification mechanism.
  1401. Arguments:
  1402. Buffer is a buffer returned by WMI that the app wishes to free
  1403. Return Value:
  1404. ---*/
  1405. {
  1406. WmipInitProcessHeap();
  1407. if (Buffer != NULL)
  1408. {
  1409. WmipDebugPrint(("WMI: WMIFreeBuffer(%x)\n", Buffer));
  1410. WmipFree(Buffer);
  1411. } else {
  1412. WmipDebugPrint(("WMI: NULL passed to WMIFreeBuffer\n"));
  1413. }
  1414. }
  1415. ULONG
  1416. WMIAPI
  1417. WmiNotificationRegistrationA(
  1418. IN LPGUID Guid,
  1419. IN BOOLEAN Enable,
  1420. IN PVOID DeliveryInfo,
  1421. IN ULONG_PTR DeliveryContext,
  1422. IN ULONG Flags
  1423. )
  1424. /*+++
  1425. Routine Description:
  1426. ANSI thunk to NotificationRegistration
  1427. Return Value:
  1428. Returns ERROR_SUCCESS or an error code
  1429. ---*/
  1430. {
  1431. return(WmipNotificationRegistration(Guid,
  1432. Enable,
  1433. DeliveryInfo,
  1434. DeliveryContext,
  1435. 0,
  1436. Flags,
  1437. TRUE));
  1438. }
  1439. ULONG
  1440. WMIAPI
  1441. WmiNotificationRegistrationW(
  1442. IN LPGUID Guid,
  1443. IN BOOLEAN Enable,
  1444. IN PVOID DeliveryInfo,
  1445. IN ULONG_PTR DeliveryContext,
  1446. IN ULONG Flags
  1447. )
  1448. /*+++
  1449. Routine Description:
  1450. This routine allows a data consumer to register or unregister for
  1451. notification of events fired by WMI data providers. Notifications are
  1452. delivered via callbackor via a posted meesage to a window.
  1453. Arguments:
  1454. Guid is pointer to the guid whose events are being registered for
  1455. Enable is TRUE if enabling notifications else FALSE. If FALSE the
  1456. Destination and DestinationInformation parameters are ignored.
  1457. DeliveryInfo has the callback function pointer or window handle to which
  1458. to deliver the notifications for the guid.
  1459. DeliveryContext has a context value or additional information to use
  1460. when delivering the notification.
  1461. Flags are a set of flags that define how the notification is delivered.
  1462. DeliveryInfo and DeliveryContext have different meanings depending
  1463. upon the value in Flags:
  1464. NOTIFICATION_WINDOW_HANDLE is set when notifications for the guid
  1465. are to be delivered by posting a message to the window handle
  1466. passed in DeliveryInfo. The message posted is the value that
  1467. is returned from the call to
  1468. RegisterWindowMessage(WMINOTIFICATIONWINDOWMESSAGE) with the
  1469. wParam set to the pointer to the Wnode containing the notification
  1470. and lParam set to the context value passed in DeliveryContext.
  1471. The caller MUST free the Wnode passed in wParam by calling
  1472. WMIFreeBuffer.
  1473. NOTIFICATION_CALLBACK_DIRECT is set when notifications for the
  1474. guid are to be delivered by direct callback. Whenever a
  1475. notification arrives WMI creates a new thread dedicated to
  1476. calling the callback function with the notification. This
  1477. mechanism provides the shortest latency from notification firing
  1478. to notification delivery, although it is the most expensive
  1479. mechanism. The callback function pointer is passed in DeliveryInfo
  1480. and must conform to the prototype described by the type
  1481. NOTIFICATIONCALLBACK. The context value passed in the callback
  1482. is specified by the DeliveryContext parameter. WMI does not
  1483. serialize calling the callback function so it must be reentrant.
  1484. NOTIFICATION_CALLBACK_QUEUED is set when notifications for the
  1485. guid are to be delivered by a queued callback. Whenever a
  1486. notification arrives WMI places it at the end of an internal
  1487. queue. A single thread monitors this queue and calls the callback
  1488. function serially for each notification in the queue. This
  1489. mechanism provides low overhead for event delivery, however
  1490. notification delivery can be delayed if the callback function
  1491. for an earlier notification does not complete quickly.
  1492. The callback function pointer is passed in DeliveryInfo
  1493. and must conform to the prototype described by the type
  1494. NOTIFICATIONCALLBACK. The context value passed in the callback
  1495. is specified by the DeliveryContext parameter. WMI does
  1496. serialize calling the callback function so it need not be
  1497. reentrant provided it is not also used for
  1498. NOTIFICATION_CALLBACK_DIRECT notififications. NOTE THAT THIS
  1499. IS NOT YET IMPLEMENTED.
  1500. NOTIFICATION_TRACE_FLAG is set when the caller wishes to enable
  1501. trace logging in the data provider for the guid. DeliveryInfo
  1502. specifies the trace logger handle to be passed to the data
  1503. provider. DeliveryContext is not used. No notifications are
  1504. generated to the caller when this flag is set.
  1505. Note that all of the above flags are mutually exclusive.
  1506. Return Value:
  1507. Returns ERROR_SUCCESS or an error code
  1508. ---*/
  1509. {
  1510. return(WmipNotificationRegistration(Guid,
  1511. Enable,
  1512. DeliveryInfo,
  1513. DeliveryContext,
  1514. 0,
  1515. Flags,
  1516. FALSE));
  1517. }
  1518. // TODO: Make WmiFile
  1519. ULONG
  1520. WMIAPI
  1521. WmiFileHandleToInstanceNameA(
  1522. IN WMIHANDLE DataBlockHandle,
  1523. IN HANDLE FileHandle,
  1524. IN OUT ULONG *NumberCharacters,
  1525. OUT PCHAR InstanceNames
  1526. )
  1527. /*++
  1528. Routine Description:
  1529. ANSI thunk to WMIFileHandleToInstanceNameW
  1530. --*/
  1531. {
  1532. ULONG Status;
  1533. PWCHAR InstanceNamesUnicode;
  1534. PWCHAR WCharPtr;
  1535. PCHAR Ansi, AnsiPtr;
  1536. ULONG AnsiLen, AnsiSize;
  1537. ULONG CharAvailable, CharReturned;
  1538. ULONG AnsiStringSize;
  1539. WmipInitProcessHeap();
  1540. CharAvailable = *NumberCharacters;
  1541. CharReturned = CharAvailable;
  1542. do
  1543. {
  1544. //
  1545. // We loop until we call with a buffer big enough to return
  1546. // the entire list of instance names.
  1547. InstanceNamesUnicode = WmipAlloc(CharReturned * sizeof(WCHAR));
  1548. if (InstanceNamesUnicode == NULL)
  1549. {
  1550. Status = ERROR_NOT_ENOUGH_MEMORY;
  1551. SetLastError(Status);
  1552. return(Status);
  1553. }
  1554. Status = WmiFileHandleToInstanceNameW(DataBlockHandle,
  1555. FileHandle,
  1556. &CharReturned,
  1557. InstanceNamesUnicode);
  1558. if (Status != ERROR_INSUFFICIENT_BUFFER)
  1559. {
  1560. break;
  1561. }
  1562. WmipFree(InstanceNamesUnicode);
  1563. } while (TRUE);
  1564. //
  1565. // CONSIDER: MB Strings
  1566. if (Status == ERROR_SUCCESS)
  1567. {
  1568. //
  1569. // Determine the size needed for the ansi buffer
  1570. WCharPtr = InstanceNamesUnicode;
  1571. AnsiSize = 1;
  1572. while (*WCharPtr != UNICODE_NULL)
  1573. {
  1574. Status = AnsiSizeForUnicodeString(WCharPtr, &AnsiStringSize);
  1575. if (Status != ERROR_SUCCESS)
  1576. {
  1577. goto Done;
  1578. }
  1579. AnsiSize += AnsiStringSize;
  1580. WCharPtr += wcslen(WCharPtr)+1;
  1581. }
  1582. //
  1583. // CONSIDER: MB String
  1584. if (AnsiSize > CharAvailable)
  1585. {
  1586. Status = ERROR_INSUFFICIENT_BUFFER;
  1587. } else {
  1588. //
  1589. // Copy the list of unicode strings to ansi strings. End of list
  1590. // is double NULL.
  1591. AnsiPtr = InstanceNames;
  1592. try
  1593. {
  1594. AnsiPtr[0] = 0;
  1595. AnsiPtr[1] = 0;
  1596. } except(EXCEPTION_EXECUTE_HANDLER) {
  1597. Status = ERROR_NOACCESS;
  1598. goto Done;
  1599. }
  1600. WCharPtr = InstanceNamesUnicode;
  1601. while (*WCharPtr != UNICODE_NULL)
  1602. {
  1603. try
  1604. {
  1605. Status = UnicodeToAnsi(WCharPtr, &AnsiPtr, &AnsiLen);
  1606. } except(EXCEPTION_EXECUTE_HANDLER) {
  1607. Status = ERROR_NOACCESS;
  1608. }
  1609. if (Status != ERROR_SUCCESS)
  1610. {
  1611. break;
  1612. }
  1613. AnsiPtr += AnsiLen;
  1614. *AnsiPtr = 0;
  1615. WCharPtr += wcslen(WCharPtr)+1;
  1616. }
  1617. }
  1618. Done:
  1619. try
  1620. {
  1621. *NumberCharacters = AnsiSize;
  1622. } except(EXCEPTION_EXECUTE_HANDLER) {
  1623. Status = ERROR_NOACCESS;
  1624. }
  1625. }
  1626. WmipFree(InstanceNamesUnicode);
  1627. SetLastError(Status);
  1628. return(Status);
  1629. }
  1630. ULONG
  1631. WMIAPI
  1632. WmiFileHandleToInstanceNameW(
  1633. IN WMIHANDLE DataBlockHandle,
  1634. IN HANDLE FileHandle,
  1635. IN OUT ULONG *NumberCharacters,
  1636. OUT PWCHAR InstanceNames
  1637. )
  1638. /*+++
  1639. Routine Description:
  1640. This routine will return all of the WMI instance names provided for a
  1641. data block within the device stack targeted by a file handle. Note
  1642. that not all data providers will support this functionality.
  1643. Arguments:
  1644. DataBlockHandle - Handle to data block
  1645. FileHandle - handle to a device whose stack is targeted
  1646. *NumberCharacters - On entry has maximum size in characters of Buffer. If
  1647. ERROR_BUFFER_TOO_SMALL is returned then it returns with the number
  1648. of character needed.
  1649. InstanceNames - if successful, returns with a list of single null
  1650. terminated strings which are the WMI instance names. The last instance
  1651. name is double null terminated
  1652. Return Value:
  1653. ERROR_SUCCESS or an error code
  1654. ---*/
  1655. {
  1656. PWMIFHTOINSTANCENAME FhToInstanceName;
  1657. ULONG RetSize;
  1658. ULONG Status;
  1659. WCHAR LocalInstanceNames[2];
  1660. ULONG BufferSize;
  1661. ULONG SizeNeeded;
  1662. WCHAR Suffix[MAX_PATH];
  1663. ULONG SuffixLen, CharsNeeded;
  1664. WmipInitProcessHeap();
  1665. BufferSize = *NumberCharacters;
  1666. //
  1667. // Start off by assuming that there is only one instance name and so
  1668. // only alloc space for that.
  1669. //
  1670. SizeNeeded = FIELD_OFFSET(WMIFHTOINSTANCENAME, InstanceNames) +
  1671. (MAX_PATH * sizeof(WCHAR));
  1672. Again:
  1673. FhToInstanceName = WmipAlloc(SizeNeeded + sizeof(WCHAR));
  1674. if (FhToInstanceName == NULL)
  1675. {
  1676. return(ERROR_NOT_ENOUGH_MEMORY);
  1677. }
  1678. WmipSetHandle3264(FhToInstanceName->FileHandle, FileHandle);
  1679. WmipSetHandle3264(FhToInstanceName->KernelHandle, DataBlockHandle);
  1680. Status = WmipSendWmiKMRequest(NULL,
  1681. IOCTL_WMI_TRANSLATE_FILE_HANDLE,
  1682. FhToInstanceName,
  1683. FIELD_OFFSET(WMIFHTOINSTANCENAME,
  1684. InstanceNames),
  1685. FhToInstanceName,
  1686. SizeNeeded,
  1687. &RetSize,
  1688. NULL);
  1689. if (Status == ERROR_SUCCESS)
  1690. {
  1691. if (RetSize == sizeof(ULONG))
  1692. {
  1693. //
  1694. // If buffer passed was too small then try with a bigger buffer
  1695. //
  1696. SizeNeeded = FhToInstanceName->SizeNeeded + sizeof(WCHAR);
  1697. WmipFree(FhToInstanceName);
  1698. goto Again;
  1699. } else {
  1700. if ((RetSize < sizeof(WMIFHTOINSTANCENAME)) ||
  1701. (RetSize < (ULONG)(FhToInstanceName->InstanceNameLength +
  1702. FIELD_OFFSET(WMIFHTOINSTANCENAME, InstanceNames))))
  1703. {
  1704. //
  1705. // WMI KM returned a bogus size which should not happen
  1706. //
  1707. Status = ERROR_WMI_DP_FAILED;
  1708. WmipAssert(FALSE);
  1709. } else {
  1710. //
  1711. // Copy the results back to the users buffer if
  1712. // there is enough space
  1713. //
  1714. SuffixLen = swprintf(Suffix, L"_%d",
  1715. FhToInstanceName->BaseIndex);
  1716. try
  1717. {
  1718. CharsNeeded = (FhToInstanceName->InstanceNameLength /
  1719. sizeof(WCHAR)) + SuffixLen + 1;
  1720. *NumberCharacters = CharsNeeded;
  1721. if (BufferSize >= FhToInstanceName->InstanceNameLength)
  1722. {
  1723. wcscpy(InstanceNames,
  1724. &FhToInstanceName->InstanceNames[0]);
  1725. wcscat(InstanceNames, Suffix);
  1726. InstanceNames[CharsNeeded-2] = UNICODE_NULL;
  1727. }
  1728. } except(EXCEPTION_EXECUTE_HANDLER) {
  1729. Status = ERROR_INVALID_PARAMETER;
  1730. }
  1731. }
  1732. }
  1733. }
  1734. WmipFree(FhToInstanceName);
  1735. SetLastError(Status);
  1736. return(Status);
  1737. }
  1738. ULONG
  1739. WMIAPI
  1740. WmiEnumerateGuids(
  1741. OUT LPGUID GuidList,
  1742. IN OUT ULONG *InOutGuidCount
  1743. )
  1744. /*++
  1745. Routine Description:
  1746. This routine will enumerate all of the guids that are
  1747. registered with WMI.
  1748. Arguments:
  1749. GuidList is a pointer to an array of guids that is returned with the
  1750. *GuidCount on entry is the number of guids that can be written to
  1751. GuidList and if ERROR_SUCCESS is returned it has the actual number
  1752. of guids written to GuidList. If ERROR_MORE_DATA is returned
  1753. it has the total number of guids that are available to be returned.
  1754. Return Value:
  1755. ERROR_SUCCESS if all guids returned, ERROR_MORE_DATA if not all guids
  1756. were returned or another error code on error
  1757. --*/
  1758. {
  1759. ULONG Status;
  1760. PWMIGUIDLISTINFO GuidListInfo;
  1761. ULONG GuidCount;
  1762. ULONG SizeNeeded;
  1763. ULONG RetSize;
  1764. ULONG i;
  1765. WmipInitProcessHeap();
  1766. try
  1767. {
  1768. GuidCount = *InOutGuidCount;
  1769. } except(EXCEPTION_EXECUTE_HANDLER) {
  1770. SetLastError(ERROR_INVALID_PARAMETER);
  1771. return(ERROR_INVALID_PARAMETER);
  1772. }
  1773. if ((GuidList == NULL) && (GuidCount != 0))
  1774. {
  1775. SetLastError(ERROR_INVALID_PARAMETER);
  1776. return(ERROR_INVALID_PARAMETER);
  1777. }
  1778. //
  1779. // Allocate space for returning guids
  1780. //
  1781. SizeNeeded = FIELD_OFFSET(WMIGUIDLISTINFO, GuidList) +
  1782. GuidCount * sizeof(WMIGUIDPROPERTIES);
  1783. GuidListInfo = WmipAlloc(SizeNeeded);
  1784. if (GuidListInfo != NULL)
  1785. {
  1786. Status = WmipSendWmiKMRequest(NULL,
  1787. IOCTL_WMI_ENUMERATE_GUIDS,
  1788. GuidListInfo,
  1789. SizeNeeded,
  1790. GuidListInfo,
  1791. SizeNeeded,
  1792. &RetSize,
  1793. NULL);
  1794. if (Status == ERROR_SUCCESS)
  1795. {
  1796. if ((RetSize < FIELD_OFFSET(WMIGUIDLISTINFO, GuidList)) ||
  1797. (RetSize < (FIELD_OFFSET(WMIGUIDLISTINFO, GuidList) +
  1798. GuidListInfo->ReturnedGuidCount * sizeof(WMIGUIDPROPERTIES))))
  1799. {
  1800. //
  1801. // WMI KM returned to us a bad size which should not happen
  1802. //
  1803. Status = ERROR_WMI_DP_FAILED;
  1804. WmipAssert(FALSE);
  1805. } else {
  1806. try
  1807. {
  1808. for (i = 0; i < GuidListInfo->ReturnedGuidCount; i++)
  1809. {
  1810. GuidList[i] = GuidListInfo->GuidList[i].Guid;
  1811. }
  1812. } except(EXCEPTION_EXECUTE_HANDLER) {
  1813. Status = ERROR_NOACCESS;
  1814. }
  1815. try
  1816. {
  1817. //
  1818. // Return the total guid count which is also the actual
  1819. // guid count if we returned all guids correctly
  1820. //
  1821. *InOutGuidCount = GuidListInfo->TotalGuidCount;
  1822. if (GuidListInfo->ReturnedGuidCount != GuidListInfo->TotalGuidCount)
  1823. {
  1824. //
  1825. // If we did not return all of the guids, change
  1826. // return status to something more appropriate
  1827. //
  1828. Status = ERROR_MORE_DATA;
  1829. }
  1830. } except(EXCEPTION_EXECUTE_HANDLER) {
  1831. Status = ERROR_INVALID_PARAMETER;
  1832. }
  1833. }
  1834. }
  1835. WmipFree(GuidListInfo);
  1836. } else {
  1837. Status = ERROR_NOT_ENOUGH_MEMORY;
  1838. }
  1839. SetLastError(Status);
  1840. return(Status);
  1841. }
  1842. ULONG
  1843. WMIAPI
  1844. WmiDevInstToInstanceNameA(
  1845. OUT PCHAR InstanceName,
  1846. IN ULONG InstanceNameLength,
  1847. IN PCHAR DevInst,
  1848. IN ULONG InstanceIndex
  1849. )
  1850. /*++
  1851. Routine Description:
  1852. This routine will convert a device instance name and an instance index
  1853. into a WMI instance name.
  1854. Arguments:
  1855. InstanceName is a pointer to a buffer that returns with the WMI instance
  1856. name if the buffer is large enough
  1857. InstanceNameLength has the number of characters that can be written into
  1858. InstanceName
  1859. DevInst is the Device Instance Name
  1860. InstanceIndex is the instance index
  1861. Return Value:
  1862. number of characters that compose the WMI instance name
  1863. --*/
  1864. {
  1865. CHAR Temp[MAX_PATH];
  1866. ULONG SizeNeeded;
  1867. WmipInitProcessHeap();
  1868. sprintf(Temp, "_%d", InstanceIndex);
  1869. SizeNeeded = strlen(Temp) + strlen(DevInst) + 1;
  1870. if (InstanceNameLength >= SizeNeeded)
  1871. {
  1872. strcpy(InstanceName, DevInst);
  1873. strcat(InstanceName, Temp);
  1874. }
  1875. return(SizeNeeded);
  1876. }
  1877. ULONG
  1878. WMIAPI
  1879. WmiDevInstToInstanceNameW(
  1880. OUT PWCHAR InstanceName,
  1881. IN ULONG InstanceNameLength,
  1882. IN PWCHAR DevInst,
  1883. IN ULONG InstanceIndex
  1884. )
  1885. {
  1886. WCHAR Temp[MAX_PATH];
  1887. ULONG SizeNeeded;
  1888. WmipInitProcessHeap();
  1889. swprintf(Temp, L"_%d", InstanceIndex);
  1890. SizeNeeded = wcslen(Temp) + wcslen(DevInst) + 1;
  1891. if (InstanceNameLength >= SizeNeeded)
  1892. {
  1893. wcscpy(InstanceName, DevInst);
  1894. wcscat(InstanceName, Temp);
  1895. }
  1896. return(SizeNeeded);
  1897. }
  1898. ULONG
  1899. WMIAPI
  1900. WmiQueryGuidInformation(
  1901. IN WMIHANDLE DataBlockHandle,
  1902. OUT PWMIGUIDINFORMATION GuidInfo
  1903. )
  1904. /*++
  1905. Routine Description:
  1906. This routine will query information about a specific guid based upon
  1907. the guid handle passed
  1908. Arguments:
  1909. GuidHandle is the handle to the GUID whose information is being queried
  1910. GuidInfo returns with the guid information
  1911. Return Value:
  1912. ERROR_SUCCESS or error code
  1913. --*/
  1914. {
  1915. WMIQUERYGUIDINFO QueryGuidInfo;
  1916. ULONG Status;
  1917. ULONG RetSize;
  1918. WmipInitProcessHeap();
  1919. WmipSetHandle3264(QueryGuidInfo.KernelHandle, DataBlockHandle);
  1920. Status = WmipSendWmiKMRequest(NULL,
  1921. IOCTL_WMI_QUERY_GUID_INFO,
  1922. &QueryGuidInfo,
  1923. sizeof(QueryGuidInfo),
  1924. &QueryGuidInfo,
  1925. sizeof(QueryGuidInfo),
  1926. &RetSize,
  1927. NULL);
  1928. if (Status == ERROR_SUCCESS)
  1929. {
  1930. if (RetSize == sizeof(QueryGuidInfo))
  1931. {
  1932. try
  1933. {
  1934. GuidInfo->IsExpensive = QueryGuidInfo.IsExpensive;
  1935. } except(EXCEPTION_EXECUTE_HANDLER) {
  1936. SetLastError(ERROR_NOACCESS);
  1937. return(ERROR_NOACCESS);
  1938. }
  1939. } else {
  1940. //
  1941. // WMI KM returned an invalid size which should not happen
  1942. //
  1943. Status = ERROR_WMI_DP_FAILED;
  1944. WmipAssert(FALSE);
  1945. }
  1946. }
  1947. SetLastError(Status);
  1948. return(Status);
  1949. }
  1950. ULONG
  1951. WMIAPI
  1952. WmiReceiveNotificationsW(
  1953. IN ULONG HandleCount,
  1954. IN HANDLE *HandleList,
  1955. IN NOTIFICATIONCALLBACK Callback,
  1956. IN ULONG_PTR DeliveryContext
  1957. )
  1958. {
  1959. return(WmipReceiveNotifications(HandleCount,
  1960. HandleList,
  1961. Callback,
  1962. DeliveryContext,
  1963. FALSE,
  1964. RECEIVE_ACTION_NONE,
  1965. NULL,
  1966. NULL));
  1967. }
  1968. ULONG
  1969. WMIAPI
  1970. WmiReceiveNotificationsA(
  1971. IN ULONG HandleCount,
  1972. IN HANDLE *HandleList,
  1973. IN NOTIFICATIONCALLBACK Callback,
  1974. IN ULONG_PTR DeliveryContext
  1975. )
  1976. {
  1977. return(WmipReceiveNotifications(HandleCount,
  1978. HandleList,
  1979. Callback,
  1980. DeliveryContext,
  1981. TRUE,
  1982. RECEIVE_ACTION_NONE,
  1983. NULL,
  1984. NULL));
  1985. }