Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2945 lines
71 KiB

/*++
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 )
{
wsprintfW(
wsz,
L"select * from MicrosoftDNS_Zone where Name='%S'",
pszZoneName );
}
else
{
wsprintfW(
wsz,
L"select * from MicrosoftDNS_Server" );
}
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 ( hres == WBEM_S_FALSE )
{
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:
ERROR_SUCCESS if successful or error code on 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 );
SafeArrayPutElement(
psa,
( PLONG ) &i,
bstr );
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, 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, 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;
SafeArrayGetElement(pVec, &i, &v);
iLen = (wcslen(v) + 1) * sizeof(WCHAR);
if (iLen > iVSize) {
vbuf = (WCHAR *)realloc(vbuf, iLen + sizeof(WCHAR));
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
buf = (WCHAR *)realloc(buf, iTotBufSize);
}
wcscat(buf, L"\"");
wcscat(buf, vbuf);
if (i + 1 <= iUBound) {
wcscat(buf, L"\",");
} else {
wcscat(buf, L"\"");
}
iCurBufSize += iNeed;
SysFreeString(v);
}
free(vbuf);
}
break;
}
default:
{
buf = (WCHAR *)malloc(BLOCKSIZE);
if ( !buf ) goto AllocFailed;
wcscpy(buf, L"<conversion error>");
break;
}
}
AllocFailed:
*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 ) );
VariantCopy( &varLastColl, &varColl );
}
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;
#if 0
IWbemClassObject * pServerObj = NULL;
PWSTR pwszArgs = NULL;
PWSTR pwszCurrent;
int len;
int i;
#endif
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 );
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 );
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
//