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.

2400 lines
66 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. bmofio.cpp
  5. Abstract:
  6. Binary mof Win32 subparser for Loc Studio
  7. Author:
  8. 16-Jan-1997 AlanWar
  9. Revision History:
  10. --*/
  11. #if DEBUG_HEAP
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #endif
  16. #include <windows.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <wbemcli.h>
  20. #include "dllcalls.h"
  21. #include "bmfmisc.h"
  22. #include "mrcicode.h"
  23. #include "bmof.h"
  24. ULONG GenerateMofForObj(
  25. PMOFFILETARGET MofFileTarget,
  26. CBMOFObj *Obj
  27. );
  28. //
  29. // Each class has one or more data items that are described by a MOFDATAITEM
  30. // structure.
  31. typedef struct
  32. {
  33. PWCHAR Name;
  34. PWCHAR DataType; // Method return type
  35. ULONG Flags; // Flags, See MOFDI_FLAG_*
  36. CBMOFQualList * QualifierList;
  37. } METHODPARAMETER, *PMETHODPARAMETER;
  38. // Data item is actually a fixed sized array
  39. #define MOFDI_FLAG_ARRAY 0x00000001
  40. // Data item is an input method parameter
  41. #define MOFDI_FLAG_INPUT_METHOD 0x00000100
  42. // Data item is an output method parameter
  43. #define MOFDI_FLAG_OUTPUT_METHOD 0x00000200
  44. //
  45. // The MOFCLASSINFO structure describes the format of a data block
  46. typedef struct
  47. {
  48. PWCHAR ReturnDataType;
  49. ULONG ParamCount; // Number of wmi data items (properties)
  50. // Array of Property info
  51. METHODPARAMETER Parameters[1];
  52. } METHODPARAMLIST, *PMETHODPARAMLIST;
  53. //
  54. // Definitions for WmipAlloc/WmipFree. On debug builds we use our own
  55. // heap. Be aware that heap creation is not serialized.
  56. //
  57. #if 0
  58. #if DEBUG_HEAP
  59. PVOID WmiPrivateHeap;
  60. PVOID _stdcall WmipAlloc(ULONG size)
  61. {
  62. PVOID p = NULL;
  63. if (WmiPrivateHeap == NULL)
  64. {
  65. WmiPrivateHeap = RtlCreateHeap(HEAP_GROWABLE |
  66. HEAP_TAIL_CHECKING_ENABLED |
  67. HEAP_FREE_CHECKING_ENABLED |
  68. HEAP_DISABLE_COALESCE_ON_FREE,
  69. NULL,
  70. 0,
  71. 0,
  72. NULL,
  73. NULL);
  74. }
  75. if (WmiPrivateHeap != NULL)
  76. {
  77. p = RtlAllocateHeap(WmiPrivateHeap, 0, size);
  78. if (p != NULL)
  79. {
  80. memset(p, 0, size);
  81. }
  82. }
  83. return(p);
  84. }
  85. void _stdcall WmipFree(PVOID p)
  86. {
  87. RtlFreeHeap(WmiPrivateHeap, 0, p);
  88. }
  89. #else
  90. PVOID _stdcall WmipAlloc(ULONG size)
  91. {
  92. return(LocalAlloc(LPTR, size));
  93. }
  94. void _stdcall WmipFree(PVOID p)
  95. {
  96. LocalFree(p);
  97. }
  98. #endif
  99. #endif
  100. #define WmipAlloc malloc
  101. #define WmipFree free
  102. //
  103. // Definitions for WmipAssert
  104. //
  105. #if DBG
  106. #define WmipAssert(x) if (! (x) ) { \
  107. WmipDebugPrint(("BMOFLocParser Assertion: "#x" at %s %d\n", __FILE__, __LINE__)); \
  108. DebugBreak(); }
  109. #else
  110. #define WmipAssert(x)
  111. #endif
  112. //
  113. // WmipDebugPrint definitions
  114. //
  115. #if DBG
  116. #define WmipDebugPrint(x) WmiDebugPrint x
  117. VOID
  118. WmiDebugPrint(
  119. PCHAR DebugMessage,
  120. ...
  121. )
  122. /*++
  123. Routine Description:
  124. Debug print for properties pages - stolen from classpnp\class.c
  125. Arguments:
  126. Debug print level between 0 and 3, with 3 being the most verbose.
  127. Return Value:
  128. None
  129. --*/
  130. {
  131. #define DEBUG_BUFFER_LENGTH 512
  132. static CHAR WmiBuffer[DEBUG_BUFFER_LENGTH];
  133. va_list ap;
  134. va_start(ap, DebugMessage);
  135. _vsnprintf(WmiBuffer, DEBUG_BUFFER_LENGTH, DebugMessage, ap);
  136. OutputDebugStringA(WmiBuffer);
  137. va_end(ap);
  138. } // end WmiDebugPrint()
  139. #else
  140. #define WmipDebugPrint(x)
  141. #endif
  142. ULONG AnsiToUnicode(
  143. LPCSTR pszA,
  144. LPWSTR *ppszW
  145. )
  146. /*++
  147. Routine Description:
  148. Convert Ansi string into its Unicode equivalent
  149. Arguments:
  150. pszA is ansi string to convert
  151. *ppszW on entry has a pointer to a unicode string into which the answer
  152. is written. If NULL on entry then a buffer is allocated and returned
  153. in it.
  154. Return Value:
  155. Error code
  156. --*/
  157. {
  158. ULONG cCharacters;
  159. ULONG Status;
  160. ULONG cbUnicodeUsed;
  161. //
  162. // If input is null then just return the same.
  163. if (pszA == NULL)
  164. {
  165. *ppszW = NULL;
  166. return(ERROR_SUCCESS);
  167. }
  168. //
  169. // Determine the count of characters needed for Unicode string
  170. cCharacters = MultiByteToWideChar(CP_ACP, 0, pszA, -1, NULL, 0);
  171. if (cCharacters == 0)
  172. {
  173. *ppszW = NULL;
  174. return(GetLastError());
  175. }
  176. // Convert to Unicode
  177. cbUnicodeUsed = MultiByteToWideChar(CP_ACP, 0, pszA, -1, *ppszW, cCharacters);
  178. if (0 == cbUnicodeUsed)
  179. {
  180. Status = GetLastError();
  181. return(Status);
  182. }
  183. return(ERROR_SUCCESS);
  184. }
  185. ULONG AppendFileToFile(
  186. TCHAR *DestFile,
  187. TCHAR *SrcFile
  188. )
  189. {
  190. #define READ_BLOCK_SIZE 0x8000
  191. HANDLE DestHandle, SrcHandle;
  192. ULONG BytesRead, BytesWritten;
  193. PUCHAR Buffer;
  194. BOOL b;
  195. ULONG Status = ERROR_SUCCESS;
  196. Buffer = (PUCHAR)WmipAlloc(READ_BLOCK_SIZE);
  197. if (Buffer != NULL)
  198. {
  199. DestHandle = CreateFile(DestFile,
  200. GENERIC_READ | GENERIC_WRITE,
  201. 0,
  202. NULL,
  203. OPEN_EXISTING,
  204. FILE_ATTRIBUTE_NORMAL,
  205. NULL);
  206. if (DestHandle != INVALID_HANDLE_VALUE)
  207. {
  208. SrcHandle = CreateFile(SrcFile,
  209. GENERIC_READ,
  210. 0,
  211. NULL,
  212. OPEN_EXISTING,
  213. FILE_ATTRIBUTE_NORMAL,
  214. NULL);
  215. if (SrcHandle != INVALID_HANDLE_VALUE)
  216. {
  217. b = SetFilePointer(DestHandle,
  218. 0,
  219. NULL,
  220. FILE_END);
  221. if (b)
  222. {
  223. do
  224. {
  225. b = ReadFile(SrcHandle,
  226. Buffer,
  227. READ_BLOCK_SIZE,
  228. &BytesRead,
  229. NULL);
  230. if (b)
  231. {
  232. b = WriteFile(DestHandle,
  233. Buffer,
  234. BytesRead,
  235. &BytesWritten,
  236. NULL);
  237. if (!b)
  238. {
  239. Status = GetLastError();
  240. break;
  241. } else if (BytesWritten != BytesRead) {
  242. Status = ERROR_BAD_LENGTH;
  243. break;
  244. }
  245. } else {
  246. Status = GetLastError();
  247. break;
  248. }
  249. } while (BytesRead == READ_BLOCK_SIZE);
  250. } else {
  251. Status = GetLastError();
  252. }
  253. CloseHandle(SrcHandle);
  254. } else {
  255. Status = GetLastError();
  256. }
  257. CloseHandle(DestHandle);
  258. } else {
  259. Status = GetLastError();
  260. }
  261. WmipFree(Buffer);
  262. } else {
  263. Status = ERROR_NOT_ENOUGH_MEMORY;
  264. }
  265. return(Status);
  266. }
  267. BOOLEAN ConvertMofToBmf(
  268. TCHAR *MofFile,
  269. TCHAR *EnglishMofFile,
  270. TCHAR *BmfFile
  271. )
  272. {
  273. WBEM_COMPILE_STATUS_INFO info;
  274. SCODE sc;
  275. LONG OptionFlags, ClassFlags, InstanceFlags;
  276. PWCHAR NameSpace;
  277. WCHAR MofFileStatic[MAX_PATH];
  278. WCHAR BmfFileStatic[MAX_PATH];
  279. PWCHAR BmfFileW, MofFileW;
  280. BOOLEAN Success;
  281. ULONG Status;
  282. if (*EnglishMofFile != 0)
  283. {
  284. Status = AppendFileToFile(MofFile, EnglishMofFile);
  285. if (Status != ERROR_SUCCESS)
  286. {
  287. return(FALSE);
  288. }
  289. }
  290. #if 0
  291. OutputDebugString(MofFile);
  292. OutputDebugString("\n");
  293. DebugBreak();
  294. #endif
  295. NameSpace = L"";
  296. OptionFlags = 0;
  297. ClassFlags = 0;
  298. InstanceFlags = 0;
  299. MofFileW = MofFileStatic;
  300. Status = AnsiToUnicode(MofFile, &MofFileW);
  301. if ((Status == ERROR_SUCCESS) &&
  302. (MofFileW != NULL))
  303. {
  304. BmfFileW = BmfFileStatic;
  305. Status = AnsiToUnicode(BmfFile, &BmfFileW);
  306. if ((Status == ERROR_SUCCESS) &&
  307. (BmfFileW != NULL))
  308. {
  309. sc = CreateBMOFViaDLL( MofFileW,
  310. BmfFileW,
  311. NameSpace,
  312. OptionFlags,
  313. ClassFlags,
  314. InstanceFlags,
  315. &info);
  316. Success = (sc == S_OK);
  317. } else {
  318. Success = FALSE;
  319. }
  320. } else {
  321. Success = FALSE;
  322. }
  323. return(Success);
  324. }
  325. ULONG FilePrintVaList(
  326. HANDLE FileHandle,
  327. WCHAR *Format,
  328. va_list pArg
  329. )
  330. {
  331. WCHAR Buffer[8192];
  332. ULONG Size, Written;
  333. ULONG Status;
  334. Size = _vsnwprintf(Buffer, sizeof(Buffer)/sizeof(WCHAR), Format, pArg);
  335. if (WriteFile(FileHandle,
  336. Buffer,
  337. Size * sizeof(WCHAR),
  338. &Written,
  339. NULL))
  340. {
  341. Status = ERROR_SUCCESS;
  342. } else {
  343. Status = GetLastError();
  344. }
  345. return(Status);
  346. }
  347. ULONG FilePrint(
  348. PMOFFILETARGET MofFileTarget,
  349. WCHAR *Format,
  350. ...
  351. )
  352. {
  353. ULONG Status;
  354. va_list pArg;
  355. va_start(pArg, Format);
  356. Status = FilePrintVaList(MofFileTarget->MofHandle, Format, pArg);
  357. if ((MofFileTarget->WriteToEnglish) &&
  358. (Status == ERROR_SUCCESS) &&
  359. (MofFileTarget->EnglishMofHandle != NULL))
  360. {
  361. Status = FilePrintVaList(MofFileTarget->EnglishMofHandle, Format, pArg);
  362. }
  363. return(Status);
  364. }
  365. ULONG FilePrintToHandle(
  366. HANDLE FileHandle,
  367. WCHAR *Format,
  368. ...
  369. )
  370. {
  371. ULONG Status;
  372. va_list pArg;
  373. va_start(pArg, Format);
  374. Status = FilePrintVaList(FileHandle, Format, pArg);
  375. return(Status);
  376. }
  377. ULONG WmipDecompressBuffer(
  378. IN PUCHAR CompressedBuffer,
  379. OUT PUCHAR *UncompressedBuffer,
  380. OUT ULONG *UncompressedSize
  381. )
  382. /*++
  383. Routine Description:
  384. This routine will decompress a compressed MOF blob into a buffer
  385. that can be used to interpert the blob.
  386. Arguments:
  387. CompressedBuffer points at the compressed MOF blob
  388. *UncompressedBuffer returns with a pointer to the uncompressed
  389. MOF blob
  390. Return Value:
  391. ERROR_SUCCESS or an error code
  392. --*/
  393. {
  394. PBMOFCOMPRESSEDHEADER CompressedHeader = (PBMOFCOMPRESSEDHEADER)CompressedBuffer;
  395. BYTE *Buffer;
  396. ULONG Status;
  397. if ((CompressedHeader->Signature != BMOF_SIG) ||
  398. (CompressedHeader->CompressionType != 1))
  399. {
  400. // TODO: LocStudio message
  401. WmipDebugPrint(("WMI: Invalid compressed mof header\n"));
  402. Status = ERROR_INVALID_PARAMETER;
  403. } else {
  404. Buffer = (BYTE *)WmipAlloc(CompressedHeader->UncompressedSize);
  405. if (Buffer == NULL)
  406. {
  407. Status = ERROR_NOT_ENOUGH_MEMORY;
  408. } else {
  409. *UncompressedSize = Mrci1Decompress(&CompressedHeader->Buffer[0],
  410. CompressedHeader->CompressedSize,
  411. Buffer,
  412. CompressedHeader->UncompressedSize);
  413. if (*UncompressedSize != CompressedHeader->UncompressedSize)
  414. {
  415. // TODO: LocStudioMessage
  416. WmipDebugPrint(("WMI: Invalid compressed mof buffer\n"));
  417. WmipFree(Buffer);
  418. Status = ERROR_INVALID_PARAMETER;
  419. } else {
  420. *UncompressedBuffer = Buffer;
  421. Status = ERROR_SUCCESS;
  422. }
  423. }
  424. }
  425. return(Status);
  426. }
  427. ULONG WmipFindMofQualifier(
  428. CBMOFQualList *QualifierList,
  429. LPCWSTR QualifierName,
  430. DWORD *QualifierType,
  431. DWORD *NumberElements,
  432. PVOID QualifierValueBuffer
  433. )
  434. /*++
  435. Routine Description:
  436. This routine will find a MOF qualifier within the qualifier list passed,
  437. ensure that its type matches the type requested and return the qualifier's
  438. value
  439. Arguments:
  440. QualifierList is the MOF qualifier list
  441. QualifierName is the name of the qualifier to search for
  442. *QualifierType on entry has the qualifier type being searched for. On exit
  443. it has the actual qualifier type for the qualifier value. If on entry
  444. *QualifierType is 0xffffffff then any qualifier type is acceptable
  445. *NumberElements returns the number of elements in the array if the result
  446. of the qualifier is an array
  447. QualifierValueBuffer points to a buffer that returns the value of the
  448. qualifier. If the qualifier is a simple type (int or int64) then
  449. the value is returned in the buffer. If qualifier value is a string
  450. then a pointer to the string is returned in the buffer
  451. Return Value:
  452. ERROR_SUCCESS or a WMI Mof error code (see wmiump.h)
  453. --*/
  454. {
  455. CBMOFDataItem MofDataItem;
  456. ULONG Status;
  457. PUCHAR List, ListPtr;
  458. ULONG BaseTypeSize;
  459. LONG ElementCount;
  460. LONG i;
  461. if (QualifierList == NULL)
  462. {
  463. return(ERROR_FILE_NOT_FOUND);
  464. }
  465. if (FindQual(QualifierList, (PWCHAR)QualifierName, &MofDataItem))
  466. {
  467. if ((*QualifierType != 0xffffffff) &&
  468. (MofDataItem.m_dwType != *QualifierType))
  469. {
  470. Status = ERROR_INVALID_PARAMETER;
  471. }
  472. if (MofDataItem.m_dwType & VT_ARRAY)
  473. {
  474. if (MofDataItem.m_dwType == (VT_BSTR | VT_ARRAY))
  475. {
  476. BaseTypeSize = sizeof(PWCHAR);
  477. } else {
  478. BaseTypeSize = iTypeSize(MofDataItem.m_dwType);
  479. }
  480. ElementCount = GetNumElements(&MofDataItem, 0);
  481. if (NumberElements != NULL)
  482. {
  483. *NumberElements = ElementCount;
  484. }
  485. if (ElementCount != -1)
  486. {
  487. List = (PUCHAR)WmipAlloc(ElementCount * BaseTypeSize);
  488. if (List != NULL)
  489. {
  490. ListPtr = List;
  491. for (i = 0; i < ElementCount; i++)
  492. {
  493. if ((GetData(&MofDataItem,
  494. (BYTE *)ListPtr,
  495. &i)) == 0)
  496. {
  497. WmipFree(List);
  498. Status = ERROR_INVALID_PARAMETER;
  499. return(Status);
  500. }
  501. ListPtr += BaseTypeSize;
  502. }
  503. Status = ERROR_SUCCESS;
  504. *QualifierType = MofDataItem.m_dwType;
  505. *((PVOID *)QualifierValueBuffer) = List;
  506. } else {
  507. Status = ERROR_NOT_ENOUGH_MEMORY;
  508. }
  509. }
  510. } else {
  511. if (GetData(&MofDataItem, (BYTE *)QualifierValueBuffer, 0) == 0)
  512. {
  513. Status = ERROR_INVALID_PARAMETER;
  514. } else {
  515. *QualifierType = MofDataItem.m_dwType;
  516. Status = ERROR_SUCCESS;
  517. }
  518. }
  519. } else {
  520. Status = ERROR_FILE_NOT_FOUND;
  521. }
  522. return(Status);
  523. }
  524. ULONG WmipFindProperty(
  525. CBMOFObj * ClassObject,
  526. WCHAR * PropertyName,
  527. CBMOFDataItem *MofPropertyData,
  528. DWORD *ValueType,
  529. PVOID ValueBuffer
  530. )
  531. /*++
  532. Routine Description:
  533. This routine will find a named property within a class object
  534. Arguments:
  535. ClassObject is the class object in which to search
  536. PropertyName is the name of the property to search for
  537. MofPropertyData returns with the property data
  538. *ValueType on entry has the property data type being searched for. On exit
  539. it has the actual qualifier type for the qualifier value. If on entry
  540. *ValueType is 0xffffffff then any data type is acceptable
  541. ValueBuffer points to a buffer that returns the value of the
  542. property. If the property is a simple type (int or int64) then
  543. the value is returned in the buffer. If qualifier value is a string
  544. then a pointer to the string is returned in the buffer
  545. Return Value:
  546. ERROR_SUCCESS or a WMI Mof error code (see wmiump.h)
  547. --*/
  548. {
  549. ULONG Status;
  550. if (FindProp(ClassObject, PropertyName, MofPropertyData))
  551. {
  552. if ((*ValueType != 0xffffffff) &&
  553. (MofPropertyData->m_dwType != *ValueType))
  554. {
  555. Status = ERROR_INVALID_PARAMETER;
  556. }
  557. if (GetData(MofPropertyData, (BYTE *)ValueBuffer, 0) == 0)
  558. {
  559. Status = ERROR_INVALID_PARAMETER;
  560. } else {
  561. *ValueType = MofPropertyData->m_dwType;
  562. Status = ERROR_SUCCESS;
  563. }
  564. } else {
  565. Status = ERROR_FILE_NOT_FOUND;
  566. }
  567. return(Status);
  568. }
  569. PWCHAR AddSlashesToString(
  570. PWCHAR SlashedNamespace,
  571. PWCHAR Namespace
  572. )
  573. {
  574. PWCHAR Return = SlashedNamespace;
  575. //
  576. // MOF likes the namespace paths to be C-style, that is to have a
  577. // '\\' instad of a '\'. So whereever we see a '\', we insert a
  578. // second one
  579. //
  580. while (*Namespace != 0)
  581. {
  582. if (*Namespace == L'\\')
  583. {
  584. *SlashedNamespace++ = L'\\';
  585. }
  586. *SlashedNamespace++ = *Namespace++;
  587. }
  588. *SlashedNamespace = 0;
  589. return(Return);
  590. }
  591. ULONG GenerateDataValueFromVariant(
  592. PMOFFILETARGET MofFileTarget,
  593. VARIANT *var
  594. )
  595. {
  596. SCODE sc;
  597. VARIANT vTemp;
  598. ULONG Status;
  599. PWCHAR String;
  600. //
  601. // Uninitialized data will have a VT_NULL type.
  602. //
  603. if (var->vt == VT_NULL)
  604. {
  605. return(ERROR_SUCCESS);
  606. }
  607. //
  608. // String types can just be dumped.
  609. //
  610. if (var->vt == VT_BSTR)
  611. {
  612. String = (PWCHAR)WmipAlloc(((wcslen(var->bstrVal)) *
  613. sizeof(WCHAR) * 2) + sizeof(WCHAR));
  614. if (String != NULL)
  615. {
  616. Status = FilePrint(MofFileTarget,
  617. L"\"%ws\"",
  618. AddSlashesToString(String, var->bstrVal));
  619. WmipFree(String);
  620. } else {
  621. Status = ERROR_NOT_ENOUGH_MEMORY;
  622. }
  623. return(Status);
  624. }
  625. //
  626. // References need to be maintained
  627. //
  628. if (var->vt == (VT_BSTR | VT_BYREF))
  629. {
  630. String = (PWCHAR)WmipAlloc(((wcslen(var->bstrVal)) *
  631. sizeof(WCHAR) * 2) + sizeof(WCHAR));
  632. if (String != NULL)
  633. {
  634. Status = FilePrint(MofFileTarget,
  635. L"$%ws",
  636. AddSlashesToString(String, var->bstrVal));
  637. WmipFree(String);
  638. } else {
  639. Status = ERROR_NOT_ENOUGH_MEMORY;
  640. }
  641. return(Status);
  642. }
  643. //
  644. // Embedded classes, so recurse in to display the contents of it
  645. //
  646. if (var->vt == VT_UNKNOWN)
  647. {
  648. CBMOFObj * pObj;
  649. WmipDebugPrint(("BMOFLocParser: Data is an embeeded object %p\n",
  650. var));
  651. pObj = (CBMOFObj *)var->bstrVal;
  652. Status = GenerateMofForObj(MofFileTarget,
  653. pObj);
  654. return(Status);
  655. }
  656. if (var->vt == VT_BOOL)
  657. {
  658. if (var->boolVal)
  659. {
  660. Status = FilePrint(MofFileTarget, L"%ws", L"TRUE");
  661. } else {
  662. Status = FilePrint(MofFileTarget, L"%ws", L"FALSE");
  663. }
  664. return(Status);
  665. }
  666. //
  667. // For non string data, convert the infomation to a bstr and display it.
  668. //
  669. VariantInit(&vTemp);
  670. sc = VariantChangeTypeEx(&vTemp, var,0,0, VT_BSTR);
  671. if (sc == S_OK)
  672. {
  673. Status = FilePrint(MofFileTarget,
  674. L"%ws",
  675. vTemp.bstrVal);
  676. VariantClear(&vTemp);
  677. } else {
  678. Status = sc;
  679. }
  680. return(Status);
  681. }
  682. ULONG GenerateDataValue(
  683. PMOFFILETARGET MofFileTarget,
  684. CBMOFDataItem *Item
  685. )
  686. {
  687. DWORD Type, SimpleType;
  688. long NumDim, i;
  689. long FirstDim;
  690. VARIANT var;
  691. BOOLEAN FirstIndex;
  692. ULONG Status = ERROR_SUCCESS;
  693. //
  694. // Determine the data type and clear out the variant
  695. //
  696. Type = Item->m_dwType;
  697. SimpleType = Type & ~VT_ARRAY;
  698. memset((void *)&var.lVal, 0, 8);
  699. NumDim = GetNumDimensions(Item);
  700. if (NumDim == 0)
  701. {
  702. //
  703. // handle the simple scalar case. Note that uninitialized properties
  704. // will not have data.
  705. //
  706. if(GetData(Item, (BYTE *)&(var.lVal), NULL))
  707. {
  708. var.vt = (VARTYPE)SimpleType;
  709. Status = GenerateDataValueFromVariant(MofFileTarget,
  710. &var);
  711. if (var.vt == VT_BSTR)
  712. {
  713. BMOFFree(var.bstrVal);
  714. }
  715. }
  716. } else if (NumDim == 1) {
  717. //
  718. // For the array case, just loop getting each element.
  719. // Start by getting the number of elements
  720. //
  721. FirstDim = GetNumElements(Item, 0);
  722. Status = ERROR_SUCCESS;
  723. FirstIndex = TRUE;
  724. for (i = 0; (i < FirstDim) && (Status == ERROR_SUCCESS); i++)
  725. {
  726. if (! FirstIndex)
  727. {
  728. FilePrint(MofFileTarget,
  729. L", ");
  730. } else {
  731. FirstIndex = FALSE;
  732. }
  733. if (GetData(Item, (BYTE *)&(var.lVal), &i))
  734. {
  735. var.vt = (VARTYPE)SimpleType;
  736. Status = GenerateDataValueFromVariant(MofFileTarget,
  737. &var);
  738. if(var.vt == VT_BSTR)
  739. {
  740. BMOFFree(var.bstrVal);
  741. }
  742. }
  743. }
  744. } else {
  745. //
  746. // Currently undefined and multidimension arrays are not
  747. // supported.
  748. //
  749. WmipDebugPrint(("BMOFLocParser: Multi dimensional arrays not supported\n"));
  750. WmipAssert(FALSE);
  751. Status = ERROR_INVALID_PARAMETER;
  752. }
  753. return(Status);
  754. }
  755. #define MAX_FLAVOR_TEXT_SIZE MAX_PATH
  756. WCHAR *FlavorToText(
  757. WCHAR *ClassFlagsText,
  758. ULONG ClassFlags
  759. )
  760. {
  761. PWCHAR CommaText;
  762. //
  763. // TODO: FInd any undocumented flavors
  764. //
  765. CommaText = L"";
  766. *ClassFlagsText = 0;
  767. if (ClassFlags & FlavorAmended)
  768. {
  769. //
  770. // since this is the first if, we can assume that a , would
  771. // never be needed
  772. //
  773. wcscat(ClassFlagsText, L"amended");
  774. CommaText = L",";
  775. }
  776. if (ClassFlags & FlavorDisableOverride)
  777. {
  778. wcscat(ClassFlagsText, CommaText);
  779. wcscat(ClassFlagsText, L"DisableOverride");
  780. CommaText = L",";
  781. }
  782. if (ClassFlags & FlavorToSubclass)
  783. {
  784. wcscat(ClassFlagsText, CommaText);
  785. wcscat(ClassFlagsText, L"ToSubclass");
  786. CommaText = L",";
  787. }
  788. if (ClassFlags & FlavorToInstance)
  789. {
  790. wcscat(ClassFlagsText, CommaText);
  791. wcscat(ClassFlagsText, L"ToInstance");
  792. CommaText = L",";
  793. }
  794. WmipAssert(*ClassFlagsText != 0);
  795. WmipDebugPrint(("BmofLocParser: Flavor : %ws\n", ClassFlagsText));
  796. return(ClassFlagsText);
  797. }
  798. ULONG GenerateQualifierList(
  799. PMOFFILETARGET MofFileTarget,
  800. CBMOFQualList * QualifierList,
  801. BOOLEAN SkipId
  802. )
  803. {
  804. WCHAR *Name = NULL;
  805. CBMOFDataItem Item;
  806. BOOLEAN FirstQualifier;
  807. WCHAR OpenChar, CloseChar;
  808. ULONG Status = ERROR_SUCCESS;
  809. ULONG Flavor = 0;
  810. WCHAR s[MAX_FLAVOR_TEXT_SIZE];
  811. FirstQualifier = TRUE;
  812. ResetQualList(QualifierList);
  813. while ((Status == ERROR_SUCCESS) &&
  814. (NextQualEx(QualifierList,
  815. &Name,
  816. &Item,
  817. &Flavor,
  818. MofFileTarget->UncompressedBlob)))
  819. {
  820. //
  821. // TODO: if this is a mofcomp generated qualifier then we want
  822. // to ignore it
  823. //
  824. if (_wcsicmp(Name, L"CIMTYPE") == 0)
  825. {
  826. // must skip CIMTYPE qualifier
  827. continue;
  828. }
  829. if ((SkipId) && _wcsicmp(Name, L"ID") == 0)
  830. {
  831. // If we want to skip the ID qualifier then do so
  832. continue;
  833. }
  834. if (FirstQualifier)
  835. {
  836. Status = FilePrint(MofFileTarget,
  837. L"[");
  838. FirstQualifier = FALSE;
  839. } else {
  840. Status = FilePrint(MofFileTarget,
  841. L",\r\n ");
  842. }
  843. if (Status == ERROR_SUCCESS)
  844. {
  845. //
  846. // Arrays use {} to enclose the value of the qualifier
  847. // while scalers use ()
  848. //
  849. if (Item.m_dwType & VT_ARRAY)
  850. {
  851. OpenChar = L'{';
  852. CloseChar = L'}';
  853. } else {
  854. OpenChar = L'(';
  855. CloseChar = L')';
  856. }
  857. Status = FilePrint(MofFileTarget,
  858. L"%ws%wc",
  859. Name, OpenChar);
  860. if (Status == ERROR_SUCCESS)
  861. {
  862. Status = GenerateDataValue(MofFileTarget,
  863. &Item);
  864. if (Status == ERROR_SUCCESS)
  865. {
  866. Status = FilePrint(MofFileTarget,
  867. L"%wc",
  868. CloseChar);
  869. if ((Status == ERROR_SUCCESS) && (Flavor != 0))
  870. {
  871. Status = FilePrint(MofFileTarget,
  872. L": %ws",
  873. FlavorToText(s, Flavor));
  874. }
  875. }
  876. }
  877. }
  878. BMOFFree(Name);
  879. Flavor = 0;
  880. }
  881. if ((Status == ERROR_SUCCESS) && ! FirstQualifier)
  882. {
  883. //
  884. // if we had generated qualifiers then we need a closing ]
  885. //
  886. Status = FilePrint(MofFileTarget,
  887. L"]\r\n");
  888. }
  889. return(Status);
  890. }
  891. PWCHAR GeneratePropertyName(
  892. PWCHAR StringPtr
  893. )
  894. {
  895. #define ObjectTextLen ( ((sizeof(L"object:") / sizeof(WCHAR)) - 1) )
  896. PWCHAR PropertyType;
  897. //
  898. // If CIMTYPE begins with object: then it is an embedded object
  899. // and we need to skip the object: in the MOF generation
  900. //
  901. if (_wcsnicmp(StringPtr, L"object:", ObjectTextLen) == 0)
  902. {
  903. PropertyType = StringPtr + ObjectTextLen;
  904. } else {
  905. PropertyType = StringPtr;
  906. }
  907. return(PropertyType);
  908. }
  909. ULONG GenerateProperty(
  910. PMOFFILETARGET MofFileTarget,
  911. PWCHAR PropertyName,
  912. BOOLEAN IsInstance,
  913. CBMOFQualList * QualifierList,
  914. CBMOFDataItem *Property
  915. )
  916. {
  917. DWORD QualifierType;
  918. WCHAR *StringPtr;
  919. ULONG Status;
  920. PWCHAR ArraySuffix;
  921. PWCHAR PropertyType;
  922. PWCHAR ArrayText;
  923. QualifierType = VT_BSTR;
  924. Status = WmipFindMofQualifier(QualifierList,
  925. L"CIMTYPE",
  926. &QualifierType,
  927. NULL,
  928. (PVOID)&StringPtr);
  929. if (IsInstance)
  930. {
  931. //
  932. // Property is within an instance definition
  933. //
  934. Status = FilePrint(MofFileTarget,
  935. L"%ws = ",
  936. PropertyName);
  937. if (Status == ERROR_SUCCESS)
  938. {
  939. if (Property->m_dwType & VT_ARRAY)
  940. {
  941. //
  942. // use {} around arrays
  943. //
  944. Status = FilePrint(MofFileTarget,
  945. L"{ ");
  946. ArrayText = L"};";
  947. } else if (Property->m_dwType == VT_UNKNOWN) {
  948. ArrayText = L"";
  949. } else {
  950. ArrayText = L";";
  951. }
  952. if (Status == ERROR_SUCCESS)
  953. {
  954. Status = GenerateDataValue(MofFileTarget,
  955. Property);
  956. if (Status == ERROR_SUCCESS)
  957. {
  958. Status = FilePrint(MofFileTarget,
  959. L"%ws\r\n",
  960. ArrayText);
  961. }
  962. }
  963. }
  964. } else {
  965. //
  966. // Property is within a class definition, so just worry about
  967. // defining it.
  968. //
  969. if (Status == ERROR_SUCCESS)
  970. {
  971. PropertyType = GeneratePropertyName(StringPtr);
  972. if (Property->m_dwType & VT_ARRAY)
  973. {
  974. ArraySuffix = L"[]";
  975. } else {
  976. ArraySuffix = L"";
  977. }
  978. WmipDebugPrint(("BmofLocParser: %ws %ws%ws\n",
  979. PropertyType,
  980. PropertyName,
  981. ArraySuffix));
  982. Status = FilePrint(MofFileTarget,
  983. L"%ws %ws%ws;\r\n",
  984. PropertyType,
  985. PropertyName,
  986. ArraySuffix);
  987. BMOFFree(StringPtr);
  988. }
  989. }
  990. return(Status);
  991. }
  992. ULONG GetDataItemCount(
  993. CBMOFObj * ClassObject,
  994. PWCHAR QualifierToFind
  995. )
  996. /*++
  997. Routine Description:
  998. This routine will count the number of WMI data items in the class and
  999. the total number of properties in the class.
  1000. Arguments:
  1001. ClassObject is class for which we count the number of data items
  1002. *TotalCount returns the total number of properties
  1003. Return Value:
  1004. Count of methods
  1005. --*/
  1006. {
  1007. CBMOFQualList *PropQualifierList;
  1008. CBMOFDataItem MofPropertyData;
  1009. DWORD QualifierType;
  1010. ULONG Counter = 0;
  1011. WCHAR *PropertyName;
  1012. ULONG Status;
  1013. ULONG Index;
  1014. ResetObj(ClassObject);
  1015. while (NextProp(ClassObject, &PropertyName, &MofPropertyData))
  1016. {
  1017. PropQualifierList = GetPropQualList(ClassObject, PropertyName);
  1018. if (PropQualifierList != NULL)
  1019. {
  1020. //
  1021. // Get the id of the property so we know it order in class
  1022. QualifierType = VT_I4;
  1023. Status = WmipFindMofQualifier(PropQualifierList,
  1024. QualifierToFind,
  1025. &QualifierType,
  1026. NULL,
  1027. (PVOID)&Index);
  1028. if (Status == ERROR_SUCCESS)
  1029. {
  1030. Counter++;
  1031. }
  1032. }
  1033. BMOFFree(PropertyName);
  1034. }
  1035. return(Counter);
  1036. }
  1037. ULONG ParseMethodInOutObject(
  1038. CBMOFObj *ClassObject,
  1039. PMETHODPARAMLIST ParamList,
  1040. ULONG DataItemCount
  1041. )
  1042. /*++
  1043. Routine Description:
  1044. This routine will parse a class object that is either the in or out
  1045. parameters for a method.
  1046. Arguments:
  1047. ClassObject is the in or out parameter class object to parse
  1048. ClassInfo returns updated with information from ClassObject
  1049. DataItemCount is the number of data items in the ClassInfo
  1050. Return Value:
  1051. ERROR_SUCCESS or a WMI Mof error code (see wmiump.h)
  1052. --*/
  1053. {
  1054. ULONG Status;
  1055. CBMOFDataItem MofPropertyData;
  1056. PWCHAR PropertyName = NULL;
  1057. ULONG Index;
  1058. PMETHODPARAMETER MethodParam;
  1059. CBMOFQualList *QualifierList = NULL;
  1060. DWORD QualifierType;
  1061. short BooleanValue;
  1062. PWCHAR StringPtr;
  1063. ResetObj(ClassObject);
  1064. while (NextProp(ClassObject, &PropertyName, &MofPropertyData))
  1065. {
  1066. QualifierList = GetPropQualList(ClassObject, PropertyName);
  1067. if (QualifierList != NULL)
  1068. {
  1069. //
  1070. // Get the id of the property so we know its order in class
  1071. //
  1072. QualifierType = VT_I4;
  1073. Status = WmipFindMofQualifier(QualifierList,
  1074. L"Id",
  1075. &QualifierType,
  1076. NULL,
  1077. (PVOID)&Index);
  1078. if (Status == ERROR_SUCCESS)
  1079. {
  1080. //
  1081. // Method ids are 0 based
  1082. //
  1083. if (Index < DataItemCount)
  1084. {
  1085. //
  1086. // Valid data item id, make sure it already isn't
  1087. // in use. Note that we could have the same property
  1088. // be in both the in and the out class objects
  1089. //
  1090. MethodParam = &ParamList->Parameters[Index];
  1091. //
  1092. // If there is already an existing qualifier list
  1093. // attached then we free it and tag the new
  1094. // qualifier list to the parameter. Both lists
  1095. // should have all of the non [in] / [out]
  1096. // qualifiers
  1097. //
  1098. if (MethodParam->QualifierList != NULL)
  1099. {
  1100. BMOFFree(MethodParam->QualifierList);
  1101. }
  1102. MethodParam->QualifierList = QualifierList;
  1103. //
  1104. // See if this is an input, output or both
  1105. //
  1106. QualifierType = VT_BOOL;
  1107. Status = WmipFindMofQualifier(QualifierList,
  1108. L"in",
  1109. &QualifierType,
  1110. NULL,
  1111. (PVOID)&BooleanValue);
  1112. if ((Status == ERROR_SUCCESS) && BooleanValue)
  1113. {
  1114. MethodParam->Flags |= MOFDI_FLAG_INPUT_METHOD;
  1115. }
  1116. QualifierType = VT_BOOL;
  1117. Status = WmipFindMofQualifier(QualifierList,
  1118. L"out",
  1119. &QualifierType,
  1120. NULL,
  1121. (PVOID)&BooleanValue);
  1122. if ((Status == ERROR_SUCCESS) && BooleanValue)
  1123. {
  1124. MethodParam->Flags |= MOFDI_FLAG_OUTPUT_METHOD;
  1125. }
  1126. //
  1127. // If there is already a name and its the same as
  1128. // ours then free the old name and use the new one.
  1129. // If the names are different then we have a binary
  1130. // mof error
  1131. //
  1132. if (MethodParam->Name != NULL)
  1133. {
  1134. if (wcscmp(MethodParam->Name, PropertyName) != 0)
  1135. {
  1136. //
  1137. // id already in use, but a different name
  1138. //
  1139. BMOFFree(PropertyName);
  1140. Status = ERROR_FILE_NOT_FOUND;
  1141. goto done;
  1142. } else {
  1143. //
  1144. // This is a duplicate so just free up the
  1145. // memory used and decrement the total
  1146. // count of parameters in the list. The
  1147. // data obtained the last time should still
  1148. // be valid
  1149. //
  1150. ParamList->ParamCount--;
  1151. BMOFFree(PropertyName);
  1152. continue;
  1153. }
  1154. }
  1155. MethodParam->Name = PropertyName;
  1156. //
  1157. // Now figure out the data type for the parameter
  1158. // and the array status
  1159. //
  1160. if (MofPropertyData.m_dwType & VT_ARRAY)
  1161. {
  1162. MethodParam->Flags |= MOFDI_FLAG_ARRAY;
  1163. }
  1164. QualifierType = VT_BSTR;
  1165. Status = WmipFindMofQualifier(QualifierList,
  1166. L"CIMTYPE",
  1167. &QualifierType,
  1168. NULL,
  1169. (PVOID)&StringPtr);
  1170. if (Status == ERROR_SUCCESS)
  1171. {
  1172. MethodParam->DataType = StringPtr;
  1173. }
  1174. } else {
  1175. //
  1176. // Method ID qualifier is out of range
  1177. //
  1178. BMOFFree(QualifierList);
  1179. Status = ERROR_FILE_NOT_FOUND;
  1180. goto done;
  1181. }
  1182. } else {
  1183. //
  1184. // Check if this is the special ReturnValue parameter
  1185. // on the output parameter object. If so extract the
  1186. // return type, otherwise flag an error in the binary
  1187. // mof
  1188. //
  1189. if (_wcsicmp(L"ReturnValue", PropertyName) == 0)
  1190. {
  1191. QualifierType = VT_BSTR;
  1192. Status = WmipFindMofQualifier(QualifierList,
  1193. L"CIMTYPE",
  1194. &QualifierType,
  1195. NULL,
  1196. (PVOID)&StringPtr);
  1197. if (Status == ERROR_SUCCESS)
  1198. {
  1199. BMOFFree(ParamList->ReturnDataType);
  1200. ParamList->ReturnDataType = StringPtr;
  1201. }
  1202. } else {
  1203. Status = ERROR_FILE_NOT_FOUND;
  1204. goto done;
  1205. }
  1206. BMOFFree(PropertyName);
  1207. BMOFFree(QualifierList);
  1208. }
  1209. } else {
  1210. BMOFFree(PropertyName);
  1211. }
  1212. }
  1213. done:
  1214. return(Status);
  1215. }
  1216. ULONG ParseMethodParameterObjects(
  1217. IN CBMOFObj *InObject,
  1218. IN CBMOFObj *OutObject,
  1219. OUT PMETHODPARAMLIST *MethodParamList
  1220. )
  1221. /*++
  1222. Routine Description:
  1223. This routine will parse the in and out method parameter obejcts to create
  1224. a MOFCLASSINFO that describes the method call.
  1225. Arguments:
  1226. InObject is the object with the input parameters
  1227. OutObject is the object with the output parameters
  1228. *ClassInfo returns with the class info for the method call
  1229. Return Value:
  1230. ERROR_SUCCESS or a WMI Mof error code (see wmiump.h)
  1231. --*/
  1232. {
  1233. PMETHODPARAMLIST ParamList;
  1234. ULONG Status;
  1235. ULONG DataItemCount;
  1236. ULONG InItemCount, OutItemCount;
  1237. ULONG Size;
  1238. PMETHODPARAMETER MethodParameter;
  1239. PWCHAR StringPtr;
  1240. Status = ERROR_SUCCESS;
  1241. if (InObject != NULL)
  1242. {
  1243. ResetObj(InObject);
  1244. InItemCount = GetDataItemCount(InObject, L"Id");
  1245. } else {
  1246. InItemCount = 0;
  1247. }
  1248. if (OutObject != NULL)
  1249. {
  1250. ResetObj(OutObject);
  1251. OutItemCount = GetDataItemCount(OutObject, L"Id");
  1252. } else {
  1253. OutItemCount = 0;
  1254. }
  1255. DataItemCount = InItemCount + OutItemCount;
  1256. Size = sizeof(METHODPARAMLIST) + DataItemCount * sizeof(METHODPARAMETER);
  1257. ParamList = (PMETHODPARAMLIST)WmipAlloc(Size);
  1258. if (ParamList == NULL)
  1259. {
  1260. return(ERROR_NOT_ENOUGH_MEMORY);
  1261. }
  1262. //
  1263. // Get the essential information to fill in the parameter list
  1264. memset(ParamList, 0, Size);
  1265. ParamList->ParamCount = DataItemCount;
  1266. StringPtr = (PWCHAR)BMOFAlloc( sizeof(L"void") + sizeof(WCHAR) );
  1267. if (StringPtr != NULL)
  1268. {
  1269. wcscpy(StringPtr, L"void");
  1270. ParamList->ReturnDataType = StringPtr;
  1271. } else {
  1272. BMOFFree(ParamList);
  1273. return(ERROR_NOT_ENOUGH_MEMORY);
  1274. }
  1275. //
  1276. // Parse the input parameter class object
  1277. //
  1278. if (InObject != NULL)
  1279. {
  1280. Status = ParseMethodInOutObject(InObject,
  1281. ParamList,
  1282. DataItemCount);
  1283. } else {
  1284. Status = ERROR_SUCCESS;
  1285. }
  1286. if (Status == ERROR_SUCCESS)
  1287. {
  1288. if (OutObject != NULL)
  1289. {
  1290. //
  1291. // Parse the output parameter class object
  1292. //
  1293. Status = ParseMethodInOutObject(OutObject,
  1294. ParamList,
  1295. DataItemCount);
  1296. }
  1297. }
  1298. *MethodParamList = ParamList;
  1299. return(Status);
  1300. }
  1301. ULONG ParseMethodParameters(
  1302. CBMOFDataItem *MofMethodData,
  1303. PMETHODPARAMLIST *MethodParamList
  1304. )
  1305. {
  1306. ULONG Status = ERROR_SUCCESS;
  1307. CBMOFObj *InObject;
  1308. CBMOFObj *OutObject;
  1309. LONG i;
  1310. ULONG NumberDimensions;
  1311. ULONG NumberElements;
  1312. VARIANT InVar, OutVar;
  1313. DWORD SimpleType;
  1314. *MethodParamList = NULL;
  1315. SimpleType = MofMethodData->m_dwType & ~VT_ARRAY & ~VT_BYREF;
  1316. NumberDimensions = GetNumDimensions(MofMethodData);
  1317. if (NumberDimensions > 0)
  1318. {
  1319. NumberElements = GetNumElements(MofMethodData, 0);
  1320. WmipAssert(NumberDimensions == 1);
  1321. WmipAssert((NumberElements == 1) || (NumberElements == 2));
  1322. i = 0;
  1323. memset((void *)&InVar.lVal, 0, 8);
  1324. if (GetData(MofMethodData, (BYTE *)&(InVar.lVal), &i))
  1325. {
  1326. InObject = (CBMOFObj *)InVar.bstrVal;
  1327. InVar.vt = (VARTYPE)SimpleType;
  1328. WmipAssert(InVar.vt == VT_UNKNOWN);
  1329. if (NumberElements == 2)
  1330. {
  1331. i = 1;
  1332. memset((void *)&OutVar.lVal, 0, 8);
  1333. if (GetData(MofMethodData, (BYTE *)&(OutVar.lVal), &i))
  1334. {
  1335. OutVar.vt = (VARTYPE)SimpleType;
  1336. WmipAssert(OutVar.vt == VT_UNKNOWN);
  1337. OutObject = (CBMOFObj *)OutVar.bstrVal;
  1338. } else {
  1339. Status = ERROR_FILE_NOT_FOUND;
  1340. }
  1341. } else {
  1342. OutObject = NULL;
  1343. }
  1344. } else {
  1345. Status = ERROR_FILE_NOT_FOUND;
  1346. }
  1347. } else {
  1348. InObject = NULL;
  1349. OutObject = NULL;
  1350. }
  1351. if (Status == ERROR_SUCCESS)
  1352. {
  1353. Status = ParseMethodParameterObjects(InObject,
  1354. OutObject,
  1355. MethodParamList);
  1356. }
  1357. return(Status);
  1358. }
  1359. ULONG GenerateMethod(
  1360. PMOFFILETARGET MofFileTarget,
  1361. PWCHAR MethodName,
  1362. BOOLEAN IsInstance,
  1363. CBMOFQualList * QualifierList,
  1364. CBMOFDataItem *Method
  1365. )
  1366. {
  1367. ULONG Status;
  1368. PMETHODPARAMLIST MethodList;
  1369. ULONG i;
  1370. PWCHAR ArraySuffix;
  1371. PMETHODPARAMETER MethodParam;
  1372. Status = ParseMethodParameters(Method,
  1373. &MethodList);
  1374. if (Status == ERROR_SUCCESS)
  1375. {
  1376. Status = FilePrint(MofFileTarget,
  1377. L"%ws %ws( ",
  1378. GeneratePropertyName(MethodList->ReturnDataType),
  1379. MethodName);
  1380. if (Status == ERROR_SUCCESS)
  1381. {
  1382. for (i = 0;
  1383. ((Status == ERROR_SUCCESS) &&
  1384. (i < MethodList->ParamCount));
  1385. i++)
  1386. {
  1387. if (i != 0)
  1388. {
  1389. Status = FilePrint(MofFileTarget,
  1390. L"\r\n,");
  1391. }
  1392. if (Status == ERROR_SUCCESS)
  1393. {
  1394. MethodParam = &MethodList->Parameters[i];
  1395. Status = GenerateQualifierList(MofFileTarget,
  1396. MethodParam->QualifierList,
  1397. TRUE);
  1398. if (Status == ERROR_SUCCESS)
  1399. {
  1400. if (MethodParam->Flags & MOFDI_FLAG_ARRAY)
  1401. {
  1402. ArraySuffix = L"[]";
  1403. } else {
  1404. ArraySuffix = L"";
  1405. }
  1406. Status = FilePrint(MofFileTarget,
  1407. L"%ws %ws%ws",
  1408. GeneratePropertyName(MethodParam->DataType),
  1409. MethodParam->Name,
  1410. ArraySuffix);
  1411. }
  1412. }
  1413. }
  1414. }
  1415. if (Status == ERROR_SUCCESS)
  1416. {
  1417. Status = FilePrint(MofFileTarget,
  1418. L");\r\n");
  1419. }
  1420. }
  1421. //
  1422. // Free all memory used to build method parameter list
  1423. //
  1424. if (MethodList != NULL)
  1425. {
  1426. for (i = 0; i < MethodList->ParamCount; i++)
  1427. {
  1428. MethodParam = &MethodList->Parameters[i];
  1429. if (MethodParam->QualifierList != NULL)
  1430. {
  1431. BMOFFree(MethodParam->QualifierList);
  1432. }
  1433. if (MethodParam->Name != NULL)
  1434. {
  1435. BMOFFree(MethodParam->Name);
  1436. }
  1437. if (MethodParam->DataType != NULL)
  1438. {
  1439. BMOFFree(MethodParam->DataType);
  1440. }
  1441. }
  1442. if (MethodList->ReturnDataType != NULL)
  1443. {
  1444. BMOFFree(MethodList->ReturnDataType);
  1445. }
  1446. WmipFree(MethodList);
  1447. }
  1448. return(Status);
  1449. }
  1450. ULONG GenerateMofForObj(
  1451. PMOFFILETARGET MofFileTarget,
  1452. CBMOFObj *Obj
  1453. )
  1454. {
  1455. CBMOFQualList * QualifierList;
  1456. CBMOFDataItem Property, Method;
  1457. WCHAR *Name = NULL;
  1458. ULONG Status;
  1459. BOOLEAN IsInstance;
  1460. DWORD ObjType;
  1461. PWCHAR Text;
  1462. CBMOFDataItem MofPropertyData;
  1463. PWCHAR SuperClass, Separator;
  1464. PWCHAR EmptyString = L"";
  1465. ULONG DataType;
  1466. PWCHAR Alias, AliasSeparator;
  1467. //
  1468. // First display the class qualifier list
  1469. //
  1470. QualifierList = GetQualList(Obj);
  1471. if(QualifierList != NULL)
  1472. {
  1473. Status = GenerateQualifierList(MofFileTarget,
  1474. QualifierList,
  1475. FALSE);
  1476. BMOFFree(QualifierList);
  1477. if (Status != ERROR_SUCCESS)
  1478. {
  1479. return(Status);
  1480. }
  1481. }
  1482. //
  1483. // Now determine if this is a class or instance and display the class name
  1484. //
  1485. ObjType = GetType(Obj);
  1486. switch (ObjType)
  1487. {
  1488. case MofObjectTypeClass:
  1489. {
  1490. IsInstance = FALSE;
  1491. Text = L"class";
  1492. break;
  1493. }
  1494. case MofObjectTypeInstance:
  1495. {
  1496. IsInstance = TRUE;
  1497. Text = L"instance of";
  1498. break;
  1499. }
  1500. default:
  1501. {
  1502. WmipDebugPrint(("BMOFLocParser: Unknown class object type 0x%x\n",
  1503. ObjType));
  1504. WmipAssert(FALSE);
  1505. return(ERROR_INVALID_PARAMETER);
  1506. }
  1507. }
  1508. //
  1509. // See if there is a superclass, that is if this class was derrived
  1510. // from another
  1511. //
  1512. DataType = VT_BSTR;
  1513. Status = WmipFindProperty(Obj,
  1514. L"__SUPERCLASS",
  1515. &MofPropertyData,
  1516. &DataType,
  1517. (PVOID)&SuperClass);
  1518. switch (Status)
  1519. {
  1520. case ERROR_SUCCESS:
  1521. {
  1522. //
  1523. // This class is derrived from another
  1524. //
  1525. Separator = L":";
  1526. break;
  1527. }
  1528. case ERROR_FILE_NOT_FOUND:
  1529. {
  1530. //
  1531. // This class is not derrived from another
  1532. //
  1533. SuperClass = EmptyString;
  1534. Separator = EmptyString;
  1535. break;
  1536. }
  1537. default:
  1538. {
  1539. //
  1540. // Something is wrong, return an error
  1541. //
  1542. return(Status);
  1543. }
  1544. }
  1545. //
  1546. // See if there is an alias defined for this class
  1547. //
  1548. DataType = VT_BSTR;
  1549. Status = WmipFindProperty(Obj,
  1550. L"__ALIAS",
  1551. &MofPropertyData,
  1552. &DataType,
  1553. (PVOID)&Alias);
  1554. switch (Status)
  1555. {
  1556. case ERROR_SUCCESS:
  1557. {
  1558. //
  1559. // This class is derrived from another
  1560. //
  1561. AliasSeparator = L" as $";
  1562. break;
  1563. }
  1564. case ERROR_FILE_NOT_FOUND:
  1565. {
  1566. //
  1567. // This class is not derrived from another
  1568. //
  1569. Alias = EmptyString;
  1570. AliasSeparator = EmptyString;
  1571. break;
  1572. }
  1573. default:
  1574. {
  1575. //
  1576. // Something is wrong, return an error
  1577. //
  1578. return(Status);
  1579. }
  1580. }
  1581. if (GetName(Obj, &Name))
  1582. {
  1583. WmipDebugPrint(("BmofLocParser: Parsing -> %ws %ws %ws %ws\n",
  1584. Text,
  1585. Name,
  1586. Separator,
  1587. SuperClass));
  1588. Status = FilePrint(MofFileTarget,
  1589. L"%ws %ws %ws %ws%ws%ws\r\n{\r\n",
  1590. Text,
  1591. Name,
  1592. Separator,
  1593. SuperClass,
  1594. AliasSeparator,
  1595. Alias);
  1596. BMOFFree(Name);
  1597. } else {
  1598. Status = ERROR_INVALID_PARAMETER;
  1599. }
  1600. if (SuperClass != EmptyString)
  1601. {
  1602. BMOFFree(SuperClass);
  1603. }
  1604. //
  1605. // Now generate each property and its qualifiers
  1606. //
  1607. ResetObj(Obj);
  1608. while ((Status == ERROR_SUCCESS) && (NextProp(Obj, &Name, &Property)))
  1609. {
  1610. //
  1611. // Ignore any system property, that is, all those that begin
  1612. // with __
  1613. //
  1614. if ( (Name[0] == L'_') && (Name[1] == L'_') )
  1615. {
  1616. WmipDebugPrint(("BmofLocParser: Skipping system property %ws\n",
  1617. Name));
  1618. BMOFFree(Name);
  1619. continue;
  1620. }
  1621. QualifierList = GetPropQualList(Obj, Name);
  1622. if (QualifierList != NULL)
  1623. {
  1624. Status = GenerateQualifierList(MofFileTarget,
  1625. QualifierList,
  1626. FALSE);
  1627. }
  1628. if (Status == ERROR_SUCCESS)
  1629. {
  1630. WmipDebugPrint(("BmofLocParser: Parsing property %ws\n",
  1631. Name));
  1632. Status = GenerateProperty(MofFileTarget,
  1633. Name,
  1634. IsInstance,
  1635. QualifierList,
  1636. &Property);
  1637. }
  1638. if (QualifierList != NULL)
  1639. {
  1640. BMOFFree(QualifierList);
  1641. }
  1642. BMOFFree(Name);
  1643. }
  1644. //
  1645. // Next we generate all of the methods and their qualifiers
  1646. //
  1647. while ((Status == ERROR_SUCCESS) && (NextMeth(Obj, &Name, &Method)))
  1648. {
  1649. QualifierList = GetMethQualList(Obj, Name);
  1650. if (QualifierList != NULL)
  1651. {
  1652. Status = GenerateQualifierList(MofFileTarget,
  1653. QualifierList,
  1654. FALSE);
  1655. }
  1656. if (Status == ERROR_SUCCESS)
  1657. {
  1658. WmipDebugPrint(("BmofLocParser: Parsing method %ws\n",
  1659. Name));
  1660. Status = GenerateMethod(MofFileTarget,
  1661. Name,
  1662. IsInstance,
  1663. QualifierList,
  1664. &Method);
  1665. }
  1666. if (QualifierList != NULL)
  1667. {
  1668. BMOFFree(QualifierList);
  1669. }
  1670. BMOFFree(Name);
  1671. }
  1672. if (Status == ERROR_SUCCESS)
  1673. {
  1674. //
  1675. // Closing brace for class definition
  1676. //
  1677. Status = FilePrint(MofFileTarget,
  1678. L"};\r\n\r\n");
  1679. }
  1680. return(Status);
  1681. }
  1682. PWCHAR MakeClassInstanceFlagsText(
  1683. PWCHAR ClassFlagsText,
  1684. ULONG ClassFlags
  1685. )
  1686. {
  1687. PWCHAR CommaText;
  1688. //
  1689. // TODO: FInd any undocumented flags
  1690. //
  1691. CommaText = L"";
  1692. *ClassFlagsText = 0;
  1693. if (ClassFlags & 1)
  1694. {
  1695. //
  1696. // since this is the first if, we can assume that a , would
  1697. // never be needed
  1698. //
  1699. wcscat(ClassFlagsText, L"\"updateonly\"");
  1700. CommaText = L",";
  1701. }
  1702. if (ClassFlags & 2)
  1703. {
  1704. wcscat(ClassFlagsText, CommaText);
  1705. wcscat(ClassFlagsText, L"\"createonly\"");
  1706. CommaText = L",";
  1707. }
  1708. if (ClassFlags & 32)
  1709. {
  1710. wcscat(ClassFlagsText, CommaText);
  1711. wcscat(ClassFlagsText, L"\"safeupdate\"");
  1712. CommaText = L",";
  1713. }
  1714. if (ClassFlags & 64)
  1715. {
  1716. wcscat(ClassFlagsText, CommaText);
  1717. wcscat(ClassFlagsText, L"\"forceupdate\"");
  1718. CommaText = L",";
  1719. }
  1720. WmipAssert(*ClassFlagsText != 0);
  1721. return(ClassFlagsText);
  1722. }
  1723. ULONG WatchClassInstanceFlags(
  1724. PMOFFILETARGET MofFileTarget,
  1725. CBMOFObj *Obj,
  1726. PWCHAR ClassName,
  1727. PWCHAR PragmaName,
  1728. LONG *Flags
  1729. )
  1730. {
  1731. ULONG Status;
  1732. LONG NewFlags;
  1733. WCHAR FlagsText[MAX_PATH];
  1734. ULONG DataType;
  1735. CBMOFDataItem Property;
  1736. DataType = VT_I4;
  1737. Status = WmipFindProperty(Obj,
  1738. ClassName,
  1739. &Property,
  1740. &DataType,
  1741. &NewFlags);
  1742. if (Status == ERROR_SUCCESS)
  1743. {
  1744. if (*Flags != NewFlags)
  1745. {
  1746. //
  1747. // Flags have just appeared or
  1748. // changed so spit out a #pragma
  1749. //
  1750. WmipDebugPrint(("BmofLocParser: %ws changed to %ws\n",
  1751. PragmaName,
  1752. MakeClassInstanceFlagsText(FlagsText,
  1753. NewFlags)));
  1754. Status = FilePrint(MofFileTarget,
  1755. L"\r\n#pragma %ws(%ws)\r\n\r\n",
  1756. PragmaName,
  1757. MakeClassInstanceFlagsText(FlagsText,
  1758. NewFlags));
  1759. *Flags = NewFlags;
  1760. }
  1761. } else if (Status == ERROR_FILE_NOT_FOUND) {
  1762. Status = ERROR_SUCCESS;
  1763. }
  1764. return(Status);
  1765. }
  1766. ULONG WatchForEnglishMof(
  1767. PMOFFILETARGET MofFileTarget,
  1768. PWCHAR Namespace,
  1769. ULONG ClassFlags,
  1770. CBMOFObj *Obj
  1771. )
  1772. {
  1773. WCHAR *Name = NULL;
  1774. WCHAR *NamespaceName = NULL;
  1775. ULONG DataType;
  1776. CBMOFDataItem MofPropertyData;
  1777. ULONG Status;
  1778. WCHAR s[MAX_PATH];
  1779. //
  1780. // We are looking for an instance of __namespace
  1781. //
  1782. if (GetName(Obj, &Name))
  1783. {
  1784. if ( (GetType(Obj) == MofObjectTypeInstance) &&
  1785. (_wcsicmp(Name, L"__namespace") == 0) )
  1786. {
  1787. //
  1788. // Now if we are dropping down to a namespace that ends in
  1789. // ms_409 then that means we have an english amendment and
  1790. // want to make a copy of it. Otherwise we want to stop
  1791. // making copies. We determine the namespace we are
  1792. // creating by looking at the value of the name property.
  1793. //
  1794. DataType = VT_BSTR;
  1795. Status = WmipFindProperty(Obj,
  1796. L"name",
  1797. &MofPropertyData,
  1798. &DataType,
  1799. (PVOID)&NamespaceName);
  1800. if (Status == ERROR_SUCCESS)
  1801. {
  1802. if (_wcsicmp(NamespaceName, L"ms_409") == 0)
  1803. {
  1804. //
  1805. // moving to the english locale, so start writing
  1806. // english
  1807. //
  1808. MofFileTarget->WriteToEnglish = TRUE;
  1809. Status = FilePrintToHandle(MofFileTarget->EnglishMofHandle,
  1810. L"\r\n\r\n"
  1811. L"#pragma classflags(%d)\r\n"
  1812. L"#pragma namespace(\"%ws\")\r\n",
  1813. ClassFlags,
  1814. AddSlashesToString(s, Namespace));
  1815. } else {
  1816. //
  1817. // moving to a different locale, so stop writing
  1818. // english
  1819. //
  1820. MofFileTarget->WriteToEnglish = FALSE;
  1821. }
  1822. BMOFFree(NamespaceName);
  1823. } else if (Status == ERROR_FILE_NOT_FOUND) {
  1824. //
  1825. // Did not find the property we wanted. Not a good
  1826. // thing, but not fatal.
  1827. //
  1828. Status = ERROR_SUCCESS;
  1829. }
  1830. } else {
  1831. Status = ERROR_SUCCESS;
  1832. }
  1833. BMOFFree(Name);
  1834. } else {
  1835. Status = ERROR_SUCCESS;
  1836. }
  1837. return(Status);
  1838. }
  1839. BOOLEAN ConvertBmfToMof(
  1840. PUCHAR BinaryMofData,
  1841. TCHAR *MofFile,
  1842. TCHAR *EnglishMofFile
  1843. )
  1844. {
  1845. HANDLE FileHandle;
  1846. ULONG Status;
  1847. CBMOFObjList *ObjList;
  1848. CBMOFObj *Obj;
  1849. PUCHAR UncompressedBmof;
  1850. ULONG UncompressedBmofSize;
  1851. WCHAR Namespace[MAX_PATH];
  1852. PWCHAR NewNamespace;
  1853. ULONG DataType;
  1854. CBMOFDataItem Property;
  1855. LONG ClassFlags, InstanceFlags;
  1856. WCHAR w;
  1857. MOFFILETARGET MofFileTarget;
  1858. //
  1859. // First thing is to try to create the output files in which we will
  1860. // generate the unicode MOF text
  1861. //
  1862. FileHandle = CreateFile(MofFile,
  1863. GENERIC_READ | GENERIC_WRITE,
  1864. 0,
  1865. NULL,
  1866. CREATE_ALWAYS,
  1867. FILE_ATTRIBUTE_NORMAL,
  1868. NULL);
  1869. if (FileHandle != INVALID_HANDLE_VALUE)
  1870. {
  1871. //
  1872. // Now open english mof file
  1873. //
  1874. if (*EnglishMofFile != 0)
  1875. {
  1876. MofFileTarget.EnglishMofHandle = CreateFile(EnglishMofFile,
  1877. GENERIC_READ | GENERIC_WRITE,
  1878. 0,
  1879. NULL,
  1880. CREATE_ALWAYS,
  1881. FILE_ATTRIBUTE_NORMAL,
  1882. NULL);
  1883. } else {
  1884. MofFileTarget.EnglishMofHandle = NULL;
  1885. }
  1886. if (MofFileTarget.EnglishMofHandle != INVALID_HANDLE_VALUE)
  1887. {
  1888. //
  1889. // Initialize the mof file target information
  1890. //
  1891. MofFileTarget.MofHandle = FileHandle;
  1892. MofFileTarget.WriteToEnglish = FALSE;
  1893. //
  1894. // Write magic header that signifies that this is a unicode
  1895. // file
  1896. //
  1897. w = 0xfeff;
  1898. Status = FilePrintToHandle(FileHandle,
  1899. L"%wc",
  1900. w);
  1901. if (Status == ERROR_SUCCESS)
  1902. {
  1903. //
  1904. // Uncompress the binary mof data so that we can work with it
  1905. //
  1906. Status = WmipDecompressBuffer(BinaryMofData,
  1907. &UncompressedBmof,
  1908. &UncompressedBmofSize);
  1909. if (Status == ERROR_SUCCESS)
  1910. {
  1911. WmipDebugPrint(("BmofLocParser: %s uncompressed to %d bytes\n",
  1912. MofFile, UncompressedBmofSize));
  1913. WmipAssert(UncompressedBmof != NULL);
  1914. MofFileTarget.UncompressedBlob = UncompressedBmof;
  1915. //
  1916. // We start in the root\default namespace by default
  1917. //
  1918. wcscpy(Namespace, L"root\\default");
  1919. ClassFlags = 0;
  1920. InstanceFlags = 0;
  1921. //
  1922. // Create the binary mof object list and related structures
  1923. // so that we can later enumerate over them and
  1924. // reconstitute them back into unicode text
  1925. //
  1926. ObjList = CreateObjList(UncompressedBmof);
  1927. if(ObjList != NULL)
  1928. {
  1929. ResetObjList(ObjList);
  1930. while ((Obj = NextObj(ObjList)) &&
  1931. (Status == ERROR_SUCCESS))
  1932. {
  1933. //
  1934. // Watch for a new namespace instance and
  1935. // see if we are create an instance for
  1936. // "\\\\.\\root\\wmi\\ms_409". If so then
  1937. // turn on writing to the english mof,
  1938. // otherwise turn it off
  1939. //
  1940. if (MofFileTarget.EnglishMofHandle != NULL)
  1941. {
  1942. Status = WatchForEnglishMof(&MofFileTarget,
  1943. Namespace,
  1944. ClassFlags,
  1945. Obj);
  1946. }
  1947. if (Status == ERROR_SUCCESS)
  1948. {
  1949. //
  1950. // Watch for change in namespace and if so then
  1951. // spit out a #pragma namespace to track it
  1952. //
  1953. DataType = VT_BSTR;
  1954. Status = WmipFindProperty(Obj,
  1955. L"__NAMESPACE",
  1956. &Property,
  1957. &DataType,
  1958. (PVOID)&NewNamespace);
  1959. }
  1960. if (Status == ERROR_SUCCESS)
  1961. {
  1962. if (_wcsicmp(Namespace, NewNamespace) != 0)
  1963. {
  1964. //
  1965. // Namespace has changed, spit out a
  1966. // #pragma
  1967. //
  1968. WmipDebugPrint(("BmofLocParser: Switching from namespace %ws to %ws\n",
  1969. Namespace, NewNamespace));
  1970. Status = FilePrint(&MofFileTarget,
  1971. L"\r\n#pragma namespace(\"%ws\")\r\n\r\n",
  1972. AddSlashesToString(Namespace, NewNamespace));
  1973. wcscpy(Namespace, NewNamespace);
  1974. }
  1975. BMOFFree(NewNamespace);
  1976. } else if (Status == ERROR_FILE_NOT_FOUND) {
  1977. Status = ERROR_SUCCESS;
  1978. }
  1979. //
  1980. // Watch for change in classflags
  1981. //
  1982. if (Status == ERROR_SUCCESS)
  1983. {
  1984. Status = WatchClassInstanceFlags(&MofFileTarget,
  1985. Obj,
  1986. L"__ClassFlags",
  1987. L"Classflags",
  1988. &ClassFlags);
  1989. }
  1990. //
  1991. // Watch for change in instance flags
  1992. //
  1993. if (Status == ERROR_SUCCESS)
  1994. {
  1995. Status = WatchClassInstanceFlags(&MofFileTarget,
  1996. Obj,
  1997. L"__InstanceFlags",
  1998. L"Instanceflags",
  1999. &InstanceFlags);
  2000. }
  2001. //
  2002. // Generate mof for this object
  2003. //
  2004. if (Status == ERROR_SUCCESS)
  2005. {
  2006. Status = GenerateMofForObj(&MofFileTarget,
  2007. Obj);
  2008. }
  2009. BMOFFree(Obj);
  2010. }
  2011. BMOFFree(ObjList);
  2012. } else {
  2013. // TODO: LocStudio message
  2014. Status = ERROR_INVALID_PARAMETER;
  2015. }
  2016. WmipFree(UncompressedBmof);
  2017. }
  2018. }
  2019. CloseHandle(FileHandle);
  2020. if (MofFileTarget.EnglishMofHandle != NULL)
  2021. {
  2022. CloseHandle(MofFileTarget.EnglishMofHandle);
  2023. }
  2024. if (Status != ERROR_SUCCESS)
  2025. {
  2026. //
  2027. // There was some error generating the MOF text and we are
  2028. // going to return a failure. Make sure to clean up any
  2029. // temporary file created
  2030. //
  2031. WmipDebugPrint(("BmofLocParser: BMF parsing returns error %d\n",
  2032. Status));
  2033. #if 0
  2034. DebugBreak();
  2035. #endif
  2036. DeleteFile(MofFile);
  2037. DeleteFile(EnglishMofFile);
  2038. }
  2039. } else {
  2040. CloseHandle(FileHandle);
  2041. DeleteFile(MofFile);
  2042. Status = GetLastError();
  2043. }
  2044. } else {
  2045. Status = GetLastError();
  2046. }
  2047. return((Status == ERROR_SUCCESS) ? TRUE : FALSE);
  2048. }