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.

2945 lines
71 KiB

  1. /*++
  2. Copyright (c) 1995-2000 Microsoft Corporation
  3. Module Name:
  4. dnsc_wmi.c
  5. Abstract:
  6. WMI functions for DNSCMD
  7. Author:
  8. Jeff Westhead (jwesth) November 2000
  9. Revision History:
  10. --*/
  11. #include "dnsclip.h"
  12. #include "dnsc_wmi.h"
  13. #define DNSCMD_CHECK_WMI_ENABLED() \
  14. if ( !g_UseWmi ) \
  15. { \
  16. ASSERT( g_UseWmi ); \
  17. printf( "Internal error: WMI is not enabled!\n" ); \
  18. return ERROR_NOT_SUPPORTED; \
  19. }
  20. #define HRES_TO_STATUS( hres ) ( hres )
  21. #define DNS_WMI_NAMESPACE L"ROOT\\MicrosoftDNS"
  22. #define DNS_WMI_RELPATH L"__RELPATH"
  23. #define DNS_WMI_TIMEOUT 20000 // timeout in msecs
  24. #define DNS_WMI_BLANK_STRING \
  25. L" "
  26. #define MYTEXT2(str) L##str
  27. #define MYTEXT(str) MYTEXT2(str)
  28. #define wmiRelease( pWmiObject ) \
  29. if ( pWmiObject ) \
  30. { \
  31. pWmiObject->Release(); \
  32. pWmiObject = NULL; \
  33. }
  34. //
  35. // Globals
  36. //
  37. IWbemServices * g_pIWbemServices = NULL;
  38. //
  39. // Static functions
  40. //
  41. static DNS_STATUS
  42. getEnumerator(
  43. IN PSTR pszZoneName,
  44. OUT IEnumWbemClassObject ** ppEnum
  45. )
  46. /*++
  47. Routine Description:
  48. Retrieves WMI object enumerator. The caller must call Release on
  49. the enum object when done.
  50. Arguments:
  51. pszZoneName - zone name or NULL for server object
  52. ppEnum - ptr to ptr to WMI enumerator
  53. Return Value:
  54. ERROR_SUCCESS if successful or error code on failure.
  55. --*/
  56. {
  57. DNS_STATUS status = ERROR_SUCCESS;
  58. WCHAR wsz[ 1024 ];
  59. BSTR bstrWQL = NULL;
  60. BSTR bstrQuery = NULL;
  61. HRESULT hres = 0;
  62. if ( pszZoneName )
  63. {
  64. wsprintfW(
  65. wsz,
  66. L"select * from MicrosoftDNS_Zone where Name='%S'",
  67. pszZoneName );
  68. }
  69. else
  70. {
  71. wsprintfW(
  72. wsz,
  73. L"select * from MicrosoftDNS_Server" );
  74. }
  75. bstrWQL = SysAllocString( L"WQL" );
  76. bstrQuery = SysAllocString( wsz );
  77. if ( !bstrWQL || !bstrQuery )
  78. {
  79. status = DNS_ERROR_NO_MEMORY;
  80. goto Done;
  81. }
  82. hres = g_pIWbemServices->ExecQuery(
  83. bstrWQL,
  84. bstrQuery,
  85. WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
  86. NULL,
  87. ppEnum );
  88. if ( FAILED( hres ) )
  89. {
  90. status = hres;
  91. goto Done;
  92. }
  93. Done:
  94. SysFreeString( bstrWQL );
  95. SysFreeString( bstrQuery );
  96. return status;
  97. } // getEnumerator
  98. static DNS_STATUS
  99. getRelpath(
  100. IN IWbemClassObject * pObj,
  101. OUT VARIANT * pVar
  102. )
  103. /*++
  104. Routine Description:
  105. Loads a VARIANT with the WMI __RELPATH of the object.
  106. Arguments:
  107. pObj - object to retrieve relpath for
  108. pVar - ptr to variant - caller must VariantClear() it later
  109. Return Value:
  110. ERROR_SUCCESS if successful or error code on failure.
  111. --*/
  112. {
  113. DNS_STATUS status = ERROR_SUCCESS;
  114. if ( pObj == NULL || pVar == NULL )
  115. {
  116. status = ERROR_INVALID_PARAMETER;
  117. }
  118. else
  119. {
  120. VariantClear( pVar );
  121. HRESULT hres = pObj->Get( DNS_WMI_RELPATH, 0, pVar, NULL, NULL );
  122. status = hres;
  123. }
  124. return status;
  125. } // getRelpath
  126. static DNS_STATUS
  127. getNextObjectInEnum(
  128. IN IEnumWbemClassObject * pEnum,
  129. OUT IWbemClassObject ** ppObj,
  130. IN bool fPrintRelpath = TRUE
  131. )
  132. /*++
  133. Routine Description:
  134. Retrieves WMI object enumerator. The caller must call Release
  135. on the class object.
  136. When there are no more objects to enumerate this function will
  137. return a NULL pObj and ERROR_SUCCESS.
  138. Arguments:
  139. pszZoneName - zone name or NULL for server object
  140. ppEnum - ptr to ptr to WMI enumerator
  141. Return Value:
  142. ERROR_SUCCESS if successful or error code on failure.
  143. --*/
  144. {
  145. DNS_STATUS status = ERROR_SUCCESS;
  146. ULONG returnedCount = 0;
  147. HRESULT hres = 0;
  148. if ( !pEnum || !ppObj )
  149. {
  150. status = ERROR_INVALID_PARAMETER;
  151. goto Done;
  152. }
  153. hres = pEnum->Next(
  154. DNS_WMI_TIMEOUT,
  155. 1, // requested instance count
  156. ppObj,
  157. &returnedCount );
  158. if ( hres == WBEM_S_FALSE )
  159. {
  160. status = ERROR_SUCCESS;
  161. *ppObj = NULL;
  162. }
  163. if ( *ppObj && fPrintRelpath )
  164. {
  165. //
  166. // Print RELPATH for this object.
  167. //
  168. VARIANT var;
  169. status = getRelpath( *ppObj, &var );
  170. if ( status == ERROR_SUCCESS )
  171. {
  172. printf( "%S\n", V_BSTR( &var ) );
  173. }
  174. else
  175. {
  176. printf( "WMI error 0x%08X getting RELPATH\n", hres );
  177. }
  178. VariantClear( &var );
  179. }
  180. Done:
  181. return status;
  182. } // getNextObjectInEnum
  183. static SAFEARRAY *
  184. createSafeArrayForIpList(
  185. IN DWORD dwIpCount,
  186. IN PIP_ADDRESS pIpList
  187. )
  188. /*++
  189. Routine Description:
  190. Creates a SAFEARRAY of strings representing a list of IP addresses.
  191. Arguments:
  192. pIpList - array of IP address DWORDs
  193. dwIpCount - number of elements in pIpList
  194. Return Value:
  195. ERROR_SUCCESS if successful or error code on failure.
  196. --*/
  197. {
  198. if ( !pIpList )
  199. {
  200. return NULL;
  201. }
  202. SAFEARRAYBOUND sabound = { dwIpCount, 0 };
  203. SAFEARRAY * psa = SafeArrayCreate( VT_BSTR, 1, &sabound );
  204. for ( ULONG i = 0; i < dwIpCount; ++i )
  205. {
  206. PWSTR pwsz = ( PWSTR ) Dns_NameCopyAllocate(
  207. inet_ntoa(
  208. *( struct in_addr * )
  209. &pIpList[ i ] ),
  210. 0,
  211. DnsCharSetUtf8,
  212. DnsCharSetUnicode );
  213. BSTR bstr = SysAllocString( pwsz );
  214. SafeArrayPutElement(
  215. psa,
  216. ( PLONG ) &i,
  217. bstr );
  218. SysFreeString( bstr );
  219. FREE_HEAP( pwsz );
  220. }
  221. return psa;
  222. }
  223. static SAFEARRAY *
  224. createSafeArrayForIpArray(
  225. IN PIP_ARRAY pIpArray
  226. )
  227. /*++
  228. Routine Description:
  229. Creates a SAFEARRAY of strings representing the IP addresses
  230. in pIpArray.
  231. Arguments:
  232. pIpArray - IP array to create string SAFEARRAY for
  233. Return Value:
  234. ERROR_SUCCESS if successful or error code on failure.
  235. --*/
  236. {
  237. if ( !pIpArray )
  238. {
  239. return NULL;
  240. }
  241. return createSafeArrayForIpList(
  242. pIpArray->AddrCount,
  243. pIpArray->AddrArray );
  244. }
  245. PWCHAR
  246. valueToString(
  247. CIMTYPE dwType,
  248. VARIANT *pValue,
  249. WCHAR **pbuf )
  250. /*++
  251. Routine Description:
  252. Convert VARIANT to string. Stole this code from WMI\Samples\VC\UtilLib.
  253. Arguments:
  254. dwType - value CIMTYPE
  255. pValue - value to convert to string
  256. **pbuf - ptr to allocated string buffer - caller must free() it
  257. Return Value:
  258. ERROR_SUCCESS if successful or error code on failure.
  259. --*/
  260. {
  261. #define BLOCKSIZE ( 32 * sizeof( WCHAR ) )
  262. #define CVTBUFSIZE ( 309 + 40 )
  263. DWORD iTotBufSize, iLen;
  264. WCHAR *vbuf = NULL;
  265. WCHAR *buf = NULL;
  266. WCHAR lbuf[BLOCKSIZE];
  267. switch (pValue->vt)
  268. {
  269. case VT_EMPTY:
  270. buf = (WCHAR *)malloc(BLOCKSIZE);
  271. if ( !buf ) goto AllocFailed;
  272. wcscpy(buf, L"<empty>");
  273. break;
  274. case VT_NULL:
  275. buf = (WCHAR *)malloc(BLOCKSIZE);
  276. if ( !buf ) goto AllocFailed;
  277. wcscpy(buf, L"<null>");
  278. break;
  279. case VT_BOOL:
  280. {
  281. VARIANT_BOOL b = pValue->boolVal;
  282. buf = (WCHAR *)malloc(BLOCKSIZE);
  283. if ( !buf ) goto AllocFailed;
  284. if (!b) {
  285. wcscpy(buf, L"FALSE");
  286. } else {
  287. wcscpy(buf, L"TRUE");
  288. }
  289. break;
  290. }
  291. case VT_I1:
  292. {
  293. char b = pValue->bVal;
  294. buf = (WCHAR *)malloc(BLOCKSIZE);
  295. if ( !buf ) goto AllocFailed;
  296. if (b >= 32) {
  297. swprintf(buf, L"'%c' (%hd, 0x%hX)", b, (signed char)b, b);
  298. } else {
  299. swprintf(buf, L"%hd (0x%hX)", (signed char)b, b);
  300. }
  301. break;
  302. }
  303. case VT_UI1:
  304. {
  305. unsigned char b = pValue->bVal;
  306. buf = (WCHAR *)malloc(BLOCKSIZE);
  307. if ( !buf ) goto AllocFailed;
  308. if (b >= 32) {
  309. swprintf(buf, L"'%c' (%hu, 0x%hX)", b, (unsigned char)b, b);
  310. } else {
  311. swprintf(buf, L"%hu (0x%hX)", (unsigned char)b, b);
  312. }
  313. break;
  314. }
  315. case VT_I2:
  316. {
  317. SHORT i = pValue->iVal;
  318. buf = (WCHAR *)malloc(BLOCKSIZE);
  319. if ( !buf ) goto AllocFailed;
  320. swprintf(buf, L"%hd (0x%hX)", i, i);
  321. break;
  322. }
  323. case VT_UI2:
  324. {
  325. USHORT i = pValue->uiVal;
  326. buf = (WCHAR *)malloc(BLOCKSIZE);
  327. if ( !buf ) goto AllocFailed;
  328. swprintf(buf, L"%hu (0x%hX)", i, i);
  329. break;
  330. }
  331. case VT_I4:
  332. {
  333. LONG l = pValue->lVal;
  334. buf = (WCHAR *)malloc(BLOCKSIZE);
  335. if ( !buf ) goto AllocFailed;
  336. swprintf(buf, L"%d (0x%X)", l, l);
  337. break;
  338. }
  339. case VT_UI4:
  340. {
  341. ULONG l = pValue->ulVal;
  342. buf = (WCHAR *)malloc(BLOCKSIZE);
  343. if ( !buf ) goto AllocFailed;
  344. swprintf(buf, L"%u (0x%X)", l, l);
  345. break;
  346. }
  347. case VT_R4:
  348. {
  349. float f = pValue->fltVal;
  350. buf = (WCHAR *)malloc(CVTBUFSIZE * sizeof(WCHAR));
  351. if ( !buf ) goto AllocFailed;
  352. swprintf(buf, L"%10.4f", f);
  353. break;
  354. }
  355. case VT_R8:
  356. {
  357. double d = pValue->dblVal;
  358. buf = (WCHAR *)malloc(CVTBUFSIZE * sizeof(WCHAR));
  359. if ( !buf ) goto AllocFailed;
  360. swprintf(buf, L"%10.4f", d);
  361. break;
  362. }
  363. case VT_BSTR:
  364. {
  365. if (dwType == CIM_SINT64)
  366. {
  367. // a little redundant, but it makes me feel better
  368. LPWSTR pWStr = pValue->bstrVal;
  369. __int64 l = _wtoi64(pWStr);
  370. buf = (WCHAR *)malloc(BLOCKSIZE);
  371. if ( !buf ) goto AllocFailed;
  372. swprintf(buf, L"%I64d", l, l);
  373. }
  374. else if (dwType == CIM_UINT64)
  375. {
  376. // a little redundant, but it makes me feel better
  377. LPWSTR pWStr = pValue->bstrVal;
  378. __int64 l = _wtoi64(pWStr);
  379. buf = (WCHAR *)malloc(BLOCKSIZE);
  380. if ( !buf ) goto AllocFailed;
  381. swprintf(buf, L"%I64u", l, l);
  382. }
  383. else // string, datetime, reference
  384. {
  385. LPWSTR pWStr = pValue->bstrVal;
  386. buf = (WCHAR *)malloc((wcslen(pWStr) * sizeof(WCHAR)) + sizeof(WCHAR) + (2 * sizeof(WCHAR)));
  387. if ( !buf ) goto AllocFailed;
  388. swprintf(buf, L"%wS", pWStr);
  389. }
  390. break;
  391. }
  392. case VT_BOOL|VT_ARRAY:
  393. {
  394. SAFEARRAY *pVec = pValue->parray;
  395. long iLBound, iUBound;
  396. BOOL bFirst = TRUE;
  397. SafeArrayGetLBound(pVec, 1, &iLBound);
  398. SafeArrayGetUBound(pVec, 1, &iUBound);
  399. if ((iUBound - iLBound + 1) == 0) {
  400. buf = (WCHAR *)malloc(BLOCKSIZE);
  401. if ( !buf ) goto AllocFailed;
  402. wcscpy(buf, L"<empty array>");
  403. break;
  404. }
  405. buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
  406. if ( !buf ) goto AllocFailed;
  407. wcscpy(buf, L"");
  408. for (long i = iLBound; i <= iUBound; i++) {
  409. if (!bFirst) {
  410. wcscat(buf, L",");
  411. } else {
  412. bFirst = FALSE;
  413. }
  414. VARIANT_BOOL v;
  415. SafeArrayGetElement(pVec, &i, &v);
  416. if (v) {
  417. wcscat(buf, L"TRUE");
  418. } else {
  419. wcscat(buf, L"FALSE");
  420. }
  421. }
  422. break;
  423. }
  424. case VT_I1|VT_ARRAY:
  425. {
  426. SAFEARRAY *pVec = pValue->parray;
  427. long iLBound, iUBound;
  428. BOOL bFirst = TRUE;
  429. SafeArrayGetLBound(pVec, 1, &iLBound);
  430. SafeArrayGetUBound(pVec, 1, &iUBound);
  431. if ((iUBound - iLBound + 1) == 0) {
  432. buf = (WCHAR *)malloc(BLOCKSIZE);
  433. if ( !buf ) goto AllocFailed;
  434. wcscpy(buf, L"<empty array>");
  435. break;
  436. }
  437. buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
  438. if ( !buf ) goto AllocFailed;
  439. wcscpy(buf, L"");
  440. WCHAR *pos = buf;
  441. DWORD len;
  442. BYTE *pbstr;
  443. SafeArrayAccessData(pVec, (void HUGEP* FAR*)&pbstr);
  444. for (long i = iLBound; i <= iUBound; i++) {
  445. if (!bFirst) {
  446. wcscpy(pos, L",");
  447. pos += 1;
  448. } else {
  449. bFirst = FALSE;
  450. }
  451. char v;
  452. // SafeArrayGetElement(pVec, &i, &v);
  453. v = pbstr[i];
  454. if (v < 32) {
  455. len = swprintf(lbuf, L"%hd (0x%X)", v, v);
  456. } else {
  457. len = swprintf(lbuf, L"'%c' %hd (0x%X)", v, v, v);
  458. }
  459. wcscpy(pos, lbuf);
  460. pos += len;
  461. }
  462. SafeArrayUnaccessData(pVec);
  463. break;
  464. }
  465. case VT_UI1|VT_ARRAY:
  466. {
  467. SAFEARRAY *pVec = pValue->parray;
  468. long iLBound, iUBound;
  469. BOOL bFirst = TRUE;
  470. SafeArrayGetLBound(pVec, 1, &iLBound);
  471. SafeArrayGetUBound(pVec, 1, &iUBound);
  472. if ((iUBound - iLBound + 1) == 0) {
  473. buf = (WCHAR *)malloc(BLOCKSIZE);
  474. if ( !buf ) goto AllocFailed;
  475. wcscpy(buf, L"<empty array>");
  476. break;
  477. }
  478. buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
  479. if ( !buf ) goto AllocFailed;
  480. wcscpy(buf, L"");
  481. WCHAR *pos = buf;
  482. DWORD len;
  483. BYTE *pbstr;
  484. SafeArrayAccessData(pVec, (void HUGEP* FAR*)&pbstr);
  485. for (long i = iLBound; i <= iUBound; i++) {
  486. if (!bFirst) {
  487. wcscpy(pos, L",");
  488. pos += 1;
  489. } else {
  490. bFirst = FALSE;
  491. }
  492. unsigned char v;
  493. // SafeArrayGetElement(pVec, &i, &v);
  494. v = pbstr[i];
  495. if (v < 32) {
  496. len = swprintf(lbuf, L"%hu (0x%X)", v, v);
  497. } else {
  498. len = swprintf(lbuf, L"'%c' %hu (0x%X)", v, v, v);
  499. }
  500. wcscpy(pos, lbuf);
  501. pos += len;
  502. }
  503. SafeArrayUnaccessData(pVec);
  504. break;
  505. }
  506. case VT_I2|VT_ARRAY:
  507. {
  508. SAFEARRAY *pVec = pValue->parray;
  509. long iLBound, iUBound;
  510. BOOL bFirst = TRUE;
  511. SafeArrayGetLBound(pVec, 1, &iLBound);
  512. SafeArrayGetUBound(pVec, 1, &iUBound);
  513. if ((iUBound - iLBound + 1) == 0) {
  514. buf = (WCHAR *)malloc(BLOCKSIZE);
  515. if ( !buf ) goto AllocFailed;
  516. wcscpy(buf, L"<empty array>");
  517. break;
  518. }
  519. buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
  520. if ( !buf ) goto AllocFailed;
  521. wcscpy(buf, L"");
  522. for (long i = iLBound; i <= iUBound; i++) {
  523. if (!bFirst) {
  524. wcscat(buf, L",");
  525. } else {
  526. bFirst = FALSE;
  527. }
  528. SHORT v;
  529. SafeArrayGetElement(pVec, &i, &v);
  530. swprintf(lbuf, L"%hd", v);
  531. wcscat(buf, lbuf);
  532. }
  533. break;
  534. }
  535. case VT_UI2|VT_ARRAY:
  536. {
  537. SAFEARRAY *pVec = pValue->parray;
  538. long iLBound, iUBound;
  539. BOOL bFirst = TRUE;
  540. SafeArrayGetLBound(pVec, 1, &iLBound);
  541. SafeArrayGetUBound(pVec, 1, &iUBound);
  542. if ((iUBound - iLBound + 1) == 0) {
  543. buf = (WCHAR *)malloc(BLOCKSIZE);
  544. if ( !buf ) goto AllocFailed;
  545. wcscpy(buf, L"<empty array>");
  546. break;
  547. }
  548. buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
  549. if ( !buf ) goto AllocFailed;
  550. wcscpy(buf, L"");
  551. for (long i = iLBound; i <= iUBound; i++) {
  552. if (!bFirst) {
  553. wcscat(buf, L",");
  554. } else {
  555. bFirst = FALSE;
  556. }
  557. USHORT v;
  558. SafeArrayGetElement(pVec, &i, &v);
  559. swprintf(lbuf, L"%hu", v);
  560. wcscat(buf, lbuf);
  561. }
  562. break;
  563. }
  564. case VT_I4|VT_ARRAY:
  565. {
  566. SAFEARRAY *pVec = pValue->parray;
  567. long iLBound, iUBound;
  568. BOOL bFirst = TRUE;
  569. SafeArrayGetLBound(pVec, 1, &iLBound);
  570. SafeArrayGetUBound(pVec, 1, &iUBound);
  571. if ((iUBound - iLBound + 1) == 0) {
  572. buf = (WCHAR *)malloc(BLOCKSIZE);
  573. if ( !buf ) goto AllocFailed;
  574. wcscpy(buf, L"<empty array>");
  575. break;
  576. }
  577. buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
  578. if ( !buf ) goto AllocFailed;
  579. wcscpy(buf, L"");
  580. for (long i = iLBound; i <= iUBound; i++) {
  581. if (!bFirst) {
  582. wcscat(buf, L",");
  583. } else {
  584. bFirst = FALSE;
  585. }
  586. LONG v;
  587. SafeArrayGetElement(pVec, &i, &v);
  588. _ltow(v, lbuf, 10);
  589. wcscat(buf, lbuf);
  590. }
  591. break;
  592. }
  593. case VT_UI4|VT_ARRAY:
  594. {
  595. SAFEARRAY *pVec = pValue->parray;
  596. long iLBound, iUBound;
  597. BOOL bFirst = TRUE;
  598. SafeArrayGetLBound(pVec, 1, &iLBound);
  599. SafeArrayGetUBound(pVec, 1, &iUBound);
  600. if ((iUBound - iLBound + 1) == 0) {
  601. buf = (WCHAR *)malloc(BLOCKSIZE);
  602. if ( !buf ) goto AllocFailed;
  603. wcscpy(buf, L"<empty array>");
  604. break;
  605. }
  606. buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
  607. if ( !buf ) goto AllocFailed;
  608. wcscpy(buf, L"");
  609. for (long i = iLBound; i <= iUBound; i++) {
  610. if (!bFirst) {
  611. wcscat(buf, L",");
  612. } else {
  613. bFirst = FALSE;
  614. }
  615. ULONG v;
  616. SafeArrayGetElement(pVec, &i, &v);
  617. _ultow(v, lbuf, 10);
  618. wcscat(buf, lbuf);
  619. }
  620. break;
  621. }
  622. case CIM_REAL32|VT_ARRAY:
  623. {
  624. SAFEARRAY *pVec = pValue->parray;
  625. long iLBound, iUBound;
  626. BOOL bFirst = TRUE;
  627. SafeArrayGetLBound(pVec, 1, &iLBound);
  628. SafeArrayGetUBound(pVec, 1, &iUBound);
  629. if ((iUBound - iLBound + 1) == 0) {
  630. buf = (WCHAR *)malloc(BLOCKSIZE);
  631. if ( !buf ) goto AllocFailed;
  632. wcscpy(buf, L"<empty array>");
  633. break;
  634. }
  635. buf = (WCHAR *)malloc((iUBound - iLBound + 1) * (CVTBUFSIZE * sizeof(WCHAR)));
  636. if ( !buf ) goto AllocFailed;
  637. wcscpy(buf, L"");
  638. for (long i = iLBound; i <= iUBound; i++) {
  639. if (!bFirst) {
  640. wcscat(buf, L",");
  641. } else {
  642. bFirst = FALSE;
  643. }
  644. FLOAT v;
  645. SafeArrayGetElement(pVec, &i, &v);
  646. swprintf(lbuf, L"%10.4f", v);
  647. wcscat(buf, lbuf);
  648. }
  649. break;
  650. }
  651. case CIM_REAL64|VT_ARRAY:
  652. {
  653. SAFEARRAY *pVec = pValue->parray;
  654. long iLBound, iUBound;
  655. BOOL bFirst = TRUE;
  656. SafeArrayGetLBound(pVec, 1, &iLBound);
  657. SafeArrayGetUBound(pVec, 1, &iUBound);
  658. if ((iUBound - iLBound + 1) == 0) {
  659. buf = (WCHAR *)malloc(BLOCKSIZE);
  660. if ( !buf ) goto AllocFailed;
  661. wcscpy(buf, L"<empty array>");
  662. break;
  663. }
  664. buf = (WCHAR *)malloc((iUBound - iLBound + 1) * (CVTBUFSIZE * sizeof(WCHAR)));
  665. if ( !buf ) goto AllocFailed;
  666. wcscpy(buf, L"");
  667. for (long i = iLBound; i <= iUBound; i++) {
  668. if (!bFirst) {
  669. wcscat(buf, L",");
  670. } else {
  671. bFirst = FALSE;
  672. }
  673. double v;
  674. SafeArrayGetElement(pVec, &i, &v);
  675. swprintf(lbuf, L"%10.4f", v);
  676. wcscat(buf, lbuf);
  677. }
  678. break;
  679. }
  680. case VT_BSTR|VT_ARRAY:
  681. {
  682. if (dwType == (CIM_UINT64|VT_ARRAY))
  683. {
  684. SAFEARRAY *pVec = pValue->parray;
  685. long iLBound, iUBound;
  686. BOOL bFirst = TRUE;
  687. SafeArrayGetLBound(pVec, 1, &iLBound);
  688. SafeArrayGetUBound(pVec, 1, &iUBound);
  689. if ((iUBound - iLBound + 1) == 0) {
  690. buf = (WCHAR *)malloc(BLOCKSIZE);
  691. if ( !buf ) goto AllocFailed;
  692. wcscpy(buf, L"<empty array>");
  693. break;
  694. }
  695. buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
  696. if ( !buf ) goto AllocFailed;
  697. wcscpy(buf, L"");
  698. for (long i = iLBound; i <= iUBound; i++) {
  699. if (!bFirst) {
  700. wcscat(buf, L",");
  701. } else {
  702. bFirst = FALSE;
  703. }
  704. BSTR v = NULL;
  705. SafeArrayGetElement(pVec, &i, &v);
  706. swprintf(lbuf, L"%I64u", _wtoi64(v));
  707. wcscat(buf, lbuf);
  708. }
  709. }
  710. else if (dwType == (CIM_SINT64|VT_ARRAY))
  711. {
  712. SAFEARRAY *pVec = pValue->parray;
  713. long iLBound, iUBound;
  714. BOOL bFirst = TRUE;
  715. SafeArrayGetLBound(pVec, 1, &iLBound);
  716. SafeArrayGetUBound(pVec, 1, &iUBound);
  717. if ((iUBound - iLBound + 1) == 0) {
  718. buf = (WCHAR *)malloc(BLOCKSIZE);
  719. if ( !buf ) goto AllocFailed;
  720. wcscpy(buf, L"<empty array>");
  721. break;
  722. }
  723. buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
  724. if ( !buf ) goto AllocFailed;
  725. wcscpy(buf, L"");
  726. for (long i = iLBound; i <= iUBound; i++) {
  727. if (!bFirst) {
  728. wcscat(buf, L",");
  729. } else {
  730. bFirst = FALSE;
  731. }
  732. BSTR v = NULL;
  733. SafeArrayGetElement(pVec, &i, &v);
  734. swprintf(lbuf, L"%I64d", _wtoi64(v));
  735. wcscat(buf, lbuf);
  736. }
  737. }
  738. else // string, datetime, reference
  739. {
  740. SAFEARRAY *pVec = pValue->parray;
  741. long iLBound, iUBound;
  742. DWORD iNeed;
  743. DWORD iVSize;
  744. DWORD iCurBufSize;
  745. SafeArrayGetLBound(pVec, 1, &iLBound);
  746. SafeArrayGetUBound(pVec, 1, &iUBound);
  747. if ((iUBound - iLBound + 1) == 0) {
  748. buf = (WCHAR *)malloc(BLOCKSIZE);
  749. if ( !buf ) goto AllocFailed;
  750. wcscpy(buf, L"<empty array>");
  751. break;
  752. }
  753. iTotBufSize = (iUBound - iLBound + 1) * BLOCKSIZE;
  754. buf = (WCHAR *)malloc(iTotBufSize);
  755. if ( !buf ) goto AllocFailed;
  756. buf[0] = L'\0';
  757. iCurBufSize = 0;
  758. iVSize = BLOCKSIZE;
  759. vbuf = (WCHAR *)malloc(BLOCKSIZE);
  760. if ( !vbuf ) goto AllocFailed;
  761. for (long i = iLBound; i <= iUBound; i++) {
  762. BSTR v = NULL;
  763. SafeArrayGetElement(pVec, &i, &v);
  764. iLen = (wcslen(v) + 1) * sizeof(WCHAR);
  765. if (iLen > iVSize) {
  766. vbuf = (WCHAR *)realloc(vbuf, iLen + sizeof(WCHAR));
  767. iVSize = iLen;
  768. }
  769. // String size + (quotes + comma + null)
  770. iNeed = (swprintf(vbuf, L"%wS", v) + 4) * sizeof(WCHAR);
  771. if (iNeed + iCurBufSize > iTotBufSize) {
  772. iTotBufSize += (iNeed * 2); // Room enough for 2 more entries
  773. buf = (WCHAR *)realloc(buf, iTotBufSize);
  774. }
  775. wcscat(buf, L"\"");
  776. wcscat(buf, vbuf);
  777. if (i + 1 <= iUBound) {
  778. wcscat(buf, L"\",");
  779. } else {
  780. wcscat(buf, L"\"");
  781. }
  782. iCurBufSize += iNeed;
  783. SysFreeString(v);
  784. }
  785. free(vbuf);
  786. }
  787. break;
  788. }
  789. default:
  790. {
  791. buf = (WCHAR *)malloc(BLOCKSIZE);
  792. if ( !buf ) goto AllocFailed;
  793. wcscpy(buf, L"<conversion error>");
  794. break;
  795. }
  796. }
  797. AllocFailed:
  798. *pbuf = buf;
  799. return buf;
  800. } // valueToString
  801. DNS_STATUS
  802. printWmiObjectProperties(
  803. IWbemClassObject * pObj
  804. )
  805. {
  806. DNS_STATUS status = ERROR_SUCCESS;
  807. HRESULT hres = 0;
  808. SAFEARRAY * pNames = NULL;
  809. BSTR bstrPropName = NULL;
  810. VARIANT var;
  811. BSTR bstrCimType = SysAllocString( L"CIMTYPE" );
  812. PWSTR pwszVal = NULL;
  813. if ( !bstrCimType )
  814. {
  815. status = DNS_ERROR_NO_MEMORY;
  816. goto Done;
  817. }
  818. VariantClear( &var );
  819. //
  820. // Get the RELPATH for this object.
  821. //
  822. status = getRelpath( pObj, &var );
  823. if ( status != ERROR_SUCCESS )
  824. {
  825. goto Done;
  826. }
  827. printf( "%S\n\n", V_BSTR( &var ) );
  828. //
  829. // Enumerate all properties of this object.
  830. //
  831. hres = pObj->GetNames(
  832. NULL, // qualifier
  833. WBEM_FLAG_ALWAYS | WBEM_FLAG_NONSYSTEM_ONLY,
  834. NULL, // qualifier value
  835. &pNames );
  836. if ( FAILED( hres ) )
  837. {
  838. goto Done;
  839. }
  840. ASSERT( pNames );
  841. long lowerBound;
  842. long upperBound;
  843. SafeArrayGetLBound( pNames, 1, &lowerBound );
  844. SafeArrayGetUBound( pNames, 1, &upperBound );
  845. for ( long i = lowerBound; i <= upperBound; ++i )
  846. {
  847. //
  848. // Print the name and type of this property value.
  849. //
  850. hres = SafeArrayGetElement( pNames, &i, &bstrPropName );
  851. if ( !SUCCEEDED( hres ) )
  852. {
  853. ASSERT( SUCCEEDED( hres ) );
  854. continue;
  855. }
  856. IWbemQualifierSet * pQualSet = NULL;
  857. hres = pObj->GetPropertyQualifierSet( bstrPropName, &pQualSet );
  858. if ( !SUCCEEDED( hres ) )
  859. {
  860. ASSERT( SUCCEEDED( hres ) );
  861. continue;
  862. }
  863. VariantClear( &var );
  864. pQualSet->Get( bstrCimType, 0, &var, NULL );
  865. if ( !SUCCEEDED( hres ) )
  866. {
  867. ASSERT( SUCCEEDED( hres ) );
  868. continue;
  869. }
  870. int padlen = 30 - wcslen( bstrPropName ) - wcslen( V_BSTR( &var ) );
  871. printf(
  872. "%S (%S) %.*S = ",
  873. bstrPropName,
  874. V_BSTR( &var ),
  875. padlen > 0 ? padlen : 0,
  876. DNS_WMI_BLANK_STRING );
  877. //
  878. // Print the property value.
  879. //
  880. VariantClear( &var );
  881. CIMTYPE cimType = 0;
  882. hres = pObj->Get( bstrPropName, 0, &var, &cimType, NULL );
  883. if ( !SUCCEEDED( hres ) )
  884. {
  885. ASSERT( SUCCEEDED( hres ) );
  886. continue;
  887. }
  888. printf( "%S\n", valueToString( cimType, &var, &pwszVal ) );
  889. free( pwszVal );
  890. pwszVal = NULL;
  891. }
  892. Done:
  893. free( pwszVal );
  894. SysFreeString( bstrCimType );
  895. SafeArrayDestroy( pNames );
  896. if ( status == ERROR_SUCCESS && FAILED( hres ) )
  897. {
  898. status = HRES_TO_STATUS( hres );
  899. }
  900. return status;
  901. } // printWmiObjectProperties
  902. //
  903. // External functions
  904. //
  905. DNS_STATUS
  906. DnscmdWmi_Initialize(
  907. IN PWSTR pwszServerName
  908. )
  909. /*++
  910. Routine Description:
  911. Setup mod buffer for max count of items.
  912. Arguments:
  913. pwszServerName -- IP address or name of target server
  914. Return Value:
  915. ERROR_SUCCESS if successful or error code on failure.
  916. --*/
  917. {
  918. static const char * fn = "DnscmdWmi_Initialize";
  919. DNS_STATUS status = ERROR_SUCCESS;
  920. HRESULT hres = 0;
  921. IWbemLocator * pIWbemLocator = NULL;
  922. BSTR bstrNamespace = NULL;
  923. IWbemServices * pIWbemServices = NULL;
  924. WCHAR wsz[ 1024 ];
  925. DNSCMD_CHECK_WMI_ENABLED();
  926. //
  927. // Initialize COM.
  928. //
  929. if ( FAILED( hres = CoInitialize( NULL ) ) )
  930. {
  931. printf( "%s: CoInitialize returned 0x%08X\n", fn, hres );
  932. goto Done;
  933. }
  934. //
  935. // Initialize security.
  936. //
  937. hres = CoInitializeSecurity(
  938. NULL, // permissions
  939. -1, // auth service count
  940. NULL, // auth services
  941. NULL, // reserved
  942. RPC_C_AUTHZ_NONE,
  943. RPC_C_IMP_LEVEL_IMPERSONATE,
  944. NULL, // auth list
  945. 0, // capabilities
  946. 0 ); // reserved
  947. if ( FAILED( hres ) )
  948. {
  949. printf(
  950. "%s: CoInitializeSecurity() returned 0x%08X\n",
  951. fn,
  952. hres );
  953. goto Done;
  954. }
  955. //
  956. // Create instance of WbemLocator interface.
  957. //
  958. hres = CoCreateInstance(
  959. CLSID_WbemLocator,
  960. NULL,
  961. CLSCTX_INPROC_SERVER,
  962. IID_IWbemLocator,
  963. ( LPVOID * ) &pIWbemLocator );
  964. if ( FAILED( hres ) )
  965. {
  966. printf(
  967. "%s: CoCreateInstance( CLSID_WbemLocator ) returned 0x%08X\n",
  968. fn,
  969. hres );
  970. goto Done;
  971. }
  972. //
  973. // Connect to MicrosoftDNS namespace on server.
  974. //
  975. wsprintfW(
  976. wsz,
  977. L"\\\\%s\\%s",
  978. pwszServerName,
  979. DNS_WMI_NAMESPACE );
  980. bstrNamespace = SysAllocString( wsz );
  981. if ( !bstrNamespace )
  982. {
  983. ASSERT( bstrNamespace );
  984. status = DNS_ERROR_NO_MEMORY;
  985. goto Done;
  986. }
  987. hres = pIWbemLocator->ConnectServer(
  988. bstrNamespace,
  989. NULL, // user id
  990. NULL, // password
  991. NULL, // locale
  992. 0, // security flags
  993. NULL, // domain
  994. NULL, // context
  995. &pIWbemServices );
  996. if ( FAILED( hres ) )
  997. {
  998. printf(
  999. "%s: ConnectServer( %S ) returned 0x%08X\n",
  1000. fn,
  1001. DNS_WMI_NAMESPACE,
  1002. hres );
  1003. goto Done;
  1004. }
  1005. if ( !pIWbemServices )
  1006. {
  1007. ASSERT( pIWbemServices );
  1008. status = DNS_ERROR_NO_MEMORY;
  1009. goto Done;
  1010. }
  1011. //
  1012. // Set security.
  1013. //
  1014. hres = CoSetProxyBlanket(
  1015. pIWbemServices,
  1016. RPC_C_AUTHN_WINNT,
  1017. RPC_C_AUTHZ_NONE,
  1018. NULL, // principal name
  1019. RPC_C_AUTHN_LEVEL_CALL,
  1020. RPC_C_IMP_LEVEL_IMPERSONATE,
  1021. NULL, // client identify
  1022. EOAC_NONE );
  1023. if ( FAILED( hres ) )
  1024. {
  1025. printf(
  1026. "%s: CoSetProxyBlanket() returned 0x%08X\n",
  1027. fn,
  1028. hres );
  1029. goto Done;
  1030. }
  1031. //
  1032. // Cleanup and return.
  1033. //
  1034. Done:
  1035. SysFreeString( bstrNamespace );
  1036. if ( pIWbemLocator )
  1037. {
  1038. pIWbemLocator->Release();
  1039. }
  1040. if ( status == ERROR_SUCCESS && FAILED( hres ) )
  1041. {
  1042. status = HRES_TO_STATUS( hres );
  1043. }
  1044. if ( status == ERROR_SUCCESS )
  1045. {
  1046. g_pIWbemServices = pIWbemServices;
  1047. }
  1048. return status;
  1049. } // DnscmdWmi_Initialize
  1050. DNS_STATUS
  1051. DnscmdWmi_Free(
  1052. VOID
  1053. )
  1054. /*++
  1055. Routine Description:
  1056. Close WMI session and free globals.
  1057. Arguments:
  1058. None.
  1059. Return Value:
  1060. None.
  1061. --*/
  1062. {
  1063. DBG_FN( "DnscmdWmi_Free" )
  1064. DNSCMD_CHECK_WMI_ENABLED();
  1065. if ( g_pIWbemServices )
  1066. {
  1067. g_pIWbemServices->Release();
  1068. g_pIWbemServices = NULL;
  1069. }
  1070. CoUninitialize();
  1071. return ERROR_SUCCESS;
  1072. } // DnscmdWmi_Free
  1073. DNS_STATUS
  1074. DnscmdWmi_ProcessDnssrvQuery(
  1075. IN PSTR pszZoneName,
  1076. IN PCSTR pszQuery
  1077. )
  1078. /*++
  1079. Routine Description:
  1080. Perform query.
  1081. Arguments:
  1082. pszZoneName -- zone name or NULL for server level query
  1083. pszQuery -- query name
  1084. Return Value:
  1085. ERROR_SUCCESS if successful or error code on failure.
  1086. --*/
  1087. {
  1088. DNS_STATUS status = ERROR_SUCCESS;
  1089. BSTR bstrClassName = NULL;
  1090. IEnumWbemClassObject * pEnum = NULL;
  1091. IWbemClassObject * pObj = NULL;
  1092. ULONG returnedCount = 1;
  1093. DNSCMD_CHECK_WMI_ENABLED();
  1094. //
  1095. // Get WMI object.
  1096. //
  1097. status = getEnumerator( pszZoneName, &pEnum );
  1098. if ( status != ERROR_SUCCESS )
  1099. {
  1100. goto Done;
  1101. }
  1102. status = getNextObjectInEnum( pEnum, &pObj );
  1103. if ( status != ERROR_SUCCESS || !pObj )
  1104. {
  1105. goto Done;
  1106. }
  1107. printWmiObjectProperties( pObj );
  1108. //
  1109. // Cleanup and return.
  1110. //
  1111. Done:
  1112. SysFreeString( bstrClassName );
  1113. if ( pObj )
  1114. {
  1115. pObj->Release();
  1116. }
  1117. if ( pEnum )
  1118. {
  1119. pEnum->Release();
  1120. }
  1121. return status;
  1122. } // DnscmdWmi_ProcessDnssrvQuery
  1123. DNS_STATUS
  1124. DnscmdWmi_ProcessEnumZones(
  1125. IN DWORD dwFilter
  1126. )
  1127. /*++
  1128. Routine Description:
  1129. Enumerate zones.
  1130. Arguments:
  1131. dwFilter -- filter
  1132. Return Value:
  1133. ERROR_SUCCESS if successful or error code on failure.
  1134. --*/
  1135. {
  1136. DNS_STATUS status = ERROR_SUCCESS;
  1137. BSTR bstrClassName = NULL;
  1138. IEnumWbemClassObject * pEnum = NULL;
  1139. IWbemClassObject * pObj = NULL;
  1140. HRESULT hres = 0;
  1141. ULONG returnedCount = 1;
  1142. DNSCMD_CHECK_WMI_ENABLED();
  1143. //
  1144. // Create zone enumerator.
  1145. //
  1146. bstrClassName = SysAllocString( L"MicrosoftDNS_Zone" );
  1147. if ( !bstrClassName )
  1148. {
  1149. ASSERT( bstrClassName );
  1150. status = DNS_ERROR_NO_MEMORY;
  1151. goto Done;
  1152. }
  1153. hres = g_pIWbemServices->CreateInstanceEnum(
  1154. bstrClassName,
  1155. 0, // flags
  1156. NULL, // context
  1157. &pEnum );
  1158. if ( FAILED( hres ) )
  1159. {
  1160. goto Done;
  1161. }
  1162. ASSERT( pEnum );
  1163. //
  1164. // Enumerate zones.
  1165. //
  1166. while ( returnedCount == 1 )
  1167. {
  1168. VARIANT val;
  1169. CIMTYPE cimtype = 0;
  1170. PWSTR pwszVal = NULL;
  1171. VariantInit( &val );
  1172. status = getNextObjectInEnum( pEnum, &pObj, FALSE );
  1173. if ( status != ERROR_SUCCESS || !pObj )
  1174. {
  1175. goto Done;
  1176. }
  1177. //
  1178. // Print properties for this zone.
  1179. //
  1180. #define CHECK_HRES( hresult, propname ) \
  1181. if ( FAILED( hresult ) ) \
  1182. { \
  1183. printf( "\n\nWMI error 0x%08X reading property %S!\n", \
  1184. hresult, propname ); \
  1185. goto Done; \
  1186. }
  1187. hres = pObj->Get( L"Name", 0, &val, &cimtype, NULL );
  1188. CHECK_HRES( hres, L"Name" );
  1189. printf( " %-29S", valueToString( cimtype, &val, &pwszVal ) );
  1190. free( pwszVal );
  1191. VariantClear( &val );
  1192. hres = pObj->Get( L"ZoneType", 0, &val, &cimtype, NULL );
  1193. CHECK_HRES( hres, L"ZoneType" );
  1194. ASSERT( val.vt == VT_I4 );
  1195. printf( "%3d ", val.lVal );
  1196. VariantClear( &val );
  1197. hres = pObj->Get( L"DsIntegrated", 0, &val, &cimtype, NULL );
  1198. CHECK_HRES( hres, L"DsIntegrated" );
  1199. ASSERT( val.vt == VT_BOOL );
  1200. printf( "%-4S ", val.boolVal ? L"DS" : L"file" );
  1201. VariantClear( &val );
  1202. hres = pObj->Get( L"Reverse", 0, &val, &cimtype, NULL );
  1203. CHECK_HRES( hres, L"Reverse" );
  1204. ASSERT( val.vt == VT_BOOL );
  1205. printf( "%-3S ", val.boolVal ? L"Rev" : L"" );
  1206. VariantClear( &val );
  1207. hres = pObj->Get( L"AutoCreated", 0, &val, &cimtype, NULL );
  1208. CHECK_HRES( hres, L"AutoCreated" );
  1209. ASSERT( val.vt == VT_BOOL );
  1210. printf( "%-4S ", val.boolVal ? L"Auto" : L"" );
  1211. VariantClear( &val );
  1212. hres = pObj->Get( L"AllowUpdate", 0, &val, &cimtype, NULL );
  1213. CHECK_HRES( hres, L"AllowUpdate" );
  1214. ASSERT( val.vt == VT_BOOL );
  1215. printf( "Up=%d ", val.boolVal ? 1 : 0 );
  1216. VariantClear( &val );
  1217. hres = pObj->Get( L"Aging", 0, &val, &cimtype, NULL );
  1218. CHECK_HRES( hres, L"Aging" );
  1219. ASSERT( val.vt == VT_BOOL );
  1220. printf( "%-5S ", val.boolVal ? L"Aging" : L"" );
  1221. VariantClear( &val );
  1222. hres = pObj->Get( L"Paused", 0, &val, &cimtype, NULL );
  1223. CHECK_HRES( hres, L"Paused" );
  1224. ASSERT( val.vt == VT_BOOL );
  1225. printf( "%-6S ", val.boolVal ? L"Paused" : L"" );
  1226. VariantClear( &val );
  1227. hres = pObj->Get( L"Shutdown", 0, &val, &cimtype, NULL );
  1228. CHECK_HRES( hres, L"Shutdown" );
  1229. ASSERT( val.vt == VT_BOOL );
  1230. printf( "%-6S", val.boolVal ? L"Shutdn" : L"" );
  1231. VariantClear( &val );
  1232. printf( "\n\n" );
  1233. }
  1234. //
  1235. // Cleanup and return.
  1236. //
  1237. Done:
  1238. SysFreeString( bstrClassName );
  1239. if ( pObj )
  1240. {
  1241. pObj->Release();
  1242. }
  1243. if ( pEnum )
  1244. {
  1245. pEnum->Release();
  1246. }
  1247. if ( status == ERROR_SUCCESS && FAILED( hres ) )
  1248. {
  1249. status = HRES_TO_STATUS( hres );
  1250. }
  1251. return status;
  1252. } // DnscmdWmi_ProcessEnumZones
  1253. DNS_STATUS
  1254. DnscmdWmi_ProcessZoneInfo(
  1255. IN LPSTR pszZone
  1256. )
  1257. /*++
  1258. Routine Description:
  1259. Enumerate zones.
  1260. Arguments:
  1261. dwFilter -- filter
  1262. Return Value:
  1263. ERROR_SUCCESS if successful or error code on failure.
  1264. --*/
  1265. {
  1266. DNS_STATUS status = ERROR_SUCCESS;
  1267. IWbemClassObject * pObj = NULL;
  1268. IEnumWbemClassObject * pEnum = NULL;
  1269. ULONG returnedCount = 1;
  1270. WCHAR wsz[ 1024 ];
  1271. DNSCMD_CHECK_WMI_ENABLED();
  1272. //
  1273. // Get WMI object.
  1274. //
  1275. status = getEnumerator( pszZone, &pEnum );
  1276. if ( status != ERROR_SUCCESS )
  1277. {
  1278. goto Done;
  1279. }
  1280. status = getNextObjectInEnum( pEnum, &pObj, FALSE );
  1281. if ( status != ERROR_SUCCESS || !pObj )
  1282. {
  1283. goto Done;
  1284. }
  1285. printWmiObjectProperties( pObj );
  1286. //
  1287. // Cleanup and return.
  1288. //
  1289. Done:
  1290. if ( pObj )
  1291. {
  1292. pObj->Release();
  1293. }
  1294. if ( pEnum )
  1295. {
  1296. pEnum->Release();
  1297. }
  1298. return status;
  1299. } // DnscmdWmi_ProcessZoneInfo
  1300. DNS_STATUS
  1301. DnscmdWmi_ProcessEnumRecords(
  1302. IN LPSTR pszZone,
  1303. IN LPSTR pszNode,
  1304. IN BOOL fDetail,
  1305. IN DWORD dwFlags
  1306. )
  1307. /*++
  1308. Routine Description:
  1309. Enumerate Records.
  1310. Arguments:
  1311. pszZone -- zone name
  1312. pszNode -- name of root node to at which to enumerate records
  1313. fDetail -- print summary or full detail
  1314. dwFlags -- search flags
  1315. Return Value:
  1316. ERROR_SUCCESS if successful or error code on failure.
  1317. --*/
  1318. {
  1319. DNS_STATUS status = ERROR_SUCCESS;
  1320. BSTR bstrWQL = NULL;
  1321. BSTR bstrQuery = NULL;
  1322. IWbemClassObject * pObj = NULL;
  1323. IEnumWbemClassObject * pEnum = NULL;
  1324. HRESULT hres = 0;
  1325. ULONG returnedCount = 1;
  1326. WCHAR wsz[ 1024 ];
  1327. DNSCMD_CHECK_WMI_ENABLED();
  1328. //
  1329. // Query for zone.
  1330. //
  1331. if ( pszNode == NULL || strcmp( pszNode, "@" ) == 0 )
  1332. {
  1333. wsprintfW(
  1334. wsz,
  1335. L"select * from MicrosoftDNS_ResourceRecord "
  1336. L"where ContainerName='%S'",
  1337. pszZone );
  1338. }
  1339. else
  1340. {
  1341. wsprintfW(
  1342. wsz,
  1343. L"select * from MicrosoftDNS_ResourceRecord "
  1344. L"where DomainName='%S'",
  1345. pszNode );
  1346. }
  1347. bstrWQL = SysAllocString( L"WQL" );
  1348. bstrQuery = SysAllocString( wsz );
  1349. if ( !bstrWQL || !bstrQuery )
  1350. {
  1351. status = DNS_ERROR_NO_MEMORY;
  1352. goto Done;
  1353. }
  1354. hres = g_pIWbemServices->ExecQuery(
  1355. bstrWQL,
  1356. bstrQuery,
  1357. WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
  1358. NULL,
  1359. &pEnum );
  1360. if ( FAILED( hres ) )
  1361. {
  1362. goto Done;
  1363. }
  1364. ASSERT( pEnum );
  1365. //
  1366. // Dump results.
  1367. //
  1368. while ( 1 )
  1369. {
  1370. status = getNextObjectInEnum( pEnum, &pObj );
  1371. if ( status != ERROR_SUCCESS || !pObj )
  1372. {
  1373. break;
  1374. }
  1375. if ( fDetail )
  1376. {
  1377. printWmiObjectProperties( pObj );
  1378. }
  1379. else
  1380. {
  1381. VARIANT val;
  1382. CIMTYPE cimtype = 0;
  1383. PWSTR pwszVal = NULL;
  1384. VariantInit( &val );
  1385. hres = pObj->Get( L"TextRepresentation", 0, &val, &cimtype, NULL );
  1386. CHECK_HRES( hres, L"TextRepresentation" );
  1387. printf( "%S", valueToString( cimtype, &val, &pwszVal ) );
  1388. free( pwszVal );
  1389. VariantClear( &val );
  1390. printf( "\n" );
  1391. }
  1392. }
  1393. //
  1394. // Cleanup and return.
  1395. //
  1396. Done:
  1397. SysFreeString( bstrWQL );
  1398. SysFreeString( bstrQuery );
  1399. if ( pObj )
  1400. {
  1401. pObj->Release();
  1402. }
  1403. if ( pEnum )
  1404. {
  1405. pEnum->Release();
  1406. }
  1407. if ( status == ERROR_SUCCESS && FAILED( hres ) )
  1408. {
  1409. status = HRES_TO_STATUS( hres );
  1410. }
  1411. return status;
  1412. } // DnscmdWmi_ProcessEnumRecords
  1413. DNS_STATUS
  1414. DnscmdWmi_ResetProperty(
  1415. IN LPSTR pszZone,
  1416. IN LPSTR pszProperty,
  1417. IN DWORD cimType,
  1418. IN PVOID value
  1419. )
  1420. /*++
  1421. Routine Description:
  1422. Reset a server or zone property.
  1423. Arguments:
  1424. pszZone -- zone name - NULL for server property
  1425. pszProperty -- name of property to set
  1426. cimType -- variant type of the property, use one of:
  1427. VT_I4 - DWORD
  1428. VT_BSTR - string
  1429. ? - IP list
  1430. value -- new value for property, interpreted based on cimtype:
  1431. VT_I4 - cast pointer directly DWORD
  1432. VT_BSTR - pointer to UTF-8 string
  1433. ? - pointer to IP list
  1434. Return Value:
  1435. ERROR_SUCCESS if successful or error code on failure.
  1436. --*/
  1437. {
  1438. DNS_STATUS status = ERROR_SUCCESS;
  1439. BSTR bstrWQL = NULL;
  1440. BSTR bstrQuery = NULL;
  1441. BSTR bstrPropName = NULL;
  1442. IWbemClassObject * pObj = NULL;
  1443. IEnumWbemClassObject * pEnum = NULL;
  1444. HRESULT hres = 0;
  1445. ULONG returnedCount = 1;
  1446. WCHAR wsz[ 1024 ];
  1447. PWSTR pwszPropertyName = NULL;
  1448. PWSTR pwszPropertyValue = NULL;
  1449. DNSCMD_CHECK_WMI_ENABLED();
  1450. //
  1451. // Get WMI object.
  1452. //
  1453. status = getEnumerator( pszZone, &pEnum );
  1454. if ( status != ERROR_SUCCESS )
  1455. {
  1456. goto Done;
  1457. }
  1458. status = getNextObjectInEnum( pEnum, &pObj );
  1459. if ( status != ERROR_SUCCESS || !pObj )
  1460. {
  1461. goto Done;
  1462. }
  1463. //
  1464. // Print the object's RELPATH (warm fuzzy).
  1465. //
  1466. VARIANT var;
  1467. status = getRelpath( pObj, &var );
  1468. if ( status != ERROR_SUCCESS )
  1469. {
  1470. goto Done;
  1471. }
  1472. printf( "%S\n\n", V_BSTR( &var) );
  1473. //
  1474. // Set the property.
  1475. //
  1476. pwszPropertyName = ( PWSTR ) Dns_NameCopyAllocate(
  1477. pszProperty,
  1478. 0,
  1479. DnsCharSetUtf8,
  1480. DnsCharSetUnicode );
  1481. bstrPropName = SysAllocString( pwszPropertyName );
  1482. VariantClear( &var );
  1483. switch ( cimType )
  1484. {
  1485. case VT_BSTR:
  1486. pwszPropertyValue = ( PWSTR ) Dns_NameCopyAllocate(
  1487. ( PCHAR ) value,
  1488. 0,
  1489. DnsCharSetUtf8,
  1490. DnsCharSetUnicode );
  1491. V_VT( &var ) = VT_BSTR;
  1492. V_BSTR( &var ) = pwszPropertyValue;
  1493. break;
  1494. case PRIVATE_VT_IPARRAY:
  1495. {
  1496. SAFEARRAY * psa = createSafeArrayForIpArray(
  1497. ( PIP_ARRAY ) value );
  1498. V_VT( &var ) = VT_ARRAY | VT_BSTR;
  1499. V_ARRAY( &var ) = psa;
  1500. break;
  1501. }
  1502. default: // Assume this is DWORD property.
  1503. V_VT( &var ) = VT_I4;
  1504. V_I4( &var ) = ( DWORD ) ( DWORD_PTR ) value;
  1505. break;
  1506. }
  1507. hres = pObj->Put( bstrPropName, 0, &var, 0 );
  1508. VariantClear( &var );
  1509. if ( !SUCCEEDED( hres ) )
  1510. {
  1511. printf( "WMI: unable to Put property error=0x%08X\n", hres );
  1512. goto Done;
  1513. }
  1514. //
  1515. // Commit the change back to WMI.
  1516. //
  1517. hres = g_pIWbemServices->PutInstance( pObj, 0, NULL, NULL );
  1518. if ( !SUCCEEDED( hres ) )
  1519. {
  1520. printf( "WMI: unable to commit property error=0x%08X\n", hres );
  1521. goto Done;
  1522. }
  1523. //
  1524. // Cleanup and return.
  1525. //
  1526. Done:
  1527. FREE_HEAP( pwszPropertyName );
  1528. FREE_HEAP( pwszPropertyValue );
  1529. SysFreeString( bstrPropName );
  1530. if ( pObj )
  1531. {
  1532. pObj->Release();
  1533. }
  1534. if ( pEnum )
  1535. {
  1536. pEnum->Release();
  1537. }
  1538. if ( status == ERROR_SUCCESS && FAILED( hres ) )
  1539. {
  1540. status = HRES_TO_STATUS( hres );
  1541. }
  1542. return status;
  1543. } // DnscmdWmi_ResetDwordProperty
  1544. /*++
  1545. Routine Description:
  1546. Reset server level forwarders.
  1547. Arguments:
  1548. cForwarders -- number of forwarder IP addresses
  1549. aipForwarders -- array of forwarder IP addresses
  1550. dwForwardTimeout -- timeout
  1551. fSlave -- slave flag
  1552. Return Value:
  1553. ERROR_SUCCESS if successful or error code on failure.
  1554. --*/
  1555. DNS_STATUS
  1556. DnscmdWmi_ProcessResetForwarders(
  1557. IN DWORD cForwarders,
  1558. IN PIP_ADDRESS aipForwarders,
  1559. IN DWORD dwForwardTimeout,
  1560. IN DWORD fSlave
  1561. )
  1562. {
  1563. DNS_STATUS status = ERROR_SUCCESS;
  1564. IEnumWbemClassObject * pEnum = NULL;
  1565. IWbemClassObject * pObj = NULL;
  1566. SAFEARRAY * psa = NULL;
  1567. HRESULT hres = 0;
  1568. VARIANT var;
  1569. VariantInit( &var );
  1570. //
  1571. // Get WMI object for server.
  1572. //
  1573. status = getEnumerator( NULL, &pEnum );
  1574. if ( status != ERROR_SUCCESS )
  1575. {
  1576. goto Done;
  1577. }
  1578. status = getNextObjectInEnum( pEnum, &pObj );
  1579. if ( status != ERROR_SUCCESS || !pObj )
  1580. {
  1581. goto Done;
  1582. }
  1583. //
  1584. // Set up parameters.
  1585. //
  1586. psa = createSafeArrayForIpList( cForwarders, aipForwarders );
  1587. if ( !psa )
  1588. {
  1589. status = ERROR_INVALID_PARAMETER;
  1590. goto Done;
  1591. }
  1592. V_VT( &var ) = VT_ARRAY | VT_BSTR;
  1593. V_ARRAY( &var ) = psa;
  1594. hres = pObj->Put( MYTEXT( DNS_REGKEY_FORWARDERS ), 0, &var, 0 );
  1595. VariantClear( &var );
  1596. if ( !SUCCEEDED( hres ) )
  1597. {
  1598. printf(
  1599. "WMI: unable to Put property %S error=0x%08X\n",
  1600. MYTEXT( DNS_REGKEY_FORWARDERS ),
  1601. hres );
  1602. goto Done;
  1603. }
  1604. V_VT( &var ) = VT_I4;
  1605. V_I4( &var ) = dwForwardTimeout;
  1606. hres = pObj->Put( MYTEXT( DNS_REGKEY_FORWARD_TIMEOUT ), 0, &var, 0 );
  1607. VariantClear( &var );
  1608. if ( !SUCCEEDED( hres ) )
  1609. {
  1610. printf(
  1611. "WMI: unable to Put property %S error=0x%08X\n",
  1612. MYTEXT( DNS_REGKEY_FORWARD_TIMEOUT ),
  1613. hres );
  1614. goto Done;
  1615. }
  1616. V_VT( &var ) = VT_BOOL;
  1617. V_BOOL( &var ) = ( VARIANT_BOOL ) fSlave;
  1618. hres = pObj->Put( MYTEXT( DNS_REGKEY_SLAVE ), 0, &var, 0 );
  1619. VariantClear( &var );
  1620. if ( !SUCCEEDED( hres ) )
  1621. {
  1622. printf(
  1623. "WMI: unable to Put property %S error=0x%08X\n",
  1624. MYTEXT( DNS_REGKEY_SLAVE ),
  1625. hres );
  1626. goto Done;
  1627. }
  1628. //
  1629. // Commit the change back to WMI.
  1630. //
  1631. hres = g_pIWbemServices->PutInstance( pObj, 0, NULL, NULL );
  1632. if ( !SUCCEEDED( hres ) )
  1633. {
  1634. printf( "WMI: unable to commit property error=0x%08X\n", hres );
  1635. goto Done;
  1636. }
  1637. //
  1638. // Cleanup and return.
  1639. //
  1640. Done:
  1641. if ( pObj )
  1642. {
  1643. pObj->Release();
  1644. }
  1645. if ( pEnum )
  1646. {
  1647. pEnum->Release();
  1648. }
  1649. VariantClear( &var );
  1650. if ( status == ERROR_SUCCESS && FAILED( hres ) )
  1651. {
  1652. status = hres;
  1653. }
  1654. return status;
  1655. }
  1656. /*++
  1657. Routine Description:
  1658. Send generic operation to server.
  1659. Arguments:
  1660. pszZone -- zone name or NULL for server level operation
  1661. pszOperation -- string identifying operation
  1662. dwTypeId -- DNS RPC data type of data at pvData
  1663. pvData -- DNS RPC data in DNS RPC union format
  1664. Return Value:
  1665. ERROR_SUCCESS if successful or error code on failure.
  1666. --*/
  1667. DNS_STATUS
  1668. DnscmdWmi_ProcessDnssrvOperation(
  1669. IN LPSTR pszZoneName,
  1670. IN LPSTR pszOperation,
  1671. IN DWORD dwTypeId,
  1672. IN PVOID pvData
  1673. )
  1674. {
  1675. DNS_STATUS status = ERROR_SUCCESS;
  1676. HRESULT hres = 0;
  1677. IEnumWbemClassObject * pEnum = NULL;
  1678. IWbemClassObject * pObj = NULL;
  1679. SAFEARRAY * psa = NULL;
  1680. PWSTR pwszOperation = NULL;
  1681. VARIANT var;
  1682. VariantInit( &var );
  1683. //
  1684. // Get WMI object.
  1685. //
  1686. status = getEnumerator( pszZoneName, &pEnum );
  1687. if ( status != ERROR_SUCCESS )
  1688. {
  1689. goto Done;
  1690. }
  1691. status = getNextObjectInEnum( pEnum, &pObj );
  1692. if ( status != ERROR_SUCCESS || !pObj )
  1693. {
  1694. goto Done;
  1695. }
  1696. //
  1697. // Process operation.
  1698. //
  1699. pwszOperation = ( PWSTR ) Dns_NameCopyAllocate(
  1700. pszOperation,
  1701. 0,
  1702. DnsCharSetUtf8,
  1703. DnsCharSetUnicode );
  1704. if ( !pwszOperation )
  1705. {
  1706. status = DNS_ERROR_NO_MEMORY;
  1707. goto Done;
  1708. }
  1709. if ( _stricmp( pszOperation, DNS_REGKEY_ZONE_MASTERS ) == 0 ||
  1710. _stricmp( pszOperation, DNS_REGKEY_ZONE_LOCAL_MASTERS ) == 0 )
  1711. {
  1712. //
  1713. // For these properties do a simple Put operation by converting
  1714. // the DNS RPC data into VARIANT format and calling Put.
  1715. //
  1716. switch ( dwTypeId )
  1717. {
  1718. case DNSSRV_TYPEID_IPARRAY:
  1719. {
  1720. PIP_ARRAY pip = ( PIP_ARRAY ) pvData;
  1721. psa = createSafeArrayForIpList(
  1722. pip ? pip->AddrCount : 0,
  1723. pip ? pip->AddrArray : NULL );
  1724. if ( !psa )
  1725. {
  1726. status = ERROR_INVALID_PARAMETER;
  1727. goto Done;
  1728. }
  1729. V_VT( &var ) = VT_ARRAY | VT_BSTR;
  1730. V_ARRAY( &var ) = psa;
  1731. hres = pObj->Put( pwszOperation, 0, &var, 0 );
  1732. break;
  1733. }
  1734. default:
  1735. status = ERROR_NOT_SUPPORTED;
  1736. break;
  1737. }
  1738. //
  1739. // Commit the Put operation.
  1740. //
  1741. if ( status == ERROR_SUCCESS && SUCCEEDED( hres ) )
  1742. {
  1743. hres = g_pIWbemServices->PutInstance( pObj, 0, NULL, NULL );
  1744. if ( FAILED( hres ) )
  1745. {
  1746. printf(
  1747. "WMI: unable to commit property %s error=0x%08X\n",
  1748. pszOperation,
  1749. hres );
  1750. goto Done;
  1751. }
  1752. }
  1753. }
  1754. else if ( _stricmp( pszOperation, DNSSRV_OP_ZONE_DELETE ) == 0 ||
  1755. _stricmp( pszOperation, DNSSRV_OP_ZONE_DELETE_FROM_DS ) == 0 )
  1756. {
  1757. //
  1758. // Delete the zone.
  1759. //
  1760. VARIANT relpath;
  1761. status = getRelpath( pObj, &relpath );
  1762. if ( status == ERROR_SUCCESS )
  1763. {
  1764. hres = g_pIWbemServices->DeleteInstance(
  1765. V_BSTR( &relpath ),
  1766. 0,
  1767. NULL,
  1768. NULL );
  1769. }
  1770. VariantClear( &relpath );
  1771. }
  1772. else
  1773. {
  1774. status = ERROR_NOT_SUPPORTED;
  1775. }
  1776. //
  1777. // Cleanup and return.
  1778. //
  1779. Done:
  1780. if ( psa )
  1781. {
  1782. SafeArrayDestroy( psa );
  1783. }
  1784. if ( pwszOperation )
  1785. {
  1786. FREE_HEAP( pwszOperation );
  1787. }
  1788. if ( pObj )
  1789. {
  1790. pObj->Release();
  1791. }
  1792. if ( pEnum )
  1793. {
  1794. pEnum->Release();
  1795. }
  1796. VariantClear( &var );
  1797. if ( status == ERROR_SUCCESS && FAILED( hres ) )
  1798. {
  1799. status = hres;
  1800. }
  1801. return status;
  1802. } // DnscmdWmi_ProcessDnssrvOperation
  1803. DNS_STATUS
  1804. DnscmdWmi_ProcessRecordAdd(
  1805. IN LPSTR pszZoneName,
  1806. IN LPSTR pszNodeName,
  1807. IN PDNS_RPC_RECORD prrRpc,
  1808. IN DWORD Argc,
  1809. IN LPSTR * Argv
  1810. )
  1811. /*++
  1812. Routine Description:
  1813. Add or delete a resource record. This function will take
  1814. of the necessary some data from the RPC record and some from
  1815. the argument list.
  1816. Arguments:
  1817. pszZoneName -- zone name
  1818. pszNodeName -- name of property to set
  1819. prrRpc -- RPC record
  1820. Argc -- count of arguments used to create RPC record
  1821. Argv -- arguments used to create RPC record
  1822. Return Value:
  1823. ERROR_SUCCESS if successful or error code on failure.
  1824. --*/
  1825. {
  1826. DNS_STATUS status = ERROR_SUCCESS;
  1827. PWSTR pwszZoneName = NULL;
  1828. PWSTR pwszArgs = NULL;
  1829. PWSTR pwszCurrent;
  1830. IWbemClassObject * pClassObj = NULL;
  1831. IWbemClassObject * pServerObj = NULL;
  1832. IWbemClassObject * pInSig = NULL;
  1833. IWbemClassObject * pOutSig = NULL;
  1834. IWbemClassObject * pInParams = NULL;
  1835. IEnumWbemClassObject * pEnum = NULL;
  1836. HRESULT hres = 0;
  1837. BSTR bstrClassName;
  1838. BSTR bstrMethodName;
  1839. VARIANT var;
  1840. int len;
  1841. int i;
  1842. DNSCMD_CHECK_WMI_ENABLED();
  1843. //
  1844. // Allocate and initialize various stuff.
  1845. //
  1846. VariantInit( &var );
  1847. bstrClassName = SysAllocString( L"MicrosoftDNS_ResourceRecord" );
  1848. bstrMethodName = SysAllocString( L"CreateInstanceFromTextRepresentation" );
  1849. if ( !bstrClassName || !bstrMethodName )
  1850. {
  1851. status = DNS_ERROR_NO_MEMORY;
  1852. goto Done;
  1853. }
  1854. pwszZoneName = ( PWSTR ) Dns_NameCopyAllocate(
  1855. pszZoneName,
  1856. 0,
  1857. DnsCharSetUtf8,
  1858. DnsCharSetUnicode );
  1859. if ( !pwszZoneName )
  1860. {
  1861. status = DNS_ERROR_NO_MEMORY;
  1862. goto Done;
  1863. }
  1864. //
  1865. // Get WMI class object for Resource Record class.
  1866. //
  1867. hres = g_pIWbemServices->GetObject(
  1868. bstrClassName,
  1869. WBEM_FLAG_RETURN_WBEM_COMPLETE,
  1870. NULL,
  1871. &pClassObj,
  1872. NULL );
  1873. if ( FAILED( hres ) )
  1874. {
  1875. goto Done;
  1876. }
  1877. ASSERT( pClassObj );
  1878. //
  1879. // Get WMI object for server.
  1880. //
  1881. status = getEnumerator( NULL, &pEnum );
  1882. if ( status != ERROR_SUCCESS )
  1883. {
  1884. goto Done;
  1885. }
  1886. ASSERT( pEnum );
  1887. status = getNextObjectInEnum( pEnum, &pServerObj );
  1888. if ( status != ERROR_SUCCESS )
  1889. {
  1890. goto Done;
  1891. }
  1892. ASSERT( pServerObj );
  1893. //
  1894. // Get WMI method signature for CreateInstanceFromTextRepresentation.
  1895. //
  1896. hres = pClassObj->GetMethod(
  1897. bstrMethodName,
  1898. 0,
  1899. &pInSig,
  1900. &pOutSig );
  1901. if ( FAILED( hres ) )
  1902. {
  1903. goto Done;
  1904. }
  1905. if ( pInSig == NULL )
  1906. {
  1907. status = ERROR_INVALID_PARAMETER;
  1908. goto Done;
  1909. }
  1910. //
  1911. // Create an instance of the method input parameters.
  1912. //
  1913. hres = pInSig->SpawnInstance( 0, &pInParams );
  1914. if ( FAILED( hres ) )
  1915. {
  1916. goto Done;
  1917. }
  1918. ASSERT( pInParams );
  1919. //
  1920. // Collect the arguments into one big string
  1921. // -> owner name
  1922. // -> record class
  1923. // -> record type
  1924. // -> Argv array (space separated)
  1925. //
  1926. len = Argc * 2 + // for spaces
  1927. 30 + // for record type
  1928. strlen( pszNodeName );
  1929. for ( i = 0; i < ( int ) Argc; ++i )
  1930. {
  1931. len += strlen( Argv[ i ] );
  1932. }
  1933. pwszCurrent = pwszArgs = new WCHAR [ len * sizeof( WCHAR ) ];
  1934. if ( !pwszArgs )
  1935. {
  1936. status = DNS_ERROR_NO_MEMORY;
  1937. goto Done;
  1938. }
  1939. for ( i = -3; i < ( int ) Argc; ++i )
  1940. {
  1941. CHAR szBuff[ 40 ];
  1942. PSTR psz;
  1943. if ( i == -3 )
  1944. {
  1945. psz = pszNodeName;
  1946. }
  1947. else if ( i == -2 )
  1948. {
  1949. psz = "IN";
  1950. }
  1951. else if ( i == -1 )
  1952. {
  1953. psz = Dns_RecordStringForType( prrRpc->wType );
  1954. }
  1955. else
  1956. {
  1957. psz = Argv[ i ];
  1958. }
  1959. PWSTR pwsz = ( PWSTR ) Dns_NameCopyAllocate(
  1960. psz,
  1961. 0,
  1962. DnsCharSetUtf8,
  1963. DnsCharSetUnicode );
  1964. if ( !pwsz )
  1965. {
  1966. status = DNS_ERROR_NO_MEMORY;
  1967. goto Done;
  1968. }
  1969. if ( pwszCurrent != pwszArgs )
  1970. {
  1971. wcscpy( pwszCurrent++, L" " );
  1972. }
  1973. wcscpy( pwszCurrent, pwsz );
  1974. pwszCurrent += wcslen( pwsz );
  1975. }
  1976. //
  1977. // Set method input parameters.
  1978. //
  1979. getRelpath( pServerObj, &var );
  1980. hres = pInParams->Put( L"DnsServerName", 0, &var, 0 );
  1981. VariantClear( &var );
  1982. V_VT( &var ) = VT_BSTR;
  1983. V_BSTR( &var ) = SysAllocString( pwszZoneName );
  1984. hres = pInParams->Put( L"ContainerName", 0, &var, 0 );
  1985. VariantClear( &var );
  1986. V_VT( &var ) = VT_BSTR;
  1987. V_BSTR( &var ) = SysAllocString( pwszArgs );
  1988. hres = pInParams->Put( L"TextRepresentation", 0, &var, 0 );
  1989. VariantClear( &var );
  1990. //
  1991. // Execute the method (finally!)
  1992. //
  1993. hres = g_pIWbemServices->ExecMethod(
  1994. bstrClassName,
  1995. bstrMethodName,
  1996. 0, // flags
  1997. NULL, // context
  1998. pInParams, // input params
  1999. NULL, // output params
  2000. NULL ); // call result
  2001. if ( FAILED( hres ) )
  2002. {
  2003. goto Done;
  2004. }
  2005. //
  2006. // Cleanup and return.
  2007. //
  2008. Done:
  2009. VariantClear( &var );
  2010. FREE_HEAP( pwszZoneName );
  2011. delete [] pwszArgs;
  2012. SysFreeString( bstrMethodName );
  2013. SysFreeString( bstrClassName );
  2014. wmiRelease( pEnum );
  2015. wmiRelease( pClassObj );
  2016. wmiRelease( pServerObj );
  2017. wmiRelease( pInSig );
  2018. wmiRelease( pOutSig );
  2019. wmiRelease( pInParams );
  2020. if ( status == ERROR_SUCCESS && FAILED( hres ) )
  2021. {
  2022. status = HRES_TO_STATUS( hres );
  2023. }
  2024. return status;
  2025. } // DnscmdWmi_ProcessRecordAdd
  2026. DNS_STATUS
  2027. DnscmdWmi_GetStatistics(
  2028. IN DWORD dwStatId
  2029. )
  2030. /*++
  2031. Routine Description:
  2032. Retrieves and dumps all statistics matching the dwStatId mask.
  2033. Arguments:
  2034. dwStatId -- statistic filter
  2035. Return Value:
  2036. ERROR_SUCCESS if successful or error code on failure.
  2037. --*/
  2038. {
  2039. DNS_STATUS status = ERROR_SUCCESS;
  2040. WCHAR wsz[ 1024 ];
  2041. BSTR bstrWQL = NULL;
  2042. BSTR bstrQuery = NULL;
  2043. HRESULT hres = 0;
  2044. IEnumWbemClassObject * pEnum = NULL;
  2045. IWbemClassObject * pObj = NULL;
  2046. //
  2047. // Execute query for statistics.
  2048. //
  2049. wsprintfW(
  2050. wsz,
  2051. L"select * from MicrosoftDNS_Statistic" );
  2052. bstrWQL = SysAllocString( L"WQL" );
  2053. bstrQuery = SysAllocString( wsz );
  2054. if ( !bstrWQL || !bstrQuery )
  2055. {
  2056. status = DNS_ERROR_NO_MEMORY;
  2057. goto Done;
  2058. }
  2059. hres = g_pIWbemServices->ExecQuery(
  2060. bstrWQL,
  2061. bstrQuery,
  2062. WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
  2063. NULL,
  2064. &pEnum );
  2065. if ( FAILED( hres ) )
  2066. {
  2067. status = hres;
  2068. goto Done;
  2069. }
  2070. //
  2071. // Dump query results.
  2072. //
  2073. VARIANT varLastColl;
  2074. VariantInit( &varLastColl );
  2075. while ( 1 )
  2076. {
  2077. status = getNextObjectInEnum( pEnum, &pObj, FALSE );
  2078. if ( status != ERROR_SUCCESS || !pObj )
  2079. {
  2080. break;
  2081. }
  2082. CIMTYPE cimColl = 0;
  2083. CIMTYPE cimName = 0;
  2084. CIMTYPE cimValue = 0;
  2085. CIMTYPE cimStringValue = 0;
  2086. VARIANT varColl;
  2087. VARIANT varName;
  2088. VARIANT varValue;
  2089. VARIANT varStringValue;
  2090. VariantInit( &varColl );
  2091. VariantInit( &varName );
  2092. VariantInit( &varValue );
  2093. VariantInit( &varStringValue );
  2094. hres = pObj->Get( L"CollectionName", 0, &varColl, &cimColl, NULL );
  2095. CHECK_HRES( hres, L"CollectionName" );
  2096. hres = pObj->Get( L"Name", 0, &varName, &cimName, NULL );
  2097. CHECK_HRES( hres, L"Name" );
  2098. hres = pObj->Get( L"Value", 0, &varValue, &cimValue, NULL );
  2099. CHECK_HRES( hres, L"Value" );
  2100. hres = pObj->Get( L"StringValue", 0, &varStringValue, &cimValue, NULL );
  2101. CHECK_HRES( hres, L"StringValue" );
  2102. if ( V_VT( &varLastColl ) == VT_EMPTY ||
  2103. wcscmp( V_BSTR( &varLastColl ), V_BSTR( &varColl ) ) != 0 )
  2104. {
  2105. //
  2106. // Entering new collection. NOTE: this assumes that stats
  2107. // are ordered by collection. Probably not a great assumption
  2108. // but it works for now.
  2109. //
  2110. printf( "\n%S:\n", V_BSTR( &varColl ) );
  2111. VariantCopy( &varLastColl, &varColl );
  2112. }
  2113. printf(
  2114. " %-35S = ",
  2115. V_BSTR( &varName ) );
  2116. if ( V_VT( &varValue ) != VT_NULL )
  2117. {
  2118. printf( "%lu", V_UI4( &varValue ) );
  2119. // printf( "%lu (0x%08X)", V_UI4( &varValue ), V_UI4( &varValue ) );
  2120. }
  2121. else if ( V_VT( &varStringValue ) == VT_BSTR )
  2122. {
  2123. printf( "%S", V_BSTR( &varStringValue ) );
  2124. }
  2125. else
  2126. {
  2127. printf( "invalid value!" );
  2128. }
  2129. printf( "\n" );
  2130. VariantClear( &varColl );
  2131. VariantClear( &varName );
  2132. VariantClear( &varValue );
  2133. VariantClear( &varStringValue );
  2134. }
  2135. VariantClear( &varLastColl );
  2136. //
  2137. // Cleanup and return
  2138. //
  2139. Done:
  2140. SysFreeString( bstrWQL );
  2141. SysFreeString( bstrQuery );
  2142. if ( pEnum )
  2143. {
  2144. pEnum->Release();
  2145. }
  2146. if ( pObj )
  2147. {
  2148. pObj->Release();
  2149. }
  2150. if ( status == ERROR_SUCCESS && FAILED( hres ) )
  2151. {
  2152. status = HRES_TO_STATUS( hres );
  2153. }
  2154. return status;
  2155. }
  2156. DNS_STATUS
  2157. DnscmdWmi_ProcessResetZoneSecondaries(
  2158. IN LPSTR pszZoneName,
  2159. IN DWORD fSecureSecondaries,
  2160. IN DWORD cSecondaries,
  2161. IN PIP_ADDRESS aipSecondaries,
  2162. IN DWORD fNotifyLevel,
  2163. IN DWORD cNotify,
  2164. IN PIP_ADDRESS aipNotify
  2165. )
  2166. /*++
  2167. Routine Description:
  2168. Send "zone reset secondaries" command to the server to reset
  2169. the zone secondary and notify list parameters.
  2170. Arguments:
  2171. pszZoneName -- zone name
  2172. fSecureSecondaries -- secondary directive (ZONE_SECSECURE_XXX)
  2173. cSecondaries -- count of IP addresses in aipSecondaries
  2174. aipSecondaries -- secondary server IP address array
  2175. fNotifyLevel -- notify directive (ZONE_NOTIFY_XXX)
  2176. cNotify -- count of IP addresses in aipNotify
  2177. aipNotify -- notify server IP address array
  2178. Return Value:
  2179. ERROR_SUCCESS if successful or error code on failure.
  2180. --*/
  2181. {
  2182. DNS_STATUS status = ERROR_SUCCESS;
  2183. BSTR bstrClassName;
  2184. BSTR bstrMethodName;
  2185. PWSTR pwszZoneName = NULL;
  2186. IWbemClassObject * pObj = NULL;
  2187. IWbemClassObject * pClassObj = NULL;
  2188. IWbemClassObject * pInSig = NULL;
  2189. IWbemClassObject * pOutSig = NULL;
  2190. IWbemClassObject * pInParams = NULL;
  2191. IEnumWbemClassObject * pEnum = NULL;
  2192. VARIANT var;
  2193. HRESULT hres;
  2194. SAFEARRAY * psa;
  2195. #if 0
  2196. IWbemClassObject * pServerObj = NULL;
  2197. PWSTR pwszArgs = NULL;
  2198. PWSTR pwszCurrent;
  2199. int len;
  2200. int i;
  2201. #endif
  2202. DNSCMD_CHECK_WMI_ENABLED();
  2203. //
  2204. // Allocate and initialize various stuff.
  2205. //
  2206. VariantInit( &var );
  2207. bstrClassName = SysAllocString( L"MicrosoftDNS_Zone" );
  2208. bstrMethodName = SysAllocString( L"ResetSecondaries" );
  2209. if ( !bstrClassName || !bstrMethodName )
  2210. {
  2211. status = DNS_ERROR_NO_MEMORY;
  2212. goto Done;
  2213. }
  2214. //
  2215. // Get WMI class object for the Zone class.
  2216. //
  2217. hres = g_pIWbemServices->GetObject(
  2218. bstrClassName,
  2219. WBEM_FLAG_RETURN_WBEM_COMPLETE,
  2220. NULL,
  2221. &pClassObj,
  2222. NULL );
  2223. if ( FAILED( hres ) )
  2224. {
  2225. goto Done;
  2226. }
  2227. ASSERT( pClassObj );
  2228. //
  2229. // Get WMI object for specified zone.
  2230. //
  2231. status = getEnumerator( pszZoneName, &pEnum );
  2232. if ( status != ERROR_SUCCESS )
  2233. {
  2234. goto Done;
  2235. }
  2236. status = getNextObjectInEnum( pEnum, &pObj );
  2237. if ( status != ERROR_SUCCESS || !pObj )
  2238. {
  2239. goto Done;
  2240. }
  2241. //
  2242. // Get WMI method signature for ResetSecondaries.
  2243. //
  2244. hres = pClassObj->GetMethod(
  2245. bstrMethodName,
  2246. 0,
  2247. &pInSig,
  2248. &pOutSig );
  2249. if ( FAILED( hres ) )
  2250. {
  2251. goto Done;
  2252. }
  2253. if ( pInSig == NULL )
  2254. {
  2255. status = ERROR_INVALID_PARAMETER;
  2256. goto Done;
  2257. }
  2258. //
  2259. // Create an instance of the method input parameters.
  2260. //
  2261. hres = pInSig->SpawnInstance( 0, &pInParams );
  2262. if ( FAILED( hres ) )
  2263. {
  2264. goto Done;
  2265. }
  2266. ASSERT( pInParams );
  2267. //
  2268. // Set method input parameters.
  2269. //
  2270. printWmiObjectProperties( pInParams );
  2271. {
  2272. BSTR b = NULL;
  2273. pInParams->GetObjectText( 0, &b );
  2274. printf( "\nObjectText:\n%S\n", b );
  2275. }
  2276. VariantClear( &var );
  2277. {
  2278. BSTR bstr = SysAllocString( L"SecureSecondaries" );
  2279. V_VT( &var ) = VT_UI4;
  2280. V_UI4( &var ) = fSecureSecondaries;
  2281. hres = pInParams->Put( bstr, 0, &var, 0 );
  2282. VariantClear( &var );
  2283. }
  2284. #if 0
  2285. V_VT( &var ) = VT_UI4;
  2286. V_UI4( &var ) = fSecureSecondaries;
  2287. hres = pInParams->Put( L"SecureSecondaries", 0, &var, 0 );
  2288. VariantClear( &var );
  2289. #endif
  2290. V_VT( &var ) = VT_UI4;
  2291. V_UI4( &var ) = fNotifyLevel;
  2292. hres = pInParams->Put( L"Notify", 0, &var, 0 );
  2293. VariantClear( &var );
  2294. psa = createSafeArrayForIpList( cSecondaries, aipSecondaries );
  2295. V_VT( &var ) = VT_ARRAY | VT_BSTR;
  2296. V_ARRAY( &var ) = psa;
  2297. hres = pInParams->Put( L"SecondaryServers", 0, &var, 0 );
  2298. VariantClear( &var );
  2299. psa = createSafeArrayForIpList( cNotify, aipNotify );
  2300. V_VT( &var ) = VT_ARRAY | VT_BSTR;
  2301. V_ARRAY( &var ) = psa;
  2302. hres = pInParams->Put( L"NotifyServers", 0, &var, 0 );
  2303. VariantClear( &var );
  2304. //
  2305. // Execute the method.
  2306. //
  2307. hres = g_pIWbemServices->ExecMethod(
  2308. bstrClassName,
  2309. bstrMethodName,
  2310. 0, // flags
  2311. NULL, // context
  2312. pInParams, // input params
  2313. NULL, // output params
  2314. NULL ); // call result
  2315. if ( FAILED( hres ) )
  2316. {
  2317. goto Done;
  2318. }
  2319. //
  2320. // Cleanup and return.
  2321. //
  2322. Done:
  2323. VariantClear( &var );
  2324. FREE_HEAP( pwszZoneName );
  2325. SysFreeString( bstrMethodName );
  2326. SysFreeString( bstrClassName );
  2327. wmiRelease( pEnum );
  2328. wmiRelease( pClassObj );
  2329. wmiRelease( pInSig );
  2330. wmiRelease( pOutSig );
  2331. wmiRelease( pInParams );
  2332. if ( status == ERROR_SUCCESS && FAILED( hres ) )
  2333. {
  2334. status = HRES_TO_STATUS( hres );
  2335. }
  2336. return status;
  2337. } // DnscmdWmi_ProcessResetZoneSecondaries
  2338. //
  2339. // End dnsc_wmi.c
  2340. //