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.

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