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.

850 lines
21 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. chunkimpl.h
  5. Abstract:
  6. This routine will manage allocations of chunks of structures. It also
  7. contains a handy unicode to ansi conversion function
  8. Author:
  9. 16-Jan-1997 AlanWar
  10. Revision History:
  11. --*/
  12. #if DBG
  13. BOOLEAN WmipLoggingEnabled = FALSE;
  14. #endif
  15. PENTRYHEADER WmipAllocEntry(
  16. PCHUNKINFO ChunkInfo
  17. )
  18. /*++
  19. Routine Description:
  20. This routine will allocate a single structure within a list of chunks
  21. of structures.
  22. Arguments:
  23. ChunkInfo describes the chunks of structures
  24. Return Value:
  25. Pointer to structure or NULL if one cannot be allocated. Entry returns
  26. with its refcount set to 1
  27. --*/
  28. {
  29. PLIST_ENTRY ChunkList, EntryList, FreeEntryHead;
  30. PCHUNKHEADER Chunk;
  31. PBYTE EntryPtr;
  32. ULONG EntryCount, ChunkSize;
  33. PENTRYHEADER Entry;
  34. ULONG i;
  35. #ifdef HEAPVALIDATION
  36. WmipAssert(RtlValidateProcessHeaps());
  37. #endif
  38. WmipEnterCriticalSection();
  39. ChunkList = ChunkInfo->ChunkHead.Flink;
  40. //
  41. // Loop over all chunks to see if any chunk has a free entry for us
  42. while(ChunkList != &ChunkInfo->ChunkHead)
  43. {
  44. Chunk = CONTAINING_RECORD(ChunkList, CHUNKHEADER, ChunkList);
  45. if (! IsListEmpty(&Chunk->FreeEntryHead))
  46. {
  47. EntryList = RemoveHeadList(&Chunk->FreeEntryHead);
  48. Chunk->EntriesInUse++;
  49. WmipLeaveCriticalSection();
  50. Entry = (CONTAINING_RECORD(EntryList,
  51. ENTRYHEADER,
  52. FreeEntryList));
  53. WmipAssert(Entry->Flags & FLAG_ENTRY_ON_FREE_LIST);
  54. memset(Entry, 0, ChunkInfo->EntrySize);
  55. Entry->Chunk = Chunk;
  56. Entry->RefCount = 1;
  57. Entry->Flags = ChunkInfo->InitialFlags;
  58. Entry->Signature = ChunkInfo->Signature;
  59. #if DBG
  60. InterlockedIncrement(&ChunkInfo->AllocCount);
  61. #endif
  62. return(Entry);
  63. }
  64. ChunkList = ChunkList->Flink;
  65. }
  66. WmipLeaveCriticalSection();
  67. //
  68. // There are no more free entries in any of the chunks. Allocate a new
  69. // chunk if we can
  70. ChunkSize = (ChunkInfo->EntrySize * ChunkInfo->EntriesPerChunk) +
  71. sizeof(CHUNKHEADER);
  72. Chunk = (PCHUNKHEADER)WmipAlloc(ChunkSize);
  73. if (Chunk != NULL)
  74. {
  75. //
  76. // Initialize the chunk by building the free list of entries within
  77. // it while also initializing each entry.
  78. memset(Chunk, 0, ChunkSize);
  79. FreeEntryHead = &Chunk->FreeEntryHead;
  80. InitializeListHead(FreeEntryHead);
  81. EntryPtr = (PBYTE)Chunk + sizeof(CHUNKHEADER);
  82. EntryCount = ChunkInfo->EntriesPerChunk - 1;
  83. for (i = 0; i < EntryCount; i++)
  84. {
  85. Entry = (PENTRYHEADER)EntryPtr;
  86. Entry->Chunk = Chunk;
  87. Entry->Flags = FLAG_ENTRY_ON_FREE_LIST;
  88. InsertHeadList(FreeEntryHead,
  89. &((PENTRYHEADER)EntryPtr)->FreeEntryList);
  90. EntryPtr = EntryPtr + ChunkInfo->EntrySize;
  91. }
  92. //
  93. // EntryPtr now points to the last entry in the chunk which has not
  94. // been placed on the free list. This will be the entry returned
  95. // to the caller.
  96. Entry = (PENTRYHEADER)EntryPtr;
  97. Entry->Chunk = Chunk;
  98. Entry->RefCount = 1;
  99. Entry->Flags = ChunkInfo->InitialFlags;
  100. Entry->Signature = ChunkInfo->Signature;
  101. Chunk->EntriesInUse = 1;
  102. //
  103. // Now place the newly allocated chunk onto the list of chunks
  104. WmipEnterCriticalSection();
  105. InsertHeadList(&ChunkInfo->ChunkHead, &Chunk->ChunkList);
  106. WmipLeaveCriticalSection();
  107. } else {
  108. WmipDebugPrint(("WMI: Could not allocate memory for new chunk %x\n",
  109. ChunkInfo));
  110. Entry = NULL;
  111. }
  112. return(Entry);
  113. }
  114. void WmipFreeEntry(
  115. PCHUNKINFO ChunkInfo,
  116. PENTRYHEADER Entry
  117. )
  118. /*++
  119. Routine Description:
  120. This routine will free an entry within a chunk and if the chunk has no
  121. more allocated entries then the chunk will be returned to the pool.
  122. Arguments:
  123. ChunkInfo describes the chunks of structures
  124. Entry is the chunk entry to free
  125. Return Value:
  126. --*/
  127. {
  128. PCHUNKHEADER Chunk;
  129. WmipAssert(Entry != NULL);
  130. WmipAssert(! (Entry->Flags & FLAG_ENTRY_ON_FREE_LIST))
  131. WmipAssert((Entry->Flags & FLAG_ENTRY_INVALID))
  132. WmipAssert(Entry->RefCount == 0);
  133. WmipAssert(Entry->Signature == ChunkInfo->Signature);
  134. Chunk = Entry->Chunk;
  135. WmipAssert(Chunk->EntriesInUse > 0);
  136. WmipEnterCriticalSection();
  137. if ((--Chunk->EntriesInUse == 0) &&
  138. (ChunkInfo->ChunkHead.Blink != &Chunk->ChunkList))
  139. {
  140. //
  141. // We return the chunks memory back to the heap if there are no
  142. // more entries within the chunk in use and the chunk was not the
  143. // first chunk to be allocated.
  144. RemoveEntryList(&Chunk->ChunkList);
  145. WmipLeaveCriticalSection();
  146. WmipFree(Chunk);
  147. } else {
  148. //
  149. // Otherwise just mark the entry as free and put it back on the
  150. // chunks free list.
  151. #if DBG
  152. memset(Entry, 0xCCCCCCCC, ChunkInfo->EntrySize);
  153. #endif
  154. Entry->Flags = FLAG_ENTRY_ON_FREE_LIST;
  155. Entry->Signature = 0;
  156. InsertTailList(&Chunk->FreeEntryHead, &Entry->FreeEntryList);
  157. WmipLeaveCriticalSection();
  158. }
  159. }
  160. ULONG WmipUnreferenceEntry(
  161. PCHUNKINFO ChunkInfo,
  162. PENTRYHEADER Entry
  163. )
  164. /*+++
  165. Routine Description:
  166. This routine will remove a reference count from the entry and if the
  167. reference count reaches zero then the entry is removed from its active
  168. list and then cleaned up and finally freed.
  169. Arguments:
  170. ChunkInfo points at structure that describes the entry
  171. Entry is the entry to unreference
  172. Return Value:
  173. New refcount of the entry
  174. ---*/
  175. {
  176. ULONG RefCount;
  177. WmipAssert(Entry != NULL);
  178. WmipAssert(Entry->RefCount > 0);
  179. WmipAssert(Entry->Signature == ChunkInfo->Signature);
  180. WmipEnterCriticalSection();
  181. InterlockedDecrement(&Entry->RefCount);
  182. RefCount = Entry->RefCount;
  183. if (RefCount == 0)
  184. {
  185. //
  186. // Entry has reached a ref count of 0 so mark it as invalid and remove
  187. // it from its active list.
  188. Entry->Flags |= FLAG_ENTRY_INVALID;
  189. if ((Entry->InUseEntryList.Flink != NULL) &&
  190. (Entry->Flags & FLAG_ENTRY_REMOVE_LIST))
  191. {
  192. RemoveEntryList(&Entry->InUseEntryList);
  193. }
  194. WmipLeaveCriticalSection();
  195. if (ChunkInfo->EntryCleanup != NULL)
  196. {
  197. //
  198. // Call cleanup routine to free anything contained by the entry
  199. (*ChunkInfo->EntryCleanup)(ChunkInfo, Entry);
  200. }
  201. //
  202. // Place the entry back on its free list
  203. WmipFreeEntry(ChunkInfo, Entry);
  204. } else {
  205. WmipLeaveCriticalSection();
  206. }
  207. return(RefCount);
  208. }
  209. ULONG AnsiSizeForUnicodeString(
  210. PWCHAR UnicodeString,
  211. ULONG *AnsiSizeInBytes
  212. )
  213. /*++
  214. Routine Description:
  215. This routine will return the length needed to represent the unicode
  216. string as ANSI
  217. Arguments:
  218. UnicodeString is the unicode string whose ansi length is returned
  219. Return Value:
  220. Number of bytes needed to represent unicode string as ANSI
  221. --*/
  222. {
  223. WmipAssert(UnicodeString != NULL);
  224. try
  225. {
  226. *AnsiSizeInBytes = WideCharToMultiByte(CP_ACP,
  227. 0,
  228. UnicodeString,
  229. -1,
  230. NULL,
  231. 0, NULL, NULL) * sizeof(WCHAR);
  232. } except(EXCEPTION_EXECUTE_HANDLER) {
  233. return(ERROR_NOACCESS);
  234. }
  235. return((*AnsiSizeInBytes == 0) ? GetLastError() : ERROR_SUCCESS);
  236. }
  237. ULONG UnicodeToAnsi(
  238. LPCWSTR pszW,
  239. LPSTR * ppszA,
  240. ULONG *AnsiSizeInBytes OPTIONAL
  241. )
  242. /*++
  243. Routine Description:
  244. Convert Unicode string into its ansi equivalent
  245. Arguments:
  246. pszW is unicode string to convert
  247. *ppszA on entry has a pointer to a ansi string into which the answer
  248. is written. If NULL on entry then a buffer is allocated and returned
  249. in it.
  250. Return Value:
  251. Error code
  252. --*/
  253. {
  254. ULONG cbAnsi, cCharacters;
  255. ULONG Status;
  256. ULONG cbAnsiUsed;
  257. BOOLEAN CallerReturnBuffer = (*ppszA != NULL);
  258. //
  259. // If input is null then just return the same.
  260. if (pszW == NULL)
  261. {
  262. *ppszA = NULL;
  263. return(ERROR_SUCCESS);
  264. }
  265. try
  266. {
  267. cCharacters = wcslen(pszW)+1;
  268. } except(EXCEPTION_EXECUTE_HANDLER) {
  269. WmipDebugPrint(("WMI: Bad pointer %x passed to UnicodeToAnsi\n", pszW));
  270. return(ERROR_NOACCESS);
  271. }
  272. // Determine number of bytes to be allocated for ANSI string. An
  273. // ANSI string can have at most 2 bytes per character (for Double
  274. // Byte Character Strings.)
  275. cbAnsi = cCharacters*2;
  276. // Use of the OLE allocator is not required because the resultant
  277. // ANSI string will never be passed to another COM component. You
  278. // can use your own allocator.
  279. if (*ppszA == NULL)
  280. {
  281. *ppszA = (LPSTR) WmipAlloc(cbAnsi);
  282. if (NULL == *ppszA)
  283. {
  284. return(ERROR_NOT_ENOUGH_MEMORY);
  285. }
  286. }
  287. // Convert to ANSI.
  288. try
  289. {
  290. cbAnsiUsed = WideCharToMultiByte(CP_ACP, 0, pszW, cCharacters, *ppszA,
  291. cbAnsi, NULL, NULL);
  292. } except(EXCEPTION_EXECUTE_HANDLER) {
  293. if (! CallerReturnBuffer)
  294. {
  295. WmipFree(*ppszA);
  296. *ppszA = NULL;
  297. }
  298. return(ERROR_NOACCESS);
  299. }
  300. if (AnsiSizeInBytes != NULL)
  301. {
  302. *AnsiSizeInBytes = cbAnsiUsed;
  303. }
  304. if (0 == cbAnsiUsed)
  305. {
  306. Status = GetLastError();
  307. if (! CallerReturnBuffer)
  308. {
  309. WmipFree(*ppszA);
  310. *ppszA = NULL;
  311. }
  312. return(Status);
  313. }
  314. return(ERROR_SUCCESS);
  315. }
  316. ULONG AnsiToUnicode(
  317. LPCSTR pszA,
  318. LPWSTR * ppszW
  319. )
  320. /*++
  321. Routine Description:
  322. Convert Ansi string into its Unicode equivalent
  323. Arguments:
  324. pszA is ansi string to convert
  325. *ppszW on entry has a pointer to a unicode string into which the answer
  326. is written. If NULL on entry then a buffer is allocated and returned
  327. in it.
  328. Return Value:
  329. Error code
  330. --*/
  331. {
  332. ULONG cCharacters;
  333. ULONG Status;
  334. ULONG cbUnicodeUsed;
  335. BOOLEAN CallerReturnBuffer = (*ppszW != NULL);
  336. //
  337. // If input is null then just return the same.
  338. if (pszA == NULL)
  339. {
  340. *ppszW = NULL;
  341. return(ERROR_SUCCESS);
  342. }
  343. //
  344. // Determine the count of characters needed for Unicode string
  345. try
  346. {
  347. cCharacters = MultiByteToWideChar(CP_ACP, 0, pszA, -1, NULL, 0);
  348. } except(EXCEPTION_EXECUTE_HANDLER) {
  349. WmipDebugPrint(("WMI: Bad pointer %x passed to AnsiToUnicode\n", pszA));
  350. return(ERROR_NOACCESS);
  351. }
  352. if (cCharacters == 0)
  353. {
  354. *ppszW = NULL;
  355. return(GetLastError());
  356. }
  357. // Use of the OLE allocator is not required because the resultant
  358. // ANSI string will never be passed to another COM component. You
  359. // can use your own allocator.
  360. if (*ppszW == NULL)
  361. {
  362. *ppszW = (LPWSTR) WmipAlloc(cCharacters * sizeof(WCHAR));
  363. }
  364. if (NULL == *ppszW)
  365. return(ERROR_NOT_ENOUGH_MEMORY);
  366. // Convert to Unicode
  367. try
  368. {
  369. cbUnicodeUsed = MultiByteToWideChar(CP_ACP, 0, pszA, -1, *ppszW, cCharacters);
  370. } except(EXCEPTION_EXECUTE_HANDLER) {
  371. if (! CallerReturnBuffer)
  372. {
  373. WmipFree(*ppszW);
  374. *ppszW = NULL;
  375. }
  376. return(ERROR_NOACCESS);
  377. }
  378. if (0 == cbUnicodeUsed)
  379. {
  380. Status = GetLastError();
  381. if (! CallerReturnBuffer)
  382. {
  383. WmipFree(*ppszW);
  384. *ppszW = NULL;
  385. }
  386. return(Status);
  387. }
  388. return(ERROR_SUCCESS);
  389. }
  390. ULONG UnicodeSizeForAnsiString(
  391. LPCSTR pszA,
  392. ULONG *UnicodeSizeInBytes
  393. )
  394. /*++
  395. Routine Description:
  396. This routine will return the length needed to represent the ansi
  397. string as UNICODE
  398. Arguments:
  399. pszA is ansi string to convert
  400. Return Value:
  401. Error code
  402. --*/
  403. {
  404. WmipAssert(pszA != NULL);
  405. //
  406. // Determine the count of characters needed for Unicode string
  407. try
  408. {
  409. *UnicodeSizeInBytes = MultiByteToWideChar(CP_ACP, 0, pszA, -1, NULL, 0) * sizeof(WCHAR);
  410. } except(EXCEPTION_EXECUTE_HANDLER) {
  411. return(ERROR_NOACCESS);
  412. }
  413. return((*UnicodeSizeInBytes == 0) ? GetLastError() : ERROR_SUCCESS);
  414. }
  415. #if 0 // TODO: Delete me
  416. ULONG WmipStaticInstanceNameSize(
  417. PWMIINSTANCEINFO WmiInstanceInfo
  418. )
  419. /*+++
  420. Routine Description:
  421. This routine will calculate the size needed to place instance names in
  422. a WNODE_ALL_DATA
  423. Arguments:
  424. WmiInstanceInfo describes to instance set whose instance name size
  425. is to be calculated
  426. Return Value:
  427. Size needed to place instance names in a WNODE_ALL_DATA plus 3. The
  428. extra 3 bytes are added in case the OffsetInstanceNameOffsets need to be
  429. padded since they must be on a 4 byte boundry.
  430. ---*/
  431. {
  432. ULONG NameSize;
  433. ULONG i;
  434. ULONG SuffixLen;
  435. //
  436. // If we already computed this then just return the results
  437. if (WmiInstanceInfo->InstanceNameSize != 0)
  438. {
  439. return(WmiInstanceInfo->InstanceNameSize);
  440. }
  441. //
  442. // Start with a name size of 3 in case the OffsetInstanceNameOffset will
  443. // need to be padded so that it starts on a 4 byte boundry.
  444. NameSize = 3;
  445. if (WmiInstanceInfo->Flags & IS_INSTANCE_BASENAME)
  446. {
  447. //
  448. // For static base names we assume that there will never be more than
  449. // 999999 instances of a guid.
  450. SuffixLen = MAXBASENAMESUFFIXSIZE * sizeof(WCHAR);
  451. WmipAssert((WmiInstanceInfo->BaseIndex + WmiInstanceInfo->InstanceCount) < 999999);
  452. NameSize += ((wcslen(WmiInstanceInfo->BaseName) * sizeof(WCHAR)) + 2 + SuffixLen + sizeof(ULONG)) * WmiInstanceInfo->InstanceCount;
  453. } else if (WmiInstanceInfo->Flags & IS_INSTANCE_STATICNAMES)
  454. {
  455. //
  456. // Count up each size of the static instance names in the list
  457. for (i = 0; i < WmiInstanceInfo->InstanceCount; i++)
  458. {
  459. NameSize += (wcslen(WmiInstanceInfo->StaticNamePtr[i]) + 2) * sizeof(WCHAR) + sizeof(ULONG);
  460. }
  461. }
  462. WmiInstanceInfo->InstanceNameSize = NameSize;
  463. return(NameSize);
  464. }
  465. void WmipInsertStaticNames(
  466. PWNODE_ALL_DATA Wnode,
  467. ULONG MaxWnodeSize,
  468. PWMIINSTANCEINFO WmiInstanceInfo
  469. )
  470. /*+++
  471. Routine Description:
  472. This routine will copy into the WNODE_ALL_DATA instance names for a
  473. static instance name set. If the Wnode_All_data is too small then it
  474. is converted to a WNODE_TOO_SMALL
  475. Arguments:
  476. Wnode points at the WNODE_ALL_DATA
  477. MaxWnodeSize is the maximum size of the Wnode
  478. WmiInstanceInfo is the Instance Info
  479. Return Value:
  480. ---*/
  481. {
  482. PWCHAR NamePtr;
  483. PULONG NameOffsetPtr;
  484. ULONG InstanceCount;
  485. ULONG i;
  486. WCHAR Index[7];
  487. PWCHAR StaticName;
  488. ULONG SizeNeeded;
  489. ULONG NameLen;
  490. USHORT Len;
  491. ULONG PaddedBufferSize;
  492. if ((WmiInstanceInfo->Flags &
  493. (IS_INSTANCE_BASENAME | IS_INSTANCE_STATICNAMES)) == 0)
  494. {
  495. WmipDebugPrint(("WMI: Try to setup static names for dynamic guid\n"));
  496. return;
  497. }
  498. InstanceCount = WmiInstanceInfo->InstanceCount;
  499. //
  500. // Pad out the size of the buffer to a 4 byte boundry since the
  501. // OffsetInstanceNameOffsets must be on a 4 byte boundry
  502. PaddedBufferSize = (Wnode->WnodeHeader.BufferSize + 3) & ~3;
  503. //
  504. // Compute size needed to write instance names.
  505. SizeNeeded = (InstanceCount * sizeof(ULONG)) +
  506. WmipStaticInstanceNameSize(WmiInstanceInfo) +
  507. Wnode->WnodeHeader.BufferSize;
  508. if (SizeNeeded > MaxWnodeSize)
  509. {
  510. //
  511. // If not enough space left then change into a WNODE_TOO_SMALL
  512. Wnode->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
  513. Wnode->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
  514. ((PWNODE_TOO_SMALL)Wnode)->SizeNeeded = SizeNeeded;
  515. return;
  516. }
  517. //
  518. // Build the array of offsets to instance names
  519. NameOffsetPtr = (PULONG)((PBYTE)Wnode + PaddedBufferSize);
  520. Wnode->OffsetInstanceNameOffsets = (ULONG)((PBYTE)NameOffsetPtr - (PBYTE)Wnode);
  521. NamePtr = (PWCHAR)(NameOffsetPtr + InstanceCount);
  522. if (WmiInstanceInfo->Flags & IS_INSTANCE_BASENAME)
  523. {
  524. if (WmiInstanceInfo->Flags & IS_PDO_INSTANCENAME)
  525. {
  526. Wnode->WnodeHeader.Flags |= WNODE_FLAG_PDO_INSTANCE_NAMES;
  527. }
  528. for (i = 0; i < InstanceCount; i++)
  529. {
  530. *NameOffsetPtr++ = (ULONG)((PBYTE)NamePtr - (PBYTE)Wnode);
  531. wcscpy(NamePtr+1,
  532. WmiInstanceInfo->BaseName);
  533. swprintf(Index, L"%d", WmiInstanceInfo->BaseIndex+i);
  534. wcscat(NamePtr+1, Index);
  535. NameLen = wcslen(NamePtr+1) + 1;
  536. *NamePtr = (USHORT)NameLen * sizeof(WCHAR);
  537. NamePtr += NameLen + 1;
  538. }
  539. } else if (WmiInstanceInfo->Flags & IS_INSTANCE_STATICNAMES) {
  540. for (i = 0; i < InstanceCount; i++)
  541. {
  542. *NameOffsetPtr++ = (ULONG)((PBYTE)NamePtr - (PBYTE)Wnode);
  543. StaticName = WmiInstanceInfo->StaticNamePtr[i];
  544. Len = (wcslen(StaticName)+1) * sizeof(WCHAR);
  545. *NamePtr++ = Len;
  546. wcscpy(NamePtr, StaticName);
  547. NamePtr += Len / sizeof(WCHAR);
  548. }
  549. }
  550. Wnode->WnodeHeader.BufferSize = SizeNeeded;
  551. }
  552. #endif
  553. #ifdef HEAPVALIDATION
  554. PVOID WmipAlloc(
  555. ULONG Size
  556. )
  557. {
  558. PVOID p;
  559. WmipAssert(RtlValidateProcessHeaps());
  560. p = RtlAllocateHeap(WmipProcessHeap, 0, Size);
  561. WmipDebugPrint(("WMI: WmipAlloc %x (%x)\n", p, Size));
  562. return(p);
  563. }
  564. void WmipFree(
  565. PVOID p
  566. )
  567. {
  568. WmipDebugPrint(("WMI: WmipFree %x\n", p));
  569. WmipAssert(p != NULL);
  570. WmipAssert(RtlValidateProcessHeaps());
  571. RtlFreeHeap(WmipProcessHeap, 0, p);
  572. }
  573. #endif
  574. #ifdef MEMPHIS
  575. void __cdecl DebugOut(char *Format, ...)
  576. {
  577. char Buffer[1024];
  578. va_list pArg;
  579. ULONG i;
  580. va_start(pArg, Format);
  581. i = _vsnprintf(Buffer, sizeof(Buffer), Format, pArg);
  582. OutputDebugString(Buffer);
  583. }
  584. #else
  585. void __cdecl DebugOut(char *Format, ...)
  586. {
  587. char Buffer[1024];
  588. va_list pArg;
  589. ULONG i;
  590. i = sprintf(Buffer, "[%d] - ", GetTickCount());
  591. va_start(pArg, Format);
  592. i = _vsnprintf(&Buffer[i], sizeof(Buffer), Format, pArg);
  593. DbgPrint(Buffer);
  594. }
  595. #endif
  596. #ifndef MEMPHIS
  597. ULONG WmipCheckGuidAccess(
  598. LPGUID Guid,
  599. ACCESS_MASK DesiredAccess
  600. )
  601. {
  602. HANDLE Handle;
  603. ULONG Status;
  604. Status = WmipOpenKernelGuid(Guid,
  605. DesiredAccess,
  606. &Handle,
  607. IOCTL_WMI_OPEN_GUID
  608. );
  609. if (Status == ERROR_SUCCESS)
  610. {
  611. CloseHandle(Handle);
  612. }
  613. return(Status);
  614. }
  615. ULONG WmipBuildGuidObjectAttributes(
  616. IN LPGUID Guid,
  617. OUT POBJECT_ATTRIBUTES ObjectAttributes,
  618. OUT PUNICODE_STRING GuidString,
  619. OUT PWCHAR GuidObjectName
  620. )
  621. {
  622. WCHAR GuidChar[37];
  623. WmipAssert(Guid != NULL);
  624. //
  625. // Build up guid name into the ObjectAttributes
  626. //
  627. swprintf(GuidChar, L"%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
  628. Guid->Data1, Guid->Data2,
  629. Guid->Data3,
  630. Guid->Data4[0], Guid->Data4[1],
  631. Guid->Data4[2], Guid->Data4[3],
  632. Guid->Data4[4], Guid->Data4[5],
  633. Guid->Data4[6], Guid->Data4[7]);
  634. WmipAssert(wcslen(GuidChar) == 36);
  635. wcscpy(GuidObjectName, WmiGuidObjectDirectory);
  636. wcscat(GuidObjectName, GuidChar);
  637. RtlInitUnicodeString(GuidString, GuidObjectName);
  638. memset(ObjectAttributes, 0, sizeof(OBJECT_ATTRIBUTES));
  639. ObjectAttributes->Length = sizeof(OBJECT_ATTRIBUTES);
  640. ObjectAttributes->ObjectName = GuidString;
  641. return(ERROR_SUCCESS);
  642. }
  643. ULONG WmipOpenKernelGuid(
  644. LPGUID Guid,
  645. ACCESS_MASK DesiredAccess,
  646. PHANDLE Handle,
  647. ULONG Ioctl
  648. )
  649. {
  650. WMIOPENGUIDBLOCK WmiOpenGuidBlock;
  651. UNICODE_STRING GuidString;
  652. ULONG ReturnSize;
  653. ULONG Status;
  654. WCHAR GuidObjectName[WmiGuidObjectNameLength+1];
  655. OBJECT_ATTRIBUTES ObjectAttributes;
  656. Status = WmipBuildGuidObjectAttributes(Guid,
  657. &ObjectAttributes,
  658. &GuidString,
  659. GuidObjectName);
  660. if (Status == ERROR_SUCCESS)
  661. {
  662. WmiOpenGuidBlock.ObjectAttributes = &ObjectAttributes;
  663. WmiOpenGuidBlock.DesiredAccess = DesiredAccess;
  664. Status = WmipSendWmiKMRequest(NULL,
  665. Ioctl,
  666. (PVOID)&WmiOpenGuidBlock,
  667. sizeof(WMIOPENGUIDBLOCK),
  668. (PVOID)&WmiOpenGuidBlock,
  669. sizeof(WMIOPENGUIDBLOCK),
  670. &ReturnSize,
  671. NULL);
  672. if (Status == ERROR_SUCCESS)
  673. {
  674. *Handle = WmiOpenGuidBlock.Handle.Handle;
  675. } else {
  676. *Handle = NULL;
  677. }
  678. }
  679. return(Status);
  680. }
  681. #endif
  682.