459 lines
10 KiB
C++
459 lines
10 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, ¤t, &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)
|
||
|
{
|
||
|
}
|
||
|
}
|
||
|
|