WindowsXP-SP1/admin/snapin/dsadmin/util.cpp
2020-09-30 16:53:49 +02:00

459 lines
11 KiB
C++

// Util.cpp : Implementation of ds routines and classes
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1999
//
// File: Util.cpp
//
// Contents: Utility functions
//
// History: 02-Oct-96 WayneSc Created
//
//
//--------------------------------------------------------------------------
#include "stdafx.h"
#include "util.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define MAX_STRING 1024
//+----------------------------------------------------------------------------
//
// Function: LoadStringToTchar
//
// Sysnopsis: Loads the given string into an allocated buffer that must be
// caller freed using delete.
//
//-----------------------------------------------------------------------------
BOOL LoadStringToTchar(int ids, PTSTR * pptstr)
{
TCHAR szBuf[MAX_STRING];
if (!LoadString(_Module.GetModuleInstance(), ids, szBuf, MAX_STRING - 1))
{
return FALSE;
}
*pptstr = new TCHAR[_tcslen(szBuf) + 1];
if (*pptstr == NULL)
{
return FALSE;
};
_tcscpy(*pptstr, szBuf);
return TRUE;
}
//
// These routines courtesy of Felix Wong -- JonN 2/24/98
//
// just guessing at what Felix meant by these -- JonN 2/24/98
#define RRETURN(hr) { ASSERT( SUCCEEDED(hr) ); return hr; }
#define BAIL_ON_FAILURE if ( FAILED(hr) ) { ASSERT(FALSE); goto error; }
//////////////////////////////////////////////////////////////////////////
// Variant Utilitites
//
HRESULT BinaryToVariant(DWORD Length,
BYTE* pByte,
VARIANT* lpVarDestObject)
{
HRESULT hr = S_OK;
SAFEARRAY *aList = NULL;
SAFEARRAYBOUND aBound;
CHAR HUGEP *pArray = NULL;
aBound.lLbound = 0;
aBound.cElements = Length;
aList = SafeArrayCreate( VT_UI1, 1, &aBound );
if ( aList == NULL )
{
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
hr = SafeArrayAccessData( aList, (void HUGEP * FAR *) &pArray );
BAIL_ON_FAILURE(hr);
memcpy( pArray, pByte, aBound.cElements );
SafeArrayUnaccessData( aList );
V_VT(lpVarDestObject) = VT_ARRAY | VT_UI1;
V_ARRAY(lpVarDestObject) = aList;
RRETURN(hr);
error:
if ( aList )
{
SafeArrayDestroy( aList );
}
RRETURN(hr);
}
HRESULT HrVariantToStringList(const CComVariant& refvar,
CStringList& refstringlist)
{
HRESULT hr = S_OK;
long start, end, current;
if (V_VT(&refvar) == VT_BSTR)
{
refstringlist.AddHead( V_BSTR(&refvar) );
return S_OK;
}
//
// Check the VARIANT to make sure we have
// an array of variants.
//
if ( V_VT(&refvar) != ( VT_ARRAY | VT_VARIANT ) )
{
ASSERT(FALSE);
return E_UNEXPECTED;
}
SAFEARRAY *saAttributes = V_ARRAY( &refvar );
//
// Figure out the dimensions of the array.
//
hr = SafeArrayGetLBound( saAttributes, 1, &start );
if( FAILED(hr) )
return hr;
hr = SafeArrayGetUBound( saAttributes, 1, &end );
if( FAILED(hr) )
return hr;
CComVariant SingleResult;
//
// Process the array elements.
//
for ( current = start; current <= end; current++)
{
hr = SafeArrayGetElement( saAttributes, &current, &SingleResult );
if( FAILED(hr) )
return hr;
if ( V_VT(&SingleResult) != VT_BSTR )
return E_UNEXPECTED;
refstringlist.AddHead( V_BSTR(&SingleResult) );
}
return S_OK;
} // VariantToStringList()
HRESULT HrStringListToVariant(CComVariant& refvar,
const CStringList& refstringlist)
{
HRESULT hr = S_OK;
int cCount = (int)refstringlist.GetCount();
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = cCount;
SAFEARRAY* psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
if (NULL == psa)
return E_OUTOFMEMORY;
V_VT(&refvar) = VT_VARIANT|VT_ARRAY;
V_ARRAY(&refvar) = psa;
POSITION pos = refstringlist.GetHeadPosition();
long i;
for (i = 0; i < cCount, pos != NULL; i++)
{
CComVariant SingleResult; // declare inside loop. Otherwise, throws
// exception in destructor if nothing added.
V_VT(&SingleResult) = VT_BSTR;
V_BSTR(&SingleResult) = T2BSTR((LPCTSTR)refstringlist.GetNext(pos));
hr = SafeArrayPutElement(psa, &i, &SingleResult);
if( FAILED(hr) )
return hr;
}
if (i != cCount || pos != NULL)
return E_UNEXPECTED;
return hr;
} // StringListToVariant()
//////////////////////////////////////////////////////////
// streaming helper functions
HRESULT SaveStringHelper(LPCWSTR pwsz, IStream* pStm)
{
ASSERT(pStm);
ULONG nBytesWritten;
HRESULT hr;
//
// wcslen returns a size_t and to make that consoles work the same
// on any platform we always convert to a DWORD
//
DWORD nLen = static_cast<DWORD>(wcslen(pwsz)+1); // WCHAR including NULL
hr = pStm->Write((void*)&nLen, sizeof(DWORD),&nBytesWritten);
ASSERT(nBytesWritten == sizeof(DWORD));
if (FAILED(hr))
return hr;
hr = pStm->Write((void*)pwsz, sizeof(WCHAR)*nLen,&nBytesWritten);
ASSERT(nBytesWritten == sizeof(WCHAR)*nLen);
TRACE(_T("SaveStringHelper(<%s> nLen = %d\n"),pwsz,nLen);
return hr;
}
HRESULT LoadStringHelper(CString& sz, IStream* pStm)
{
ASSERT(pStm);
HRESULT hr;
ULONG nBytesRead;
DWORD nLen = 0;
hr = pStm->Read((void*)&nLen,sizeof(DWORD), &nBytesRead);
ASSERT(nBytesRead == sizeof(DWORD));
if (FAILED(hr) || (nBytesRead != sizeof(DWORD)))
return hr;
hr = pStm->Read((void*)sz.GetBuffer(nLen),sizeof(WCHAR)*nLen, &nBytesRead);
ASSERT(nBytesRead == sizeof(WCHAR)*nLen);
sz.ReleaseBuffer();
TRACE(_T("LoadStringHelper(<%s> nLen = %d\n"),(LPCTSTR)sz,nLen);
return hr;
}
HRESULT SaveDWordHelper(IStream* pStm, DWORD dw)
{
ULONG nBytesWritten;
HRESULT hr = pStm->Write((void*)&dw, sizeof(DWORD),&nBytesWritten);
if (nBytesWritten < sizeof(DWORD))
hr = STG_E_CANTSAVE;
return hr;
}
HRESULT LoadDWordHelper(IStream* pStm, DWORD* pdw)
{
ULONG nBytesRead;
HRESULT hr = pStm->Read((void*)pdw,sizeof(DWORD), &nBytesRead);
ASSERT(nBytesRead == sizeof(DWORD));
return hr;
}
void GetCurrentTimeStampMinusInterval(DWORD dwDays,
LARGE_INTEGER* pLI)
{
ASSERT(pLI);
FILETIME ftCurrent;
GetSystemTimeAsFileTime(&ftCurrent);
pLI->LowPart = ftCurrent.dwLowDateTime;
pLI->HighPart = ftCurrent.dwHighDateTime;
pLI->QuadPart -= ((((ULONGLONG)dwDays * 24) * 60) * 60) * 10000000;
}
/////////////////////////////////////////////////////////////////////
// CCommandLineOptions
//
// helper function to parse a single command and match it with a given switch
//
BOOL _LoadCommandLineValue(IN LPCWSTR lpszSwitch,
IN LPCWSTR lpszArg,
OUT CString* pszValue)
{
ASSERT(lpszSwitch != NULL);
ASSERT(lpszArg != NULL);
int nSwitchLen = lstrlen(lpszSwitch); // not counting NULL
// check if the arg is the one we look for
if (_wcsnicmp(lpszSwitch, lpszArg, nSwitchLen) == 0)
{
// got it, copy the value
if (pszValue != NULL)
(*pszValue) = lpszArg+nSwitchLen;
return TRUE;
}
// not found, empty string
if (pszValue != NULL)
pszValue->Empty();
return FALSE;
}
void CCommandLineOptions::Initialize()
{
// command line overrides the snapin understands,
// not subject to localization
static LPCWSTR lpszOverrideDomainCommandLine = L"/Domain=";
static LPCWSTR lpszOverrideServerCommandLine = L"/Server=";
static LPCWSTR lpszOverrideRDNCommandLine = L"/RDN=";
static LPCWSTR lpszOverrideSavedQueriesCommandLine = L"/Queries=";
#ifdef DBG
static LPCWSTR lpszOverrideNoNameCommandLine = L"/NoName";
#endif
// do it only once
if (m_bInit)
{
return;
}
m_bInit = TRUE;
//
// see if we have command line arguments
//
LPCWSTR * lpServiceArgVectors; // Array of pointers to string
int cArgs = 0; // Count of arguments
lpServiceArgVectors = (LPCWSTR *)CommandLineToArgvW(GetCommandLineW(), OUT &cArgs);
if (lpServiceArgVectors == NULL)
{
// none, just return
return;
}
// loop and search for pertinent strings
for (int i = 1; i < cArgs; i++)
{
ASSERT(lpServiceArgVectors[i] != NULL);
TRACE (_T("command line arg: %s\n"), lpServiceArgVectors[i]);
if (_LoadCommandLineValue(lpszOverrideDomainCommandLine,
lpServiceArgVectors[i], &m_szOverrideDomainName))
{
continue;
}
if (_LoadCommandLineValue(lpszOverrideServerCommandLine,
lpServiceArgVectors[i], &m_szOverrideServerName))
{
continue;
}
if (_LoadCommandLineValue(lpszOverrideRDNCommandLine,
lpServiceArgVectors[i], &m_szOverrideRDN))
{
continue;
}
if (_LoadCommandLineValue(lpszOverrideSavedQueriesCommandLine,
lpServiceArgVectors[i], &m_szSavedQueriesXMLFile))
{
continue;
}
#ifdef DBG
if (_LoadCommandLineValue(lpszOverrideNoNameCommandLine,
lpServiceArgVectors[i], NULL))
{
continue;
}
#endif
}
LocalFree(lpServiceArgVectors);
}
////////////////////////////////////////////////////////////////
// Type conversions for LARGE_INTEGERs
void wtoli(LPCWSTR p, LARGE_INTEGER& liOut)
{
liOut.QuadPart = 0;
BOOL bNeg = FALSE;
if (*p == L'-')
{
bNeg = TRUE;
p++;
}
while (*p != L'\0')
{
liOut.QuadPart = 10 * liOut.QuadPart + (*p-L'0');
p++;
}
if (bNeg)
{
liOut.QuadPart *= -1;
}
}
void litow(LARGE_INTEGER& li, CString& sResult)
{
LARGE_INTEGER n;
n.QuadPart = li.QuadPart;
if (n.QuadPart == 0)
{
sResult = L"0";
}
else
{
CString sNeg;
sResult = L"";
if (n.QuadPart < 0)
{
sNeg = CString(L'-');
n.QuadPart *= -1;
}
while (n.QuadPart > 0)
{
sResult += CString(L'0' + static_cast<WCHAR>(n.QuadPart % 10));
n.QuadPart = n.QuadPart / 10;
}
sResult = sResult + sNeg;
}
sResult.MakeReverse();
}
// This wrapper function required to make prefast shut up when we are
// initializing a critical section in a constructor.
void
ExceptionPropagatingInitializeCriticalSection(LPCRITICAL_SECTION critsec)
{
__try
{
::InitializeCriticalSection(critsec);
}
//
// propagate the exception to our caller.
//
__except (EXCEPTION_CONTINUE_SEARCH)
{
}
}