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
2973 lines
74 KiB
/*++
|
|
|
|
Copyright (c) 1995-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dnsc_wmi.c
|
|
|
|
Abstract:
|
|
|
|
WMI functions for DNSCMD
|
|
|
|
Author:
|
|
|
|
Jeff Westhead (jwesth) November 2000
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "dnsclip.h"
|
|
#include "dnsc_wmi.h"
|
|
|
|
|
|
#define DNSCMD_CHECK_WMI_ENABLED() \
|
|
if ( !g_UseWmi ) \
|
|
{ \
|
|
ASSERT( g_UseWmi ); \
|
|
printf( "Internal error: WMI is not enabled!\n" ); \
|
|
return ERROR_NOT_SUPPORTED; \
|
|
}
|
|
|
|
#define HRES_TO_STATUS( hres ) ( hres )
|
|
|
|
#define DNS_WMI_NAMESPACE L"ROOT\\MicrosoftDNS"
|
|
#define DNS_WMI_RELPATH L"__RELPATH"
|
|
#define DNS_WMI_TIMEOUT 20000 // timeout in msecs
|
|
|
|
#define DNS_WMI_BLANK_STRING \
|
|
L" "
|
|
|
|
#define MYTEXT2(str) L##str
|
|
#define MYTEXT(str) MYTEXT2(str)
|
|
|
|
|
|
#define wmiRelease( pWmiObject ) \
|
|
if ( pWmiObject ) \
|
|
{ \
|
|
pWmiObject->Release(); \
|
|
pWmiObject = NULL; \
|
|
}
|
|
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
|
|
|
|
IWbemServices * g_pIWbemServices = NULL;
|
|
|
|
|
|
//
|
|
// Static functions
|
|
//
|
|
|
|
|
|
|
|
static DNS_STATUS
|
|
getEnumerator(
|
|
IN PSTR pszZoneName,
|
|
OUT IEnumWbemClassObject ** ppEnum
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrieves WMI object enumerator. The caller must call Release on
|
|
the enum object when done.
|
|
|
|
Arguments:
|
|
|
|
pszZoneName - zone name or NULL for server object
|
|
|
|
ppEnum - ptr to ptr to WMI enumerator
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful or error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
WCHAR wsz[ 1024 ];
|
|
BSTR bstrWQL = NULL;
|
|
BSTR bstrQuery = NULL;
|
|
HRESULT hres = 0;
|
|
|
|
if ( pszZoneName )
|
|
{
|
|
status = StringCchPrintfW(
|
|
wsz,
|
|
sizeofarray( wsz ),
|
|
L"select * from MicrosoftDNS_Zone where Name='%S'",
|
|
pszZoneName );
|
|
}
|
|
else
|
|
{
|
|
status = StringCchPrintfW(
|
|
wsz,
|
|
sizeofarray( wsz ),
|
|
L"select * from MicrosoftDNS_Server" );
|
|
}
|
|
|
|
if ( FAILED( status ) )
|
|
{
|
|
return status;
|
|
}
|
|
|
|
bstrWQL = SysAllocString( L"WQL" );
|
|
bstrQuery = SysAllocString( wsz );
|
|
if ( !bstrWQL || !bstrQuery )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
hres = g_pIWbemServices->ExecQuery(
|
|
bstrWQL,
|
|
bstrQuery,
|
|
WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
|
|
NULL,
|
|
ppEnum );
|
|
if ( FAILED( hres ) )
|
|
{
|
|
status = hres;
|
|
goto Done;
|
|
}
|
|
|
|
Done:
|
|
|
|
SysFreeString( bstrWQL );
|
|
SysFreeString( bstrQuery );
|
|
|
|
return status;
|
|
} // getEnumerator
|
|
|
|
|
|
|
|
static DNS_STATUS
|
|
getRelpath(
|
|
IN IWbemClassObject * pObj,
|
|
OUT VARIANT * pVar
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Loads a VARIANT with the WMI __RELPATH of the object.
|
|
|
|
Arguments:
|
|
|
|
pObj - object to retrieve relpath for
|
|
|
|
pVar - ptr to variant - caller must VariantClear() it later
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful or error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
|
|
if ( pObj == NULL || pVar == NULL )
|
|
{
|
|
status = ERROR_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
VariantClear( pVar );
|
|
HRESULT hres = pObj->Get( DNS_WMI_RELPATH, 0, pVar, NULL, NULL );
|
|
status = hres;
|
|
}
|
|
return status;
|
|
} // getRelpath
|
|
|
|
|
|
|
|
static DNS_STATUS
|
|
getNextObjectInEnum(
|
|
IN IEnumWbemClassObject * pEnum,
|
|
OUT IWbemClassObject ** ppObj,
|
|
IN bool fPrintRelpath = TRUE
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrieves WMI object enumerator. The caller must call Release
|
|
on the class object.
|
|
|
|
When there are no more objects to enumerate this function will
|
|
return a NULL pObj and ERROR_SUCCESS.
|
|
|
|
Arguments:
|
|
|
|
pszZoneName - zone name or NULL for server object
|
|
|
|
ppEnum - ptr to ptr to WMI enumerator
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful or error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
ULONG returnedCount = 0;
|
|
HRESULT hres = 0;
|
|
|
|
if ( !pEnum || !ppObj )
|
|
{
|
|
status = ERROR_INVALID_PARAMETER;
|
|
goto Done;
|
|
}
|
|
|
|
hres = pEnum->Next(
|
|
DNS_WMI_TIMEOUT,
|
|
1, // requested instance count
|
|
ppObj,
|
|
&returnedCount );
|
|
if ( FAILED( hres ) )
|
|
{
|
|
status = ERROR_SUCCESS;
|
|
*ppObj = NULL;
|
|
}
|
|
|
|
if ( *ppObj && fPrintRelpath )
|
|
{
|
|
//
|
|
// Print RELPATH for this object.
|
|
//
|
|
|
|
VARIANT var;
|
|
|
|
status = getRelpath( *ppObj, &var );
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf( "%S\n", V_BSTR( &var ) );
|
|
}
|
|
else
|
|
{
|
|
printf( "WMI error 0x%08X getting RELPATH\n", hres );
|
|
}
|
|
VariantClear( &var );
|
|
}
|
|
|
|
Done:
|
|
|
|
return status;
|
|
} // getNextObjectInEnum
|
|
|
|
|
|
|
|
static SAFEARRAY *
|
|
createSafeArrayForIpList(
|
|
IN DWORD dwIpCount,
|
|
IN PIP_ADDRESS pIpList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates a SAFEARRAY of strings representing a list of IP addresses.
|
|
|
|
Arguments:
|
|
|
|
pIpList - array of IP address DWORDs
|
|
|
|
dwIpCount - number of elements in pIpList
|
|
|
|
Return Value:
|
|
|
|
Safe array on success or NULL or failure.
|
|
|
|
--*/
|
|
{
|
|
if ( !pIpList )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
SAFEARRAYBOUND sabound = { dwIpCount, 0 };
|
|
SAFEARRAY * psa = SafeArrayCreate( VT_BSTR, 1, &sabound );
|
|
for ( ULONG i = 0; i < dwIpCount; ++i )
|
|
{
|
|
PWSTR pwsz = ( PWSTR ) Dns_NameCopyAllocate(
|
|
inet_ntoa(
|
|
*( struct in_addr * )
|
|
&pIpList[ i ] ),
|
|
0,
|
|
DnsCharSetUtf8,
|
|
DnsCharSetUnicode );
|
|
BSTR bstr = SysAllocString( pwsz );
|
|
if ( FAILED( SafeArrayPutElement(
|
|
psa,
|
|
( PLONG ) &i,
|
|
bstr ) ) )
|
|
{
|
|
SafeArrayDestroy( psa );
|
|
psa = NULL;
|
|
}
|
|
SysFreeString( bstr );
|
|
FREE_HEAP( pwsz );
|
|
}
|
|
return psa;
|
|
}
|
|
|
|
|
|
|
|
static SAFEARRAY *
|
|
createSafeArrayForIpArray(
|
|
IN PIP_ARRAY pIpArray
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates a SAFEARRAY of strings representing the IP addresses
|
|
in pIpArray.
|
|
|
|
Arguments:
|
|
|
|
pIpArray - IP array to create string SAFEARRAY for
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful or error code on failure.
|
|
|
|
--*/
|
|
{
|
|
if ( !pIpArray )
|
|
{
|
|
return NULL;
|
|
}
|
|
return createSafeArrayForIpList(
|
|
pIpArray->AddrCount,
|
|
pIpArray->AddrArray );
|
|
}
|
|
|
|
|
|
|
|
PWCHAR
|
|
valueToString(
|
|
CIMTYPE dwType,
|
|
VARIANT *pValue,
|
|
WCHAR **pbuf )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert VARIANT to string. Stole this code from WMI\Samples\VC\UtilLib.
|
|
|
|
Arguments:
|
|
|
|
dwType - value CIMTYPE
|
|
|
|
pValue - value to convert to string
|
|
|
|
**pbuf - ptr to allocated string buffer - caller must free() it
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful or error code on failure.
|
|
|
|
--*/
|
|
{
|
|
#define BLOCKSIZE ( 32 * sizeof( WCHAR ) )
|
|
#define CVTBUFSIZE ( 309 + 40 )
|
|
|
|
DWORD iTotBufSize, iLen;
|
|
|
|
WCHAR *vbuf = NULL;
|
|
WCHAR *buf = NULL;
|
|
|
|
WCHAR lbuf[BLOCKSIZE];
|
|
|
|
switch (pValue->vt)
|
|
{
|
|
|
|
case VT_EMPTY:
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"<empty>");
|
|
break;
|
|
|
|
case VT_NULL:
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"<null>");
|
|
break;
|
|
|
|
case VT_BOOL:
|
|
{
|
|
VARIANT_BOOL b = pValue->boolVal;
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
if (!b) {
|
|
wcscpy(buf, L"FALSE");
|
|
} else {
|
|
wcscpy(buf, L"TRUE");
|
|
}
|
|
break;
|
|
}
|
|
|
|
case VT_I1:
|
|
{
|
|
char b = pValue->bVal;
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
if (b >= 32) {
|
|
swprintf(buf, L"'%c' (%hd, 0x%hX)", b, (signed char)b, b);
|
|
} else {
|
|
swprintf(buf, L"%hd (0x%hX)", (signed char)b, b);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case VT_UI1:
|
|
{
|
|
unsigned char b = pValue->bVal;
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
if (b >= 32) {
|
|
swprintf(buf, L"'%c' (%hu, 0x%hX)", b, (unsigned char)b, b);
|
|
} else {
|
|
swprintf(buf, L"%hu (0x%hX)", (unsigned char)b, b);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case VT_I2:
|
|
{
|
|
SHORT i = pValue->iVal;
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
swprintf(buf, L"%hd (0x%hX)", i, i);
|
|
break;
|
|
}
|
|
|
|
case VT_UI2:
|
|
{
|
|
USHORT i = pValue->uiVal;
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
swprintf(buf, L"%hu (0x%hX)", i, i);
|
|
break;
|
|
}
|
|
|
|
case VT_I4:
|
|
{
|
|
LONG l = pValue->lVal;
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
swprintf(buf, L"%d (0x%X)", l, l);
|
|
break;
|
|
}
|
|
|
|
case VT_UI4:
|
|
{
|
|
ULONG l = pValue->ulVal;
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
swprintf(buf, L"%u (0x%X)", l, l);
|
|
break;
|
|
}
|
|
|
|
case VT_R4:
|
|
{
|
|
float f = pValue->fltVal;
|
|
buf = (WCHAR *)malloc(CVTBUFSIZE * sizeof(WCHAR));
|
|
if ( !buf ) goto AllocFailed;
|
|
swprintf(buf, L"%10.4f", f);
|
|
break;
|
|
}
|
|
|
|
case VT_R8:
|
|
{
|
|
double d = pValue->dblVal;
|
|
buf = (WCHAR *)malloc(CVTBUFSIZE * sizeof(WCHAR));
|
|
if ( !buf ) goto AllocFailed;
|
|
swprintf(buf, L"%10.4f", d);
|
|
break;
|
|
}
|
|
|
|
case VT_BSTR:
|
|
{
|
|
if (dwType == CIM_SINT64)
|
|
{
|
|
// a little redundant, but it makes me feel better
|
|
LPWSTR pWStr = pValue->bstrVal;
|
|
__int64 l = _wtoi64(pWStr);
|
|
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
swprintf(buf, L"%I64d", l);
|
|
}
|
|
else if (dwType == CIM_UINT64)
|
|
{
|
|
// a little redundant, but it makes me feel better
|
|
LPWSTR pWStr = pValue->bstrVal;
|
|
__int64 l = _wtoi64(pWStr);
|
|
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
swprintf(buf, L"%I64u", l);
|
|
}
|
|
else // string, datetime, reference
|
|
{
|
|
LPWSTR pWStr = pValue->bstrVal;
|
|
buf = (WCHAR *)malloc((wcslen(pWStr) * sizeof(WCHAR)) + sizeof(WCHAR) + (2 * sizeof(WCHAR)));
|
|
if ( !buf ) goto AllocFailed;
|
|
swprintf(buf, L"%wS", pWStr);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case VT_BOOL|VT_ARRAY:
|
|
{
|
|
SAFEARRAY *pVec = pValue->parray;
|
|
long iLBound, iUBound;
|
|
BOOL bFirst = TRUE;
|
|
|
|
SafeArrayGetLBound(pVec, 1, &iLBound);
|
|
SafeArrayGetUBound(pVec, 1, &iUBound);
|
|
if ((iUBound - iLBound + 1) == 0) {
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"<empty array>");
|
|
break;
|
|
}
|
|
|
|
buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"");
|
|
|
|
for (long i = iLBound; i <= iUBound; i++) {
|
|
if (!bFirst) {
|
|
wcscat(buf, L",");
|
|
} else {
|
|
bFirst = FALSE;
|
|
}
|
|
|
|
VARIANT_BOOL v;
|
|
SafeArrayGetElement(pVec, &i, &v);
|
|
if (v) {
|
|
wcscat(buf, L"TRUE");
|
|
} else {
|
|
wcscat(buf, L"FALSE");
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case VT_I1|VT_ARRAY:
|
|
{
|
|
SAFEARRAY *pVec = pValue->parray;
|
|
long iLBound, iUBound;
|
|
BOOL bFirst = TRUE;
|
|
|
|
SafeArrayGetLBound(pVec, 1, &iLBound);
|
|
SafeArrayGetUBound(pVec, 1, &iUBound);
|
|
if ((iUBound - iLBound + 1) == 0) {
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"<empty array>");
|
|
break;
|
|
}
|
|
|
|
buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"");
|
|
WCHAR *pos = buf;
|
|
DWORD len;
|
|
|
|
BYTE *pbstr;
|
|
SafeArrayAccessData(pVec, (void HUGEP* FAR*)&pbstr);
|
|
|
|
for (long i = iLBound; i <= iUBound; i++) {
|
|
if (!bFirst) {
|
|
wcscpy(pos, L",");
|
|
pos += 1;
|
|
} else {
|
|
bFirst = FALSE;
|
|
}
|
|
|
|
char v;
|
|
// SafeArrayGetElement(pVec, &i, &v);
|
|
v = pbstr[i];
|
|
|
|
if (v < 32) {
|
|
len = swprintf(lbuf, L"%hd (0x%X)", v, v);
|
|
} else {
|
|
len = swprintf(lbuf, L"'%c' %hd (0x%X)", v, v, v);
|
|
}
|
|
|
|
wcscpy(pos, lbuf);
|
|
pos += len;
|
|
|
|
}
|
|
|
|
SafeArrayUnaccessData(pVec);
|
|
|
|
break;
|
|
}
|
|
|
|
case VT_UI1|VT_ARRAY:
|
|
{
|
|
SAFEARRAY *pVec = pValue->parray;
|
|
long iLBound, iUBound;
|
|
BOOL bFirst = TRUE;
|
|
|
|
SafeArrayGetLBound(pVec, 1, &iLBound);
|
|
SafeArrayGetUBound(pVec, 1, &iUBound);
|
|
if ((iUBound - iLBound + 1) == 0) {
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"<empty array>");
|
|
break;
|
|
}
|
|
|
|
buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"");
|
|
WCHAR *pos = buf;
|
|
DWORD len;
|
|
|
|
BYTE *pbstr;
|
|
SafeArrayAccessData(pVec, (void HUGEP* FAR*)&pbstr);
|
|
|
|
for (long i = iLBound; i <= iUBound; i++) {
|
|
if (!bFirst) {
|
|
wcscpy(pos, L",");
|
|
pos += 1;
|
|
} else {
|
|
bFirst = FALSE;
|
|
}
|
|
|
|
unsigned char v;
|
|
// SafeArrayGetElement(pVec, &i, &v);
|
|
v = pbstr[i];
|
|
|
|
if (v < 32) {
|
|
len = swprintf(lbuf, L"%hu (0x%X)", v, v);
|
|
} else {
|
|
len = swprintf(lbuf, L"'%c' %hu (0x%X)", v, v, v);
|
|
}
|
|
|
|
wcscpy(pos, lbuf);
|
|
pos += len;
|
|
|
|
}
|
|
|
|
SafeArrayUnaccessData(pVec);
|
|
|
|
break;
|
|
}
|
|
|
|
case VT_I2|VT_ARRAY:
|
|
{
|
|
SAFEARRAY *pVec = pValue->parray;
|
|
long iLBound, iUBound;
|
|
BOOL bFirst = TRUE;
|
|
|
|
SafeArrayGetLBound(pVec, 1, &iLBound);
|
|
SafeArrayGetUBound(pVec, 1, &iUBound);
|
|
if ((iUBound - iLBound + 1) == 0) {
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"<empty array>");
|
|
break;
|
|
}
|
|
|
|
buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"");
|
|
|
|
for (long i = iLBound; i <= iUBound; i++) {
|
|
if (!bFirst) {
|
|
wcscat(buf, L",");
|
|
} else {
|
|
bFirst = FALSE;
|
|
}
|
|
|
|
SHORT v;
|
|
SafeArrayGetElement(pVec, &i, &v);
|
|
swprintf(lbuf, L"%hd", v);
|
|
wcscat(buf, lbuf);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case VT_UI2|VT_ARRAY:
|
|
{
|
|
SAFEARRAY *pVec = pValue->parray;
|
|
long iLBound, iUBound;
|
|
BOOL bFirst = TRUE;
|
|
|
|
SafeArrayGetLBound(pVec, 1, &iLBound);
|
|
SafeArrayGetUBound(pVec, 1, &iUBound);
|
|
if ((iUBound - iLBound + 1) == 0) {
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"<empty array>");
|
|
break;
|
|
}
|
|
|
|
buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"");
|
|
|
|
for (long i = iLBound; i <= iUBound; i++) {
|
|
if (!bFirst) {
|
|
wcscat(buf, L",");
|
|
} else {
|
|
bFirst = FALSE;
|
|
}
|
|
|
|
USHORT v;
|
|
SafeArrayGetElement(pVec, &i, &v);
|
|
swprintf(lbuf, L"%hu", v);
|
|
wcscat(buf, lbuf);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case VT_I4|VT_ARRAY:
|
|
{
|
|
SAFEARRAY *pVec = pValue->parray;
|
|
long iLBound, iUBound;
|
|
BOOL bFirst = TRUE;
|
|
|
|
SafeArrayGetLBound(pVec, 1, &iLBound);
|
|
SafeArrayGetUBound(pVec, 1, &iUBound);
|
|
if ((iUBound - iLBound + 1) == 0) {
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"<empty array>");
|
|
break;
|
|
}
|
|
|
|
buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"");
|
|
|
|
for (long i = iLBound; i <= iUBound; i++) {
|
|
if (!bFirst) {
|
|
wcscat(buf, L",");
|
|
} else {
|
|
bFirst = FALSE;
|
|
}
|
|
|
|
LONG v;
|
|
SafeArrayGetElement(pVec, &i, &v);
|
|
_ltow(v, lbuf, 10);
|
|
wcscat(buf, lbuf);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case VT_UI4|VT_ARRAY:
|
|
{
|
|
SAFEARRAY *pVec = pValue->parray;
|
|
long iLBound, iUBound;
|
|
BOOL bFirst = TRUE;
|
|
|
|
SafeArrayGetLBound(pVec, 1, &iLBound);
|
|
SafeArrayGetUBound(pVec, 1, &iUBound);
|
|
if ((iUBound - iLBound + 1) == 0) {
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"<empty array>");
|
|
break;
|
|
}
|
|
|
|
buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"");
|
|
|
|
for (long i = iLBound; i <= iUBound; i++) {
|
|
if (!bFirst) {
|
|
wcscat(buf, L",");
|
|
} else {
|
|
bFirst = FALSE;
|
|
}
|
|
|
|
ULONG v;
|
|
SafeArrayGetElement(pVec, &i, &v);
|
|
_ultow(v, lbuf, 10);
|
|
wcscat(buf, lbuf);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case CIM_REAL32|VT_ARRAY:
|
|
{
|
|
SAFEARRAY *pVec = pValue->parray;
|
|
long iLBound, iUBound;
|
|
BOOL bFirst = TRUE;
|
|
|
|
SafeArrayGetLBound(pVec, 1, &iLBound);
|
|
SafeArrayGetUBound(pVec, 1, &iUBound);
|
|
if ((iUBound - iLBound + 1) == 0) {
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"<empty array>");
|
|
break;
|
|
}
|
|
|
|
buf = (WCHAR *)malloc((iUBound - iLBound + 1) * (CVTBUFSIZE * sizeof(WCHAR)));
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"");
|
|
|
|
for (long i = iLBound; i <= iUBound; i++) {
|
|
if (!bFirst) {
|
|
wcscat(buf, L",");
|
|
} else {
|
|
bFirst = FALSE;
|
|
}
|
|
|
|
FLOAT v;
|
|
SafeArrayGetElement(pVec, &i, &v);
|
|
swprintf(lbuf, L"%10.4f", v);
|
|
wcscat(buf, lbuf);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case CIM_REAL64|VT_ARRAY:
|
|
{
|
|
SAFEARRAY *pVec = pValue->parray;
|
|
long iLBound, iUBound;
|
|
BOOL bFirst = TRUE;
|
|
|
|
SafeArrayGetLBound(pVec, 1, &iLBound);
|
|
SafeArrayGetUBound(pVec, 1, &iUBound);
|
|
if ((iUBound - iLBound + 1) == 0) {
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"<empty array>");
|
|
break;
|
|
}
|
|
|
|
buf = (WCHAR *)malloc((iUBound - iLBound + 1) * (CVTBUFSIZE * sizeof(WCHAR)));
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"");
|
|
|
|
for (long i = iLBound; i <= iUBound; i++) {
|
|
if (!bFirst) {
|
|
wcscat(buf, L",");
|
|
} else {
|
|
bFirst = FALSE;
|
|
}
|
|
|
|
double v;
|
|
SafeArrayGetElement(pVec, &i, &v);
|
|
swprintf(lbuf, L"%10.4f", v);
|
|
wcscat(buf, lbuf);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case VT_BSTR|VT_ARRAY:
|
|
{
|
|
|
|
if (dwType == (CIM_UINT64|VT_ARRAY))
|
|
{
|
|
SAFEARRAY *pVec = pValue->parray;
|
|
long iLBound, iUBound;
|
|
BOOL bFirst = TRUE;
|
|
|
|
SafeArrayGetLBound(pVec, 1, &iLBound);
|
|
SafeArrayGetUBound(pVec, 1, &iUBound);
|
|
if ((iUBound - iLBound + 1) == 0) {
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"<empty array>");
|
|
break;
|
|
}
|
|
|
|
buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"");
|
|
|
|
for (long i = iLBound; i <= iUBound; i++) {
|
|
if (!bFirst) {
|
|
wcscat(buf, L",");
|
|
} else {
|
|
bFirst = FALSE;
|
|
}
|
|
|
|
BSTR v = NULL;
|
|
|
|
SafeArrayGetElement(pVec, &i, &v);
|
|
|
|
swprintf(lbuf, L"%I64u", _wtoi64(v));
|
|
wcscat(buf, lbuf);
|
|
}
|
|
}
|
|
else if (dwType == (CIM_SINT64|VT_ARRAY))
|
|
{
|
|
SAFEARRAY *pVec = pValue->parray;
|
|
long iLBound, iUBound;
|
|
BOOL bFirst = TRUE;
|
|
|
|
SafeArrayGetLBound(pVec, 1, &iLBound);
|
|
SafeArrayGetUBound(pVec, 1, &iUBound);
|
|
if ((iUBound - iLBound + 1) == 0) {
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"<empty array>");
|
|
break;
|
|
}
|
|
|
|
buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"");
|
|
|
|
for (long i = iLBound; i <= iUBound; i++) {
|
|
if (!bFirst) {
|
|
wcscat(buf, L",");
|
|
} else {
|
|
bFirst = FALSE;
|
|
}
|
|
|
|
BSTR v = NULL;
|
|
|
|
SafeArrayGetElement(pVec, &i, &v);
|
|
|
|
swprintf(lbuf, L"%I64d", _wtoi64(v));
|
|
wcscat(buf, lbuf);
|
|
}
|
|
}
|
|
else // string, datetime, reference
|
|
{
|
|
|
|
SAFEARRAY *pVec = pValue->parray;
|
|
long iLBound, iUBound;
|
|
DWORD iNeed;
|
|
DWORD iVSize;
|
|
DWORD iCurBufSize;
|
|
|
|
SafeArrayGetLBound(pVec, 1, &iLBound);
|
|
SafeArrayGetUBound(pVec, 1, &iUBound);
|
|
if ((iUBound - iLBound + 1) == 0) {
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"<empty array>");
|
|
break;
|
|
}
|
|
|
|
iTotBufSize = (iUBound - iLBound + 1) * BLOCKSIZE;
|
|
buf = (WCHAR *)malloc(iTotBufSize);
|
|
if ( !buf ) goto AllocFailed;
|
|
buf[0] = L'\0';
|
|
iCurBufSize = 0;
|
|
iVSize = BLOCKSIZE;
|
|
vbuf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !vbuf ) goto AllocFailed;
|
|
|
|
for (long i = iLBound; i <= iUBound; i++) {
|
|
BSTR v = NULL;
|
|
WCHAR * newbuf = NULL;
|
|
|
|
SafeArrayGetElement(pVec, &i, &v);
|
|
iLen = (wcslen(v) + 1) * sizeof(WCHAR);
|
|
if (iLen > iVSize) {
|
|
newbuf = (WCHAR *)realloc(vbuf, iLen + sizeof(WCHAR));
|
|
if ( !newbuf ) goto AllocFailed;
|
|
vbuf = newbuf;
|
|
iVSize = iLen;
|
|
}
|
|
|
|
// String size + (quotes + comma + null)
|
|
iNeed = (swprintf(vbuf, L"%wS", v) + 4) * sizeof(WCHAR);
|
|
if (iNeed + iCurBufSize > iTotBufSize) {
|
|
iTotBufSize += (iNeed * 2); // Room enough for 2 more entries
|
|
newbuf = (WCHAR *)realloc(buf, iTotBufSize);
|
|
if ( !newbuf ) goto AllocFailed;
|
|
buf = newbuf;
|
|
}
|
|
wcscat(buf, L"\"");
|
|
wcscat(buf, vbuf);
|
|
if (i + 1 <= iUBound)
|
|
{
|
|
wcscat(buf, L"\",");
|
|
} else
|
|
{
|
|
wcscat(buf, L"\"");
|
|
}
|
|
iCurBufSize += iNeed;
|
|
SysFreeString(v);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if ( !buf ) goto AllocFailed;
|
|
wcscpy(buf, L"<conversion error>");
|
|
break;
|
|
}
|
|
}
|
|
|
|
AllocFailed:
|
|
|
|
if ( vbuf )
|
|
{
|
|
free( vbuf );
|
|
}
|
|
|
|
*pbuf = buf;
|
|
return buf;
|
|
} // valueToString
|
|
|
|
|
|
DNS_STATUS
|
|
printWmiObjectProperties(
|
|
IWbemClassObject * pObj
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
HRESULT hres = 0;
|
|
SAFEARRAY * pNames = NULL;
|
|
BSTR bstrPropName = NULL;
|
|
VARIANT var;
|
|
BSTR bstrCimType = SysAllocString( L"CIMTYPE" );
|
|
PWSTR pwszVal = NULL;
|
|
|
|
if ( !bstrCimType )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
VariantClear( &var );
|
|
|
|
//
|
|
// Get the RELPATH for this object.
|
|
//
|
|
|
|
status = getRelpath( pObj, &var );
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
goto Done;
|
|
}
|
|
printf( "%S\n\n", V_BSTR( &var ) );
|
|
|
|
//
|
|
// Enumerate all properties of this object.
|
|
//
|
|
|
|
hres = pObj->GetNames(
|
|
NULL, // qualifier
|
|
WBEM_FLAG_ALWAYS | WBEM_FLAG_NONSYSTEM_ONLY,
|
|
NULL, // qualifier value
|
|
&pNames );
|
|
if ( FAILED( hres ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
ASSERT( pNames );
|
|
|
|
long lowerBound;
|
|
long upperBound;
|
|
SafeArrayGetLBound( pNames, 1, &lowerBound );
|
|
SafeArrayGetUBound( pNames, 1, &upperBound );
|
|
|
|
for ( long i = lowerBound; i <= upperBound; ++i )
|
|
{
|
|
//
|
|
// Print the name and type of this property value.
|
|
//
|
|
|
|
hres = SafeArrayGetElement( pNames, &i, &bstrPropName );
|
|
if ( !SUCCEEDED( hres ) )
|
|
{
|
|
ASSERT( SUCCEEDED( hres ) );
|
|
continue;
|
|
}
|
|
|
|
IWbemQualifierSet * pQualSet = NULL;
|
|
hres = pObj->GetPropertyQualifierSet( bstrPropName, &pQualSet );
|
|
if ( !SUCCEEDED( hres ) )
|
|
{
|
|
ASSERT( SUCCEEDED( hres ) );
|
|
continue;
|
|
}
|
|
|
|
VariantClear( &var );
|
|
pQualSet->Get( bstrCimType, 0, &var, NULL );
|
|
if ( !SUCCEEDED( hres ) )
|
|
{
|
|
ASSERT( SUCCEEDED( hres ) );
|
|
continue;
|
|
}
|
|
|
|
int padlen = 30 - wcslen( bstrPropName ) - wcslen( V_BSTR( &var ) );
|
|
printf(
|
|
"%S (%S) %.*S = ",
|
|
bstrPropName,
|
|
V_BSTR( &var ),
|
|
padlen > 0 ? padlen : 0,
|
|
DNS_WMI_BLANK_STRING );
|
|
|
|
//
|
|
// Print the property value.
|
|
//
|
|
|
|
VariantClear( &var );
|
|
CIMTYPE cimType = 0;
|
|
hres = pObj->Get( bstrPropName, 0, &var, &cimType, NULL );
|
|
if ( !SUCCEEDED( hres ) )
|
|
{
|
|
ASSERT( SUCCEEDED( hres ) );
|
|
continue;
|
|
}
|
|
|
|
printf( "%S\n", valueToString( cimType, &var, &pwszVal ) );
|
|
free( pwszVal );
|
|
pwszVal = NULL;
|
|
}
|
|
|
|
Done:
|
|
|
|
free( pwszVal );
|
|
SysFreeString( bstrCimType );
|
|
SafeArrayDestroy( pNames );
|
|
|
|
if ( status == ERROR_SUCCESS && FAILED( hres ) )
|
|
{
|
|
status = HRES_TO_STATUS( hres );
|
|
}
|
|
|
|
return status;
|
|
} // printWmiObjectProperties
|
|
|
|
|
|
//
|
|
// External functions
|
|
//
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
DnscmdWmi_Initialize(
|
|
IN PWSTR pwszServerName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Setup mod buffer for max count of items.
|
|
|
|
Arguments:
|
|
|
|
pwszServerName -- IP address or name of target server
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful or error code on failure.
|
|
|
|
--*/
|
|
{
|
|
static const char * fn = "DnscmdWmi_Initialize";
|
|
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
HRESULT hres = 0;
|
|
IWbemLocator * pIWbemLocator = NULL;
|
|
BSTR bstrNamespace = NULL;
|
|
IWbemServices * pIWbemServices = NULL;
|
|
WCHAR wsz[ 1024 ];
|
|
|
|
DNSCMD_CHECK_WMI_ENABLED();
|
|
|
|
//
|
|
// Initialize COM.
|
|
//
|
|
|
|
if ( FAILED( hres = CoInitialize( NULL ) ) )
|
|
{
|
|
printf( "%s: CoInitialize returned 0x%08X\n", fn, hres );
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Initialize security.
|
|
//
|
|
|
|
hres = CoInitializeSecurity(
|
|
NULL, // permissions
|
|
-1, // auth service count
|
|
NULL, // auth services
|
|
NULL, // reserved
|
|
RPC_C_AUTHZ_NONE,
|
|
RPC_C_IMP_LEVEL_IMPERSONATE,
|
|
NULL, // auth list
|
|
0, // capabilities
|
|
0 ); // reserved
|
|
if ( FAILED( hres ) )
|
|
{
|
|
printf(
|
|
"%s: CoInitializeSecurity() returned 0x%08X\n",
|
|
fn,
|
|
hres );
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Create instance of WbemLocator interface.
|
|
//
|
|
|
|
hres = CoCreateInstance(
|
|
CLSID_WbemLocator,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IWbemLocator,
|
|
( LPVOID * ) &pIWbemLocator );
|
|
if ( FAILED( hres ) )
|
|
{
|
|
printf(
|
|
"%s: CoCreateInstance( CLSID_WbemLocator ) returned 0x%08X\n",
|
|
fn,
|
|
hres );
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Connect to MicrosoftDNS namespace on server.
|
|
//
|
|
|
|
wsprintfW(
|
|
wsz,
|
|
L"\\\\%s\\%s",
|
|
pwszServerName,
|
|
DNS_WMI_NAMESPACE );
|
|
bstrNamespace = SysAllocString( wsz );
|
|
if ( !bstrNamespace )
|
|
{
|
|
ASSERT( bstrNamespace );
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
hres = pIWbemLocator->ConnectServer(
|
|
bstrNamespace,
|
|
NULL, // user id
|
|
NULL, // password
|
|
NULL, // locale
|
|
0, // security flags
|
|
NULL, // domain
|
|
NULL, // context
|
|
&pIWbemServices );
|
|
if ( FAILED( hres ) )
|
|
{
|
|
printf(
|
|
"%s: ConnectServer( %S ) returned 0x%08X\n",
|
|
fn,
|
|
DNS_WMI_NAMESPACE,
|
|
hres );
|
|
goto Done;
|
|
}
|
|
|
|
if ( !pIWbemServices )
|
|
{
|
|
ASSERT( pIWbemServices );
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Set security.
|
|
//
|
|
|
|
hres = CoSetProxyBlanket(
|
|
pIWbemServices,
|
|
RPC_C_AUTHN_WINNT,
|
|
RPC_C_AUTHZ_NONE,
|
|
NULL, // principal name
|
|
RPC_C_AUTHN_LEVEL_CALL,
|
|
RPC_C_IMP_LEVEL_IMPERSONATE,
|
|
NULL, // client identify
|
|
EOAC_NONE );
|
|
if ( FAILED( hres ) )
|
|
{
|
|
printf(
|
|
"%s: CoSetProxyBlanket() returned 0x%08X\n",
|
|
fn,
|
|
hres );
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Cleanup and return.
|
|
//
|
|
|
|
Done:
|
|
|
|
SysFreeString( bstrNamespace );
|
|
|
|
if ( pIWbemLocator )
|
|
{
|
|
pIWbemLocator->Release();
|
|
}
|
|
|
|
if ( status == ERROR_SUCCESS && FAILED( hres ) )
|
|
{
|
|
status = HRES_TO_STATUS( hres );
|
|
}
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
g_pIWbemServices = pIWbemServices;
|
|
}
|
|
|
|
return status;
|
|
} // DnscmdWmi_Initialize
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
DnscmdWmi_Free(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Close WMI session and free globals.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DBG_FN( "DnscmdWmi_Free" )
|
|
|
|
DNSCMD_CHECK_WMI_ENABLED();
|
|
|
|
if ( g_pIWbemServices )
|
|
{
|
|
g_pIWbemServices->Release();
|
|
g_pIWbemServices = NULL;
|
|
}
|
|
|
|
CoUninitialize();
|
|
|
|
return ERROR_SUCCESS;
|
|
} // DnscmdWmi_Free
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
DnscmdWmi_ProcessDnssrvQuery(
|
|
IN PSTR pszZoneName,
|
|
IN PCSTR pszQuery
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Perform query.
|
|
|
|
Arguments:
|
|
|
|
pszZoneName -- zone name or NULL for server level query
|
|
|
|
pszQuery -- query name
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful or error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
BSTR bstrClassName = NULL;
|
|
IEnumWbemClassObject * pEnum = NULL;
|
|
IWbemClassObject * pObj = NULL;
|
|
ULONG returnedCount = 1;
|
|
|
|
DNSCMD_CHECK_WMI_ENABLED();
|
|
|
|
//
|
|
// Get WMI object.
|
|
//
|
|
|
|
status = getEnumerator( pszZoneName, &pEnum );
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
status = getNextObjectInEnum( pEnum, &pObj );
|
|
if ( status != ERROR_SUCCESS || !pObj )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
printWmiObjectProperties( pObj );
|
|
|
|
//
|
|
// Cleanup and return.
|
|
//
|
|
|
|
Done:
|
|
|
|
SysFreeString( bstrClassName );
|
|
|
|
if ( pObj )
|
|
{
|
|
pObj->Release();
|
|
}
|
|
|
|
if ( pEnum )
|
|
{
|
|
pEnum->Release();
|
|
}
|
|
|
|
return status;
|
|
} // DnscmdWmi_ProcessDnssrvQuery
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
DnscmdWmi_ProcessEnumZones(
|
|
IN DWORD dwFilter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enumerate zones.
|
|
|
|
Arguments:
|
|
|
|
dwFilter -- filter
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful or error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
BSTR bstrClassName = NULL;
|
|
IEnumWbemClassObject * pEnum = NULL;
|
|
IWbemClassObject * pObj = NULL;
|
|
HRESULT hres = 0;
|
|
ULONG returnedCount = 1;
|
|
|
|
DNSCMD_CHECK_WMI_ENABLED();
|
|
|
|
//
|
|
// Create zone enumerator.
|
|
//
|
|
|
|
bstrClassName = SysAllocString( L"MicrosoftDNS_Zone" );
|
|
if ( !bstrClassName )
|
|
{
|
|
ASSERT( bstrClassName );
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
hres = g_pIWbemServices->CreateInstanceEnum(
|
|
bstrClassName,
|
|
0, // flags
|
|
NULL, // context
|
|
&pEnum );
|
|
if ( FAILED( hres ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
ASSERT( pEnum );
|
|
|
|
//
|
|
// Enumerate zones.
|
|
//
|
|
|
|
while ( returnedCount == 1 )
|
|
{
|
|
VARIANT val;
|
|
CIMTYPE cimtype = 0;
|
|
PWSTR pwszVal = NULL;
|
|
|
|
VariantInit( &val );
|
|
|
|
status = getNextObjectInEnum( pEnum, &pObj, FALSE );
|
|
if ( status != ERROR_SUCCESS || !pObj )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Print properties for this zone.
|
|
//
|
|
|
|
#define CHECK_HRES( hresult, propname ) \
|
|
if ( FAILED( hresult ) ) \
|
|
{ \
|
|
printf( "\n\nWMI error 0x%08X reading property %S!\n", \
|
|
hresult, propname ); \
|
|
goto Done; \
|
|
}
|
|
|
|
hres = pObj->Get( L"Name", 0, &val, &cimtype, NULL );
|
|
CHECK_HRES( hres, L"Name" );
|
|
printf( " %-29S", valueToString( cimtype, &val, &pwszVal ) );
|
|
free( pwszVal );
|
|
VariantClear( &val );
|
|
|
|
hres = pObj->Get( L"ZoneType", 0, &val, &cimtype, NULL );
|
|
CHECK_HRES( hres, L"ZoneType" );
|
|
ASSERT( val.vt == VT_I4 );
|
|
printf( "%3d ", val.lVal );
|
|
VariantClear( &val );
|
|
|
|
hres = pObj->Get( L"DsIntegrated", 0, &val, &cimtype, NULL );
|
|
CHECK_HRES( hres, L"DsIntegrated" );
|
|
ASSERT( val.vt == VT_BOOL );
|
|
printf( "%-4S ", val.boolVal ? L"DS" : L"file" );
|
|
VariantClear( &val );
|
|
|
|
hres = pObj->Get( L"Reverse", 0, &val, &cimtype, NULL );
|
|
CHECK_HRES( hres, L"Reverse" );
|
|
ASSERT( val.vt == VT_BOOL );
|
|
printf( "%-3S ", val.boolVal ? L"Rev" : L"" );
|
|
VariantClear( &val );
|
|
|
|
hres = pObj->Get( L"AutoCreated", 0, &val, &cimtype, NULL );
|
|
CHECK_HRES( hres, L"AutoCreated" );
|
|
ASSERT( val.vt == VT_BOOL );
|
|
printf( "%-4S ", val.boolVal ? L"Auto" : L"" );
|
|
VariantClear( &val );
|
|
|
|
hres = pObj->Get( L"AllowUpdate", 0, &val, &cimtype, NULL );
|
|
CHECK_HRES( hres, L"AllowUpdate" );
|
|
ASSERT( val.vt == VT_BOOL );
|
|
printf( "Up=%d ", val.boolVal ? 1 : 0 );
|
|
VariantClear( &val );
|
|
|
|
hres = pObj->Get( L"Aging", 0, &val, &cimtype, NULL );
|
|
CHECK_HRES( hres, L"Aging" );
|
|
ASSERT( val.vt == VT_BOOL );
|
|
printf( "%-5S ", val.boolVal ? L"Aging" : L"" );
|
|
VariantClear( &val );
|
|
|
|
hres = pObj->Get( L"Paused", 0, &val, &cimtype, NULL );
|
|
CHECK_HRES( hres, L"Paused" );
|
|
ASSERT( val.vt == VT_BOOL );
|
|
printf( "%-6S ", val.boolVal ? L"Paused" : L"" );
|
|
VariantClear( &val );
|
|
|
|
hres = pObj->Get( L"Shutdown", 0, &val, &cimtype, NULL );
|
|
CHECK_HRES( hres, L"Shutdown" );
|
|
ASSERT( val.vt == VT_BOOL );
|
|
printf( "%-6S", val.boolVal ? L"Shutdn" : L"" );
|
|
VariantClear( &val );
|
|
|
|
printf( "\n\n" );
|
|
}
|
|
|
|
//
|
|
// Cleanup and return.
|
|
//
|
|
|
|
Done:
|
|
|
|
SysFreeString( bstrClassName );
|
|
|
|
if ( pObj )
|
|
{
|
|
pObj->Release();
|
|
}
|
|
|
|
if ( pEnum )
|
|
{
|
|
pEnum->Release();
|
|
}
|
|
|
|
if ( status == ERROR_SUCCESS && FAILED( hres ) )
|
|
{
|
|
status = HRES_TO_STATUS( hres );
|
|
}
|
|
|
|
return status;
|
|
} // DnscmdWmi_ProcessEnumZones
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
DnscmdWmi_ProcessZoneInfo(
|
|
IN LPSTR pszZone
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enumerate zones.
|
|
|
|
Arguments:
|
|
|
|
dwFilter -- filter
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful or error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
IWbemClassObject * pObj = NULL;
|
|
IEnumWbemClassObject * pEnum = NULL;
|
|
ULONG returnedCount = 1;
|
|
WCHAR wsz[ 1024 ];
|
|
|
|
DNSCMD_CHECK_WMI_ENABLED();
|
|
|
|
//
|
|
// Get WMI object.
|
|
//
|
|
|
|
status = getEnumerator( pszZone, &pEnum );
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
status = getNextObjectInEnum( pEnum, &pObj, FALSE );
|
|
if ( status != ERROR_SUCCESS || !pObj )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
printWmiObjectProperties( pObj );
|
|
|
|
//
|
|
// Cleanup and return.
|
|
//
|
|
|
|
Done:
|
|
|
|
if ( pObj )
|
|
{
|
|
pObj->Release();
|
|
}
|
|
|
|
if ( pEnum )
|
|
{
|
|
pEnum->Release();
|
|
}
|
|
|
|
return status;
|
|
} // DnscmdWmi_ProcessZoneInfo
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
DnscmdWmi_ProcessEnumRecords(
|
|
IN LPSTR pszZone,
|
|
IN LPSTR pszNode,
|
|
IN BOOL fDetail,
|
|
IN DWORD dwFlags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enumerate Records.
|
|
|
|
Arguments:
|
|
|
|
pszZone -- zone name
|
|
|
|
pszNode -- name of root node to at which to enumerate records
|
|
|
|
fDetail -- print summary or full detail
|
|
|
|
dwFlags -- search flags
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful or error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
BSTR bstrWQL = NULL;
|
|
BSTR bstrQuery = NULL;
|
|
IWbemClassObject * pObj = NULL;
|
|
IEnumWbemClassObject * pEnum = NULL;
|
|
HRESULT hres = 0;
|
|
ULONG returnedCount = 1;
|
|
WCHAR wsz[ 1024 ];
|
|
|
|
DNSCMD_CHECK_WMI_ENABLED();
|
|
|
|
//
|
|
// Query for zone.
|
|
//
|
|
|
|
if ( pszNode == NULL || strcmp( pszNode, "@" ) == 0 )
|
|
{
|
|
wsprintfW(
|
|
wsz,
|
|
L"select * from MicrosoftDNS_ResourceRecord "
|
|
L"where ContainerName='%S'",
|
|
pszZone );
|
|
}
|
|
else
|
|
{
|
|
wsprintfW(
|
|
wsz,
|
|
L"select * from MicrosoftDNS_ResourceRecord "
|
|
L"where DomainName='%S'",
|
|
pszNode );
|
|
}
|
|
bstrWQL = SysAllocString( L"WQL" );
|
|
bstrQuery = SysAllocString( wsz );
|
|
if ( !bstrWQL || !bstrQuery )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
hres = g_pIWbemServices->ExecQuery(
|
|
bstrWQL,
|
|
bstrQuery,
|
|
WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
|
|
NULL,
|
|
&pEnum );
|
|
if ( FAILED( hres ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
ASSERT( pEnum );
|
|
|
|
//
|
|
// Dump results.
|
|
//
|
|
|
|
while ( 1 )
|
|
{
|
|
status = getNextObjectInEnum( pEnum, &pObj );
|
|
if ( status != ERROR_SUCCESS || !pObj )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( fDetail )
|
|
{
|
|
printWmiObjectProperties( pObj );
|
|
}
|
|
else
|
|
{
|
|
VARIANT val;
|
|
CIMTYPE cimtype = 0;
|
|
PWSTR pwszVal = NULL;
|
|
|
|
VariantInit( &val );
|
|
hres = pObj->Get( L"TextRepresentation", 0, &val, &cimtype, NULL );
|
|
CHECK_HRES( hres, L"TextRepresentation" );
|
|
printf( "%S", valueToString( cimtype, &val, &pwszVal ) );
|
|
free( pwszVal );
|
|
VariantClear( &val );
|
|
|
|
printf( "\n" );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup and return.
|
|
//
|
|
|
|
Done:
|
|
|
|
SysFreeString( bstrWQL );
|
|
SysFreeString( bstrQuery );
|
|
|
|
if ( pObj )
|
|
{
|
|
pObj->Release();
|
|
}
|
|
|
|
if ( pEnum )
|
|
{
|
|
pEnum->Release();
|
|
}
|
|
|
|
if ( status == ERROR_SUCCESS && FAILED( hres ) )
|
|
{
|
|
status = HRES_TO_STATUS( hres );
|
|
}
|
|
|
|
return status;
|
|
} // DnscmdWmi_ProcessEnumRecords
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
DnscmdWmi_ResetProperty(
|
|
IN LPSTR pszZone,
|
|
IN LPSTR pszProperty,
|
|
IN DWORD cimType,
|
|
IN PVOID value
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reset a server or zone property.
|
|
|
|
Arguments:
|
|
|
|
pszZone -- zone name - NULL for server property
|
|
|
|
pszProperty -- name of property to set
|
|
|
|
cimType -- variant type of the property, use one of:
|
|
VT_I4 - DWORD
|
|
VT_BSTR - string
|
|
? - IP list
|
|
|
|
value -- new value for property, interpreted based on cimtype:
|
|
VT_I4 - cast pointer directly DWORD
|
|
VT_BSTR - pointer to UTF-8 string
|
|
? - pointer to IP list
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful or error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
BSTR bstrWQL = NULL;
|
|
BSTR bstrQuery = NULL;
|
|
BSTR bstrPropName = NULL;
|
|
IWbemClassObject * pObj = NULL;
|
|
IEnumWbemClassObject * pEnum = NULL;
|
|
HRESULT hres = 0;
|
|
ULONG returnedCount = 1;
|
|
WCHAR wsz[ 1024 ];
|
|
PWSTR pwszPropertyName = NULL;
|
|
PWSTR pwszPropertyValue = NULL;
|
|
|
|
DNSCMD_CHECK_WMI_ENABLED();
|
|
|
|
//
|
|
// Get WMI object.
|
|
//
|
|
|
|
status = getEnumerator( pszZone, &pEnum );
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
status = getNextObjectInEnum( pEnum, &pObj );
|
|
if ( status != ERROR_SUCCESS || !pObj )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Print the object's RELPATH (warm fuzzy).
|
|
//
|
|
|
|
VARIANT var;
|
|
|
|
status = getRelpath( pObj, &var );
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
goto Done;
|
|
}
|
|
printf( "%S\n\n", V_BSTR( &var) );
|
|
|
|
//
|
|
// Set the property.
|
|
//
|
|
|
|
pwszPropertyName = ( PWSTR ) Dns_NameCopyAllocate(
|
|
pszProperty,
|
|
0,
|
|
DnsCharSetUtf8,
|
|
DnsCharSetUnicode );
|
|
bstrPropName = SysAllocString( pwszPropertyName );
|
|
|
|
VariantClear( &var );
|
|
|
|
switch ( cimType )
|
|
{
|
|
case VT_BSTR:
|
|
pwszPropertyValue = ( PWSTR ) Dns_NameCopyAllocate(
|
|
( PCHAR ) value,
|
|
0,
|
|
DnsCharSetUtf8,
|
|
DnsCharSetUnicode );
|
|
V_VT( &var ) = VT_BSTR;
|
|
V_BSTR( &var ) = pwszPropertyValue;
|
|
break;
|
|
|
|
case PRIVATE_VT_IPARRAY:
|
|
{
|
|
SAFEARRAY * psa = createSafeArrayForIpArray(
|
|
( PIP_ARRAY ) value );
|
|
V_VT( &var ) = VT_ARRAY | VT_BSTR;
|
|
V_ARRAY( &var ) = psa;
|
|
break;
|
|
}
|
|
|
|
default: // Assume this is DWORD property.
|
|
V_VT( &var ) = VT_I4;
|
|
V_I4( &var ) = ( DWORD ) ( DWORD_PTR ) value;
|
|
break;
|
|
}
|
|
|
|
hres = pObj->Put( bstrPropName, 0, &var, 0 );
|
|
VariantClear( &var );
|
|
if ( !SUCCEEDED( hres ) )
|
|
{
|
|
printf( "WMI: unable to Put property error=0x%08X\n", hres );
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Commit the change back to WMI.
|
|
//
|
|
|
|
hres = g_pIWbemServices->PutInstance( pObj, 0, NULL, NULL );
|
|
if ( !SUCCEEDED( hres ) )
|
|
{
|
|
printf( "WMI: unable to commit property error=0x%08X\n", hres );
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Cleanup and return.
|
|
//
|
|
|
|
Done:
|
|
|
|
FREE_HEAP( pwszPropertyName );
|
|
FREE_HEAP( pwszPropertyValue );
|
|
SysFreeString( bstrPropName );
|
|
|
|
if ( pObj )
|
|
{
|
|
pObj->Release();
|
|
}
|
|
|
|
if ( pEnum )
|
|
{
|
|
pEnum->Release();
|
|
}
|
|
|
|
if ( status == ERROR_SUCCESS && FAILED( hres ) )
|
|
{
|
|
status = HRES_TO_STATUS( hres );
|
|
}
|
|
|
|
return status;
|
|
} // DnscmdWmi_ResetDwordProperty
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reset server level forwarders.
|
|
|
|
Arguments:
|
|
|
|
cForwarders -- number of forwarder IP addresses
|
|
|
|
aipForwarders -- array of forwarder IP addresses
|
|
|
|
dwForwardTimeout -- timeout
|
|
|
|
fSlave -- slave flag
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful or error code on failure.
|
|
|
|
--*/
|
|
DNS_STATUS
|
|
DnscmdWmi_ProcessResetForwarders(
|
|
IN DWORD cForwarders,
|
|
IN PIP_ADDRESS aipForwarders,
|
|
IN DWORD dwForwardTimeout,
|
|
IN DWORD fSlave
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
IEnumWbemClassObject * pEnum = NULL;
|
|
IWbemClassObject * pObj = NULL;
|
|
SAFEARRAY * psa = NULL;
|
|
HRESULT hres = 0;
|
|
VARIANT var;
|
|
|
|
VariantInit( &var );
|
|
|
|
//
|
|
// Get WMI object for server.
|
|
//
|
|
|
|
status = getEnumerator( NULL, &pEnum );
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
status = getNextObjectInEnum( pEnum, &pObj );
|
|
if ( status != ERROR_SUCCESS || !pObj )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Set up parameters.
|
|
//
|
|
|
|
psa = createSafeArrayForIpList( cForwarders, aipForwarders );
|
|
if ( !psa )
|
|
{
|
|
status = ERROR_INVALID_PARAMETER;
|
|
goto Done;
|
|
}
|
|
V_VT( &var ) = VT_ARRAY | VT_BSTR;
|
|
V_ARRAY( &var ) = psa;
|
|
hres = pObj->Put( MYTEXT( DNS_REGKEY_FORWARDERS ), 0, &var, 0 );
|
|
VariantClear( &var );
|
|
if ( !SUCCEEDED( hres ) )
|
|
{
|
|
printf(
|
|
"WMI: unable to Put property %S error=0x%08X\n",
|
|
MYTEXT( DNS_REGKEY_FORWARDERS ),
|
|
hres );
|
|
goto Done;
|
|
}
|
|
|
|
V_VT( &var ) = VT_I4;
|
|
V_I4( &var ) = dwForwardTimeout;
|
|
hres = pObj->Put( MYTEXT( DNS_REGKEY_FORWARD_TIMEOUT ), 0, &var, 0 );
|
|
VariantClear( &var );
|
|
if ( !SUCCEEDED( hres ) )
|
|
{
|
|
printf(
|
|
"WMI: unable to Put property %S error=0x%08X\n",
|
|
MYTEXT( DNS_REGKEY_FORWARD_TIMEOUT ),
|
|
hres );
|
|
goto Done;
|
|
}
|
|
|
|
V_VT( &var ) = VT_BOOL;
|
|
V_BOOL( &var ) = ( VARIANT_BOOL ) fSlave;
|
|
hres = pObj->Put( MYTEXT( DNS_REGKEY_SLAVE ), 0, &var, 0 );
|
|
VariantClear( &var );
|
|
if ( !SUCCEEDED( hres ) )
|
|
{
|
|
printf(
|
|
"WMI: unable to Put property %S error=0x%08X\n",
|
|
MYTEXT( DNS_REGKEY_SLAVE ),
|
|
hres );
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Commit the change back to WMI.
|
|
//
|
|
|
|
hres = g_pIWbemServices->PutInstance( pObj, 0, NULL, NULL );
|
|
if ( !SUCCEEDED( hres ) )
|
|
{
|
|
printf( "WMI: unable to commit property error=0x%08X\n", hres );
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Cleanup and return.
|
|
//
|
|
|
|
Done:
|
|
|
|
if ( pObj )
|
|
{
|
|
pObj->Release();
|
|
}
|
|
if ( pEnum )
|
|
{
|
|
pEnum->Release();
|
|
}
|
|
VariantClear( &var );
|
|
|
|
if ( status == ERROR_SUCCESS && FAILED( hres ) )
|
|
{
|
|
status = hres;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Send generic operation to server.
|
|
|
|
Arguments:
|
|
|
|
pszZone -- zone name or NULL for server level operation
|
|
|
|
pszOperation -- string identifying operation
|
|
|
|
dwTypeId -- DNS RPC data type of data at pvData
|
|
|
|
pvData -- DNS RPC data in DNS RPC union format
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful or error code on failure.
|
|
|
|
--*/
|
|
DNS_STATUS
|
|
DnscmdWmi_ProcessDnssrvOperation(
|
|
IN LPSTR pszZoneName,
|
|
IN LPSTR pszOperation,
|
|
IN DWORD dwTypeId,
|
|
IN PVOID pvData
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
HRESULT hres = 0;
|
|
IEnumWbemClassObject * pEnum = NULL;
|
|
IWbemClassObject * pObj = NULL;
|
|
SAFEARRAY * psa = NULL;
|
|
PWSTR pwszOperation = NULL;
|
|
VARIANT var;
|
|
|
|
VariantInit( &var );
|
|
|
|
//
|
|
// Get WMI object.
|
|
//
|
|
|
|
status = getEnumerator( pszZoneName, &pEnum );
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
status = getNextObjectInEnum( pEnum, &pObj );
|
|
if ( status != ERROR_SUCCESS || !pObj )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Process operation.
|
|
//
|
|
|
|
pwszOperation = ( PWSTR ) Dns_NameCopyAllocate(
|
|
pszOperation,
|
|
0,
|
|
DnsCharSetUtf8,
|
|
DnsCharSetUnicode );
|
|
if ( !pwszOperation )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
if ( _stricmp( pszOperation, DNS_REGKEY_ZONE_MASTERS ) == 0 ||
|
|
_stricmp( pszOperation, DNS_REGKEY_ZONE_LOCAL_MASTERS ) == 0 )
|
|
{
|
|
//
|
|
// For these properties do a simple Put operation by converting
|
|
// the DNS RPC data into VARIANT format and calling Put.
|
|
//
|
|
|
|
switch ( dwTypeId )
|
|
{
|
|
case DNSSRV_TYPEID_IPARRAY:
|
|
{
|
|
PIP_ARRAY pip = ( PIP_ARRAY ) pvData;
|
|
|
|
psa = createSafeArrayForIpList(
|
|
pip ? pip->AddrCount : 0,
|
|
pip ? pip->AddrArray : NULL );
|
|
if ( !psa )
|
|
{
|
|
status = ERROR_INVALID_PARAMETER;
|
|
goto Done;
|
|
}
|
|
V_VT( &var ) = VT_ARRAY | VT_BSTR;
|
|
V_ARRAY( &var ) = psa;
|
|
hres = pObj->Put( pwszOperation, 0, &var, 0 );
|
|
break;
|
|
}
|
|
|
|
default:
|
|
status = ERROR_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Commit the Put operation.
|
|
//
|
|
|
|
if ( status == ERROR_SUCCESS && SUCCEEDED( hres ) )
|
|
{
|
|
hres = g_pIWbemServices->PutInstance( pObj, 0, NULL, NULL );
|
|
if ( FAILED( hres ) )
|
|
{
|
|
printf(
|
|
"WMI: unable to commit property %s error=0x%08X\n",
|
|
pszOperation,
|
|
hres );
|
|
goto Done;
|
|
}
|
|
}
|
|
}
|
|
else if ( _stricmp( pszOperation, DNSSRV_OP_ZONE_DELETE ) == 0 ||
|
|
_stricmp( pszOperation, DNSSRV_OP_ZONE_DELETE_FROM_DS ) == 0 )
|
|
{
|
|
//
|
|
// Delete the zone.
|
|
//
|
|
|
|
VARIANT relpath;
|
|
|
|
status = getRelpath( pObj, &relpath );
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
hres = g_pIWbemServices->DeleteInstance(
|
|
V_BSTR( &relpath ),
|
|
0,
|
|
NULL,
|
|
NULL );
|
|
}
|
|
VariantClear( &relpath );
|
|
}
|
|
else
|
|
{
|
|
status = ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
//
|
|
// Cleanup and return.
|
|
//
|
|
|
|
Done:
|
|
|
|
if ( psa )
|
|
{
|
|
SafeArrayDestroy( psa );
|
|
}
|
|
if ( pwszOperation )
|
|
{
|
|
FREE_HEAP( pwszOperation );
|
|
}
|
|
if ( pObj )
|
|
{
|
|
pObj->Release();
|
|
}
|
|
if ( pEnum )
|
|
{
|
|
pEnum->Release();
|
|
}
|
|
VariantClear( &var );
|
|
|
|
if ( status == ERROR_SUCCESS && FAILED( hres ) )
|
|
{
|
|
status = hres;
|
|
}
|
|
|
|
return status;
|
|
} // DnscmdWmi_ProcessDnssrvOperation
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
DnscmdWmi_ProcessRecordAdd(
|
|
IN LPSTR pszZoneName,
|
|
IN LPSTR pszNodeName,
|
|
IN PDNS_RPC_RECORD prrRpc,
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add or delete a resource record. This function will take
|
|
of the necessary some data from the RPC record and some from
|
|
the argument list.
|
|
|
|
Arguments:
|
|
|
|
pszZoneName -- zone name
|
|
|
|
pszNodeName -- name of property to set
|
|
|
|
prrRpc -- RPC record
|
|
|
|
Argc -- count of arguments used to create RPC record
|
|
|
|
Argv -- arguments used to create RPC record
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful or error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
PWSTR pwszZoneName = NULL;
|
|
PWSTR pwszArgs = NULL;
|
|
PWSTR pwszCurrent;
|
|
IWbemClassObject * pClassObj = NULL;
|
|
IWbemClassObject * pServerObj = NULL;
|
|
IWbemClassObject * pInSig = NULL;
|
|
IWbemClassObject * pOutSig = NULL;
|
|
IWbemClassObject * pInParams = NULL;
|
|
IEnumWbemClassObject * pEnum = NULL;
|
|
HRESULT hres = 0;
|
|
BSTR bstrClassName;
|
|
BSTR bstrMethodName;
|
|
VARIANT var;
|
|
int len;
|
|
int i;
|
|
|
|
DNSCMD_CHECK_WMI_ENABLED();
|
|
|
|
//
|
|
// Allocate and initialize various stuff.
|
|
//
|
|
|
|
VariantInit( &var );
|
|
|
|
bstrClassName = SysAllocString( L"MicrosoftDNS_ResourceRecord" );
|
|
bstrMethodName = SysAllocString( L"CreateInstanceFromTextRepresentation" );
|
|
if ( !bstrClassName || !bstrMethodName )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
pwszZoneName = ( PWSTR ) Dns_NameCopyAllocate(
|
|
pszZoneName,
|
|
0,
|
|
DnsCharSetUtf8,
|
|
DnsCharSetUnicode );
|
|
if ( !pwszZoneName )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Get WMI class object for Resource Record class.
|
|
//
|
|
|
|
hres = g_pIWbemServices->GetObject(
|
|
bstrClassName,
|
|
WBEM_FLAG_RETURN_WBEM_COMPLETE,
|
|
NULL,
|
|
&pClassObj,
|
|
NULL );
|
|
if ( FAILED( hres ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
ASSERT( pClassObj );
|
|
|
|
//
|
|
// Get WMI object for server.
|
|
//
|
|
|
|
status = getEnumerator( NULL, &pEnum );
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
goto Done;
|
|
}
|
|
ASSERT( pEnum );
|
|
|
|
status = getNextObjectInEnum( pEnum, &pServerObj );
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
goto Done;
|
|
}
|
|
ASSERT( pServerObj );
|
|
|
|
//
|
|
// Get WMI method signature for CreateInstanceFromTextRepresentation.
|
|
//
|
|
|
|
hres = pClassObj->GetMethod(
|
|
bstrMethodName,
|
|
0,
|
|
&pInSig,
|
|
&pOutSig );
|
|
if ( FAILED( hres ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
if ( pInSig == NULL )
|
|
{
|
|
status = ERROR_INVALID_PARAMETER;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Create an instance of the method input parameters.
|
|
//
|
|
|
|
hres = pInSig->SpawnInstance( 0, &pInParams );
|
|
if ( FAILED( hres ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
ASSERT( pInParams );
|
|
|
|
//
|
|
// Collect the arguments into one big string
|
|
// -> owner name
|
|
// -> record class
|
|
// -> record type
|
|
// -> Argv array (space separated)
|
|
//
|
|
|
|
len = Argc * 2 + // for spaces
|
|
30 + // for record type
|
|
strlen( pszNodeName );
|
|
for ( i = 0; i < ( int ) Argc; ++i )
|
|
{
|
|
len += strlen( Argv[ i ] );
|
|
}
|
|
pwszCurrent = pwszArgs = new WCHAR [ len * sizeof( WCHAR ) ];
|
|
if ( !pwszArgs )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
for ( i = -3; i < ( int ) Argc; ++i )
|
|
{
|
|
CHAR szBuff[ 40 ];
|
|
PSTR psz;
|
|
if ( i == -3 )
|
|
{
|
|
psz = pszNodeName;
|
|
}
|
|
else if ( i == -2 )
|
|
{
|
|
psz = "IN";
|
|
}
|
|
else if ( i == -1 )
|
|
{
|
|
psz = Dns_RecordStringForType( prrRpc->wType );
|
|
}
|
|
else
|
|
{
|
|
psz = Argv[ i ];
|
|
}
|
|
|
|
PWSTR pwsz = ( PWSTR ) Dns_NameCopyAllocate(
|
|
psz,
|
|
0,
|
|
DnsCharSetUtf8,
|
|
DnsCharSetUnicode );
|
|
if ( !pwsz )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
if ( pwszCurrent != pwszArgs )
|
|
{
|
|
wcscpy( pwszCurrent++, L" " );
|
|
}
|
|
wcscpy( pwszCurrent, pwsz );
|
|
pwszCurrent += wcslen( pwsz );
|
|
}
|
|
|
|
//
|
|
// Set method input parameters.
|
|
//
|
|
|
|
getRelpath( pServerObj, &var );
|
|
hres = pInParams->Put( L"DnsServerName", 0, &var, 0 );
|
|
VariantClear( &var );
|
|
|
|
V_VT( &var ) = VT_BSTR;
|
|
V_BSTR( &var ) = SysAllocString( pwszZoneName );
|
|
hres = pInParams->Put( L"ContainerName", 0, &var, 0 );
|
|
VariantClear( &var );
|
|
|
|
V_VT( &var ) = VT_BSTR;
|
|
V_BSTR( &var ) = SysAllocString( pwszArgs );
|
|
hres = pInParams->Put( L"TextRepresentation", 0, &var, 0 );
|
|
VariantClear( &var );
|
|
|
|
//
|
|
// Execute the method (finally!)
|
|
//
|
|
|
|
hres = g_pIWbemServices->ExecMethod(
|
|
bstrClassName,
|
|
bstrMethodName,
|
|
0, // flags
|
|
NULL, // context
|
|
pInParams, // input params
|
|
NULL, // output params
|
|
NULL ); // call result
|
|
if ( FAILED( hres ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Cleanup and return.
|
|
//
|
|
|
|
Done:
|
|
|
|
VariantClear( &var );
|
|
FREE_HEAP( pwszZoneName );
|
|
delete [] pwszArgs;
|
|
SysFreeString( bstrMethodName );
|
|
SysFreeString( bstrClassName );
|
|
wmiRelease( pEnum );
|
|
wmiRelease( pClassObj );
|
|
wmiRelease( pServerObj );
|
|
wmiRelease( pInSig );
|
|
wmiRelease( pOutSig );
|
|
wmiRelease( pInParams );
|
|
|
|
if ( status == ERROR_SUCCESS && FAILED( hres ) )
|
|
{
|
|
status = HRES_TO_STATUS( hres );
|
|
}
|
|
return status;
|
|
} // DnscmdWmi_ProcessRecordAdd
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
DnscmdWmi_GetStatistics(
|
|
IN DWORD dwStatId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrieves and dumps all statistics matching the dwStatId mask.
|
|
|
|
Arguments:
|
|
|
|
dwStatId -- statistic filter
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful or error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
WCHAR wsz[ 1024 ];
|
|
BSTR bstrWQL = NULL;
|
|
BSTR bstrQuery = NULL;
|
|
HRESULT hres = 0;
|
|
IEnumWbemClassObject * pEnum = NULL;
|
|
IWbemClassObject * pObj = NULL;
|
|
|
|
//
|
|
// Execute query for statistics.
|
|
//
|
|
|
|
wsprintfW(
|
|
wsz,
|
|
L"select * from MicrosoftDNS_Statistic" );
|
|
|
|
bstrWQL = SysAllocString( L"WQL" );
|
|
bstrQuery = SysAllocString( wsz );
|
|
if ( !bstrWQL || !bstrQuery )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
hres = g_pIWbemServices->ExecQuery(
|
|
bstrWQL,
|
|
bstrQuery,
|
|
WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
|
|
NULL,
|
|
&pEnum );
|
|
if ( FAILED( hres ) )
|
|
{
|
|
status = hres;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Dump query results.
|
|
//
|
|
|
|
VARIANT varLastColl;
|
|
VariantInit( &varLastColl );
|
|
|
|
while ( 1 )
|
|
{
|
|
status = getNextObjectInEnum( pEnum, &pObj, FALSE );
|
|
if ( status != ERROR_SUCCESS || !pObj )
|
|
{
|
|
break;
|
|
}
|
|
|
|
CIMTYPE cimColl = 0;
|
|
CIMTYPE cimName = 0;
|
|
CIMTYPE cimValue = 0;
|
|
CIMTYPE cimStringValue = 0;
|
|
|
|
VARIANT varColl;
|
|
VARIANT varName;
|
|
VARIANT varValue;
|
|
VARIANT varStringValue;
|
|
VariantInit( &varColl );
|
|
VariantInit( &varName );
|
|
VariantInit( &varValue );
|
|
VariantInit( &varStringValue );
|
|
|
|
hres = pObj->Get( L"CollectionName", 0, &varColl, &cimColl, NULL );
|
|
CHECK_HRES( hres, L"CollectionName" );
|
|
hres = pObj->Get( L"Name", 0, &varName, &cimName, NULL );
|
|
CHECK_HRES( hres, L"Name" );
|
|
hres = pObj->Get( L"Value", 0, &varValue, &cimValue, NULL );
|
|
CHECK_HRES( hres, L"Value" );
|
|
hres = pObj->Get( L"StringValue", 0, &varStringValue, &cimValue, NULL );
|
|
CHECK_HRES( hres, L"StringValue" );
|
|
|
|
if ( V_VT( &varLastColl ) == VT_EMPTY ||
|
|
wcscmp( V_BSTR( &varLastColl ), V_BSTR( &varColl ) ) != 0 )
|
|
{
|
|
//
|
|
// Entering new collection. NOTE: this assumes that stats
|
|
// are ordered by collection. Probably not a great assumption
|
|
// but it works for now.
|
|
//
|
|
|
|
printf( "\n%S:\n", V_BSTR( &varColl ) );
|
|
hres = VariantCopy( &varLastColl, &varColl );
|
|
if ( FAILED( hres ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
printf(
|
|
" %-35S = ",
|
|
V_BSTR( &varName ) );
|
|
|
|
if ( V_VT( &varValue ) != VT_NULL )
|
|
{
|
|
printf( "%lu", V_UI4( &varValue ) );
|
|
// printf( "%lu (0x%08X)", V_UI4( &varValue ), V_UI4( &varValue ) );
|
|
}
|
|
else if ( V_VT( &varStringValue ) == VT_BSTR )
|
|
{
|
|
printf( "%S", V_BSTR( &varStringValue ) );
|
|
}
|
|
else
|
|
{
|
|
printf( "invalid value!" );
|
|
}
|
|
printf( "\n" );
|
|
|
|
VariantClear( &varColl );
|
|
VariantClear( &varName );
|
|
VariantClear( &varValue );
|
|
VariantClear( &varStringValue );
|
|
}
|
|
VariantClear( &varLastColl );
|
|
|
|
//
|
|
// Cleanup and return
|
|
//
|
|
|
|
Done:
|
|
|
|
SysFreeString( bstrWQL );
|
|
SysFreeString( bstrQuery );
|
|
if ( pEnum )
|
|
{
|
|
pEnum->Release();
|
|
}
|
|
if ( pObj )
|
|
{
|
|
pObj->Release();
|
|
}
|
|
|
|
if ( status == ERROR_SUCCESS && FAILED( hres ) )
|
|
{
|
|
status = HRES_TO_STATUS( hres );
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
DnscmdWmi_ProcessResetZoneSecondaries(
|
|
IN LPSTR pszZoneName,
|
|
IN DWORD fSecureSecondaries,
|
|
IN DWORD cSecondaries,
|
|
IN PIP_ADDRESS aipSecondaries,
|
|
IN DWORD fNotifyLevel,
|
|
IN DWORD cNotify,
|
|
IN PIP_ADDRESS aipNotify
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Send "zone reset secondaries" command to the server to reset
|
|
the zone secondary and notify list parameters.
|
|
|
|
Arguments:
|
|
|
|
pszZoneName -- zone name
|
|
|
|
fSecureSecondaries -- secondary directive (ZONE_SECSECURE_XXX)
|
|
|
|
cSecondaries -- count of IP addresses in aipSecondaries
|
|
|
|
aipSecondaries -- secondary server IP address array
|
|
|
|
fNotifyLevel -- notify directive (ZONE_NOTIFY_XXX)
|
|
|
|
cNotify -- count of IP addresses in aipNotify
|
|
|
|
aipNotify -- notify server IP address array
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful or error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
BSTR bstrClassName;
|
|
BSTR bstrMethodName;
|
|
PWSTR pwszZoneName = NULL;
|
|
IWbemClassObject * pObj = NULL;
|
|
IWbemClassObject * pClassObj = NULL;
|
|
IWbemClassObject * pInSig = NULL;
|
|
IWbemClassObject * pOutSig = NULL;
|
|
IWbemClassObject * pInParams = NULL;
|
|
IEnumWbemClassObject * pEnum = NULL;
|
|
VARIANT var;
|
|
HRESULT hres;
|
|
SAFEARRAY * psa;
|
|
|
|
DNSCMD_CHECK_WMI_ENABLED();
|
|
|
|
//
|
|
// Allocate and initialize various stuff.
|
|
//
|
|
|
|
VariantInit( &var );
|
|
|
|
bstrClassName = SysAllocString( L"MicrosoftDNS_Zone" );
|
|
bstrMethodName = SysAllocString( L"ResetSecondaries" );
|
|
if ( !bstrClassName || !bstrMethodName )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Get WMI class object for the Zone class.
|
|
//
|
|
|
|
hres = g_pIWbemServices->GetObject(
|
|
bstrClassName,
|
|
WBEM_FLAG_RETURN_WBEM_COMPLETE,
|
|
NULL,
|
|
&pClassObj,
|
|
NULL );
|
|
if ( FAILED( hres ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
ASSERT( pClassObj );
|
|
|
|
//
|
|
// Get WMI object for specified zone.
|
|
//
|
|
|
|
status = getEnumerator( pszZoneName, &pEnum );
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
status = getNextObjectInEnum( pEnum, &pObj );
|
|
if ( status != ERROR_SUCCESS || !pObj )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Get WMI method signature for ResetSecondaries.
|
|
//
|
|
|
|
hres = pClassObj->GetMethod(
|
|
bstrMethodName,
|
|
0,
|
|
&pInSig,
|
|
&pOutSig );
|
|
if ( FAILED( hres ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
if ( pInSig == NULL )
|
|
{
|
|
status = ERROR_INVALID_PARAMETER;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Create an instance of the method input parameters.
|
|
//
|
|
|
|
hres = pInSig->SpawnInstance( 0, &pInParams );
|
|
if ( FAILED( hres ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
ASSERT( pInParams );
|
|
|
|
//
|
|
// Set method input parameters.
|
|
//
|
|
|
|
printWmiObjectProperties( pInParams );
|
|
|
|
{
|
|
BSTR b = NULL;
|
|
pInParams->GetObjectText( 0, &b );
|
|
printf( "\nObjectText:\n%S\n", b );
|
|
}
|
|
|
|
VariantClear( &var );
|
|
|
|
{
|
|
BSTR bstr = SysAllocString( L"SecureSecondaries" );
|
|
V_VT( &var ) = VT_UI4;
|
|
V_UI4( &var ) = fSecureSecondaries;
|
|
hres = pInParams->Put( bstr, 0, &var, 0 );
|
|
VariantClear( &var );
|
|
}
|
|
|
|
#if 0
|
|
V_VT( &var ) = VT_UI4;
|
|
V_UI4( &var ) = fSecureSecondaries;
|
|
hres = pInParams->Put( L"SecureSecondaries", 0, &var, 0 );
|
|
VariantClear( &var );
|
|
#endif
|
|
|
|
V_VT( &var ) = VT_UI4;
|
|
V_UI4( &var ) = fNotifyLevel;
|
|
hres = pInParams->Put( L"Notify", 0, &var, 0 );
|
|
VariantClear( &var );
|
|
|
|
psa = createSafeArrayForIpList( cSecondaries, aipSecondaries );
|
|
if ( !psa )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
V_VT( &var ) = VT_ARRAY | VT_BSTR;
|
|
V_ARRAY( &var ) = psa;
|
|
hres = pInParams->Put( L"SecondaryServers", 0, &var, 0 );
|
|
VariantClear( &var );
|
|
|
|
psa = createSafeArrayForIpList( cNotify, aipNotify );
|
|
if ( !psa )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
V_VT( &var ) = VT_ARRAY | VT_BSTR;
|
|
V_ARRAY( &var ) = psa;
|
|
hres = pInParams->Put( L"NotifyServers", 0, &var, 0 );
|
|
VariantClear( &var );
|
|
|
|
//
|
|
// Execute the method.
|
|
//
|
|
|
|
hres = g_pIWbemServices->ExecMethod(
|
|
bstrClassName,
|
|
bstrMethodName,
|
|
0, // flags
|
|
NULL, // context
|
|
pInParams, // input params
|
|
NULL, // output params
|
|
NULL ); // call result
|
|
if ( FAILED( hres ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Cleanup and return.
|
|
//
|
|
|
|
Done:
|
|
|
|
VariantClear( &var );
|
|
FREE_HEAP( pwszZoneName );
|
|
SysFreeString( bstrMethodName );
|
|
SysFreeString( bstrClassName );
|
|
wmiRelease( pEnum );
|
|
wmiRelease( pClassObj );
|
|
wmiRelease( pInSig );
|
|
wmiRelease( pOutSig );
|
|
wmiRelease( pInParams );
|
|
|
|
if ( status == ERROR_SUCCESS && FAILED( hres ) )
|
|
{
|
|
status = HRES_TO_STATUS( hres );
|
|
}
|
|
return status;
|
|
} // DnscmdWmi_ProcessResetZoneSecondaries
|
|
|
|
|
|
//
|
|
// End dnsc_wmi.c
|
|
//
|
|
|