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.

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