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.

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