// 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(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(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) { } }