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.

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