|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1995 - 1999
//
// File: config.cpp
//
// Contents: ICertConfig IDispatch helper functions
//
//--------------------------------------------------------------------------
#include <pch.cpp>
#pragma hdrstop
#include <stdlib.h>
#include "csdisp.h"
#define __dwFILE__ __dwFILE_CERTLIB_CONFIG_CPP__
//+------------------------------------------------------------------------
// ICertConfig dispatch support
// TCHAR szRegKeyConfigClsid[] = wszCLASS_CERTCONFIG TEXT("\\Clsid");
//+------------------------------------
// Reset method:
static OLECHAR *_apszReset[] = { TEXT("Reset"), TEXT("Index"), };
//+------------------------------------
// Next method:
static OLECHAR *_apszNext[] = { TEXT("Next"), };
//+------------------------------------
// GetField method:
static OLECHAR *_apszGetField[] = { TEXT("GetField"), TEXT("strFieldName"), };
//+------------------------------------
// GetConfig method:
static OLECHAR *_apszGetConfig[] = { TEXT("GetConfig"), TEXT("Flags"), };
//+------------------------------------
// SetSharedFolder method:
static OLECHAR *_apszSetSharedFolder[] = { TEXT("SetSharedFolder"), TEXT("strSharedFolder"), };
//+------------------------------------
// Dispatch Table:
DISPATCHTABLE s_adtConfig[] = { #define CONFIG_RESET 0
DECLARE_DISPATCH_ENTRY(_apszReset)
#define CONFIG_NEXT 1
DECLARE_DISPATCH_ENTRY(_apszNext)
#define CONFIG_GETFIELD 2
DECLARE_DISPATCH_ENTRY(_apszGetField)
#define CONFIG_GETCONFIG 3
DECLARE_DISPATCH_ENTRY(_apszGetConfig)
#define CONFIG2_SETSHAREDFOLDER 4
DECLARE_DISPATCH_ENTRY(_apszSetSharedFolder) }; #define CCONFIGDISPATCH (ARRAYSIZE(s_adtConfig))
#define CCONFIGDISPATCH_V1 CONFIG2_SETSHAREDFOLDER
#define CCONFIGDISPATCH_V2 CCONFIGDISPATCH
DWORD s_acConfigDispatch[] = { CCONFIGDISPATCH_V2, CCONFIGDISPATCH_V1, };
IID const *s_apConfigiid[] = { &IID_ICertConfig2, &IID_ICertConfig, };
HRESULT Config_Init( IN DWORD Flags, OUT DISPATCHINTERFACE *pdiConfig) { HRESULT hr;
hr = DispatchSetup2( Flags, CLSCTX_INPROC_SERVER, wszCLASS_CERTCONFIG, &CLSID_CCertConfig, ARRAYSIZE(s_acConfigDispatch), // cver
s_apConfigiid, s_acConfigDispatch, s_adtConfig, pdiConfig); _JumpIfError(hr, error, "DispatchSetup2(ICertConfig)");
error: return(hr); }
VOID Config_Release( IN OUT DISPATCHINTERFACE *pdiConfig) { DispatchRelease(pdiConfig); }
HRESULT ConfigVerifyVersion( IN DISPATCHINTERFACE *pdiConfig, IN DWORD RequiredVersion) { HRESULT hr;
CSASSERT(NULL != pdiConfig && NULL != pdiConfig->pDispatchTable);
switch (pdiConfig->m_dwVersion) { case 1: CSASSERT( NULL == pdiConfig->pDispatch || CCONFIGDISPATCH_V1 == pdiConfig->m_cDispatchTable); break;
case 2: CSASSERT( NULL == pdiConfig->pDispatch || CCONFIGDISPATCH_V2 == pdiConfig->m_cDispatchTable); break;
default: hr = HRESULT_FROM_WIN32(ERROR_INTERNAL_ERROR); _JumpError(hr, error, "m_dwVersion"); } if (pdiConfig->m_dwVersion < RequiredVersion) { hr = E_NOTIMPL; _JumpError(hr, error, "old interface"); } hr = S_OK;
error: return(hr); }
HRESULT Config_Reset( IN DISPATCHINTERFACE *pdiConfig, IN LONG Index, OUT LONG *pCount) { HRESULT hr;
CSASSERT(NULL != pdiConfig && NULL != pdiConfig->pDispatchTable);
if (NULL != pdiConfig->pDispatch) { VARIANT avar[1];
avar[0].vt = VT_I4; avar[0].lVal = Index;
hr = DispatchInvoke( pdiConfig, CONFIG_RESET, ARRAYSIZE(avar), avar, VT_I4, pCount); _JumpIfError(hr, error, "Invoke(Reset)"); } else { hr = ((ICertConfig *) pdiConfig->pUnknown)->Reset(Index, pCount);
_JumpIfError(hr, error, "ICertConfig::Reset"); }
error: return(hr); }
HRESULT Config_Next( IN DISPATCHINTERFACE *pdiConfig, IN LONG *pIndex) { HRESULT hr;
CSASSERT(NULL != pdiConfig && NULL != pdiConfig->pDispatchTable);
if (NULL != pdiConfig->pDispatch) { hr = DispatchInvoke( pdiConfig, CONFIG_NEXT, 0, NULL, VT_I4, pIndex); _JumpIfError(hr, error, "Invoke(Next)"); } else { hr = ((ICertConfig *) pdiConfig->pUnknown)->Next(pIndex); if (S_FALSE != hr) { _JumpIfError(hr, error, "ICertConfig::Next"); } }
error: return(hr); }
HRESULT Config_GetField( IN DISPATCHINTERFACE *pdiConfig, IN WCHAR const *pwszField, OUT BSTR *pstr) { HRESULT hr; BSTR strField = NULL;
CSASSERT(NULL != pdiConfig && NULL != pdiConfig->pDispatchTable);
if (!ConvertWszToBstr(&strField, pwszField, -1)) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "ConvertWszToBstr"); } //wprintf(L"str=%ws, len=%u\n", strField, ((ULONG *) strField)[-1]);
if (NULL != pdiConfig->pDispatch) { VARIANT avar[1];
avar[0].vt = VT_BSTR; avar[0].bstrVal = strField;
hr = DispatchInvoke( pdiConfig, CONFIG_GETFIELD, ARRAYSIZE(avar), avar, VT_BSTR, pstr); _JumpIfError(hr, error, "Invoke(GetField)"); } else { hr = ((ICertConfig *) pdiConfig->pUnknown)->GetField(strField, pstr); _JumpIfErrorNotSpecific( hr, error, "ICertConfig::GetField", CERTSRV_E_PROPERTY_EMPTY); } hr = S_OK;
error: if (NULL != strField) { SysFreeString(strField); } return(hr); }
HRESULT Config_GetConfig( IN DISPATCHINTERFACE *pdiConfig, IN LONG Flags, OUT BSTR *pstrConfig) { HRESULT hr;
CSASSERT(NULL != pdiConfig && NULL != pdiConfig->pDispatchTable);
if (NULL != pdiConfig->pDispatch) { VARIANT avar[1];
avar[0].vt = VT_I4; avar[0].lVal = Flags;
hr = DispatchInvoke( pdiConfig, CONFIG_GETCONFIG, ARRAYSIZE(avar), avar, VT_BSTR, pstrConfig); _JumpIfError(hr, error, "Invoke(GetConfig)"); } else { hr = ((ICertConfig *) pdiConfig->pUnknown)->GetConfig(Flags, pstrConfig); _JumpIfError(hr, error, "ICertConfig::GetConfig"); }
error: return(hr); }
HRESULT Config2_SetSharedFolder( IN DISPATCHINTERFACE *pdiConfig, IN WCHAR const *pwszSharedFolder) { HRESULT hr; BSTR strSharedFolder = NULL;
CSASSERT(NULL != pdiConfig && NULL != pdiConfig->pDispatchTable);
hr = ConfigVerifyVersion(pdiConfig, 2); _JumpIfError(hr, error, "ConfigVerifyVersion");
if (!ConvertWszToBstr(&strSharedFolder, pwszSharedFolder, -1)) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "ConvertWszToBstr"); } //wprintf(L"str=%ws, len=%u\n", strSharedFolder, ((ULONG *) strSharedFolder)[-1]);
if (NULL != pdiConfig->pDispatch) { VARIANT avar[1];
avar[0].vt = VT_BSTR; avar[0].bstrVal = strSharedFolder;
hr = DispatchInvoke( pdiConfig, CONFIG2_SETSHAREDFOLDER, ARRAYSIZE(avar), avar, 0, NULL); _JumpIfError(hr, error, "Invoke(SetSharedFolder)"); } else { hr = ((ICertConfig2 *) pdiConfig->pUnknown)->SetSharedFolder(strSharedFolder); _JumpIfError(hr, error, "ICertConfig::GetConfig"); }
error: if (NULL != strSharedFolder) { SysFreeString(strSharedFolder); } return(hr); }
WCHAR const * const s_apwszFieldNames[] = { wszCONFIG_COMMONNAME, wszCONFIG_ORGUNIT, wszCONFIG_ORGANIZATION, wszCONFIG_LOCALITY, wszCONFIG_STATE, wszCONFIG_COUNTRY, wszCONFIG_CONFIG, wszCONFIG_EXCHANGECERTIFICATE, wszCONFIG_SIGNATURECERTIFICATE, wszCONFIG_DESCRIPTION, wszCONFIG_SERVER, wszCONFIG_AUTHORITY, wszCONFIG_SANITIZEDNAME, wszCONFIG_SHORTNAME, wszCONFIG_SANITIZEDSHORTNAME, wszCONFIG_FLAGS, }; #define CSTRING (sizeof(s_apwszFieldNames)/sizeof(s_apwszFieldNames[0]))
WCHAR const *s_apwszDisplayNames[CSTRING] = { wszCONFIG_COMMONNAME L":", wszCONFIG_ORGUNIT L":", wszCONFIG_ORGANIZATION L":", wszCONFIG_LOCALITY L":", wszCONFIG_STATE L":", wszCONFIG_COUNTRY L":", wszCONFIG_CONFIG L":", wszCONFIG_EXCHANGECERTIFICATE L":", wszCONFIG_SIGNATURECERTIFICATE L":", wszCONFIG_DESCRIPTION L":", wszCONFIG_SERVER L":", wszCONFIG_AUTHORITY L":", wszCONFIG_SANITIZEDNAME L":", wszCONFIG_SHORTNAME L":", wszCONFIG_SANITIZEDSHORTNAME L":", wszCONFIG_FLAGS L":", };
HRESULT ConfigDumpSetDisplayNames( IN WCHAR const * const *apwszFieldNames, IN WCHAR const * const *apwszDisplayNames, IN DWORD cNames) { DWORD i; DWORD j; HRESULT hr;
for (i = 0; i < cNames; i++) { for (j = 0; j < CSTRING; j++) { if (0 == mylstrcmpiS(s_apwszFieldNames[j], apwszFieldNames[i]) || (0 == LSTRCMPIS(s_apwszFieldNames[j], wszCONFIG_DESCRIPTION) && 0 == LSTRCMPIS(apwszFieldNames[i], wszCONFIG_COMMENT))) { s_apwszDisplayNames[j] = apwszDisplayNames[i]; break; } } if (CSTRING <= j) { hr = E_INVALIDARG; _JumpErrorStr(hr, error, "column name", apwszFieldNames[i]); } } hr = S_OK;
error: return(hr); }
HRESULT ConfigDumpEntry( IN DISPATCHINTERFACE *pdiConfig, IN WCHAR const *pwszEntry, // localized L"Entry"
IN LONG Index, // less than 0 skip index, entry, & suffix print
OPTIONAL IN WCHAR const *pwszSuffix) { HRESULT hr; DWORD i; BSTR strings[CSTRING];
for (i = 0; i < CSTRING; i++) { strings[i] = NULL; } for (i = 0; i < CSTRING; i++) { hr = Config_GetField(pdiConfig, s_apwszFieldNames[i], &strings[i]); _JumpIfError(hr, error, "Config_GetField"); } if (-1 < Index) { myConsolePrintf( L"%ws%ws %u:%ws%ws\n", 0 == Index? L"" : L"\n", pwszEntry, Index, NULL != pwszSuffix? L" " : L"", NULL != pwszSuffix? pwszSuffix : L""); } for (i = 0; i < CSTRING; i++) { myConsolePrintf(L" "); myConsolePrintString(24, s_apwszDisplayNames[i]); myConsolePrintf(L"\t`"); if (0 != wcscmp(s_apwszFieldNames[i], L"ExchangeCertificate")) { if (NULL != strings[i]) { myConsolePrintf(L"%ws", strings[i]); } } myConsolePrintf(L"'\n"); } hr = S_OK;
error: for (i = 0; i < CSTRING; i++) { if (NULL != strings[i]) { SysFreeString(strings[i]); } } return(hr); }
HRESULT ConfigDump( IN DWORD Flags, // See DispatchSetup() Flags
IN WCHAR const *pwszEntry, // localized L"Entry"
OPTIONAL IN WCHAR const *pwszLocalSuffix, // localized L"(Local)"
OPTIONAL IN WCHAR const *pwszMach1, OPTIONAL IN WCHAR const *pwszMach2) { HRESULT hr; LONG i; LONG count; LONG Index; BSTR strServer = NULL; WCHAR const *pwszSuffix; DISPATCHINTERFACE diConfig;
hr = Config_Init(Flags, &diConfig); _JumpIfError(hr, error, "Config_Init");
hr = Config_Reset(&diConfig, 0, &count); _JumpIfError(hr, error, "Config_Reset");
Index = 0; for (i = 0; i < count; i++) { hr = Config_Next(&diConfig, &Index); if (S_OK != hr && S_FALSE != hr) { _JumpError(hr, error, "Config_Next"); } hr = S_OK; if (-1 == Index) { break; }
pwszSuffix = NULL; if (NULL != pwszLocalSuffix) { hr = Config_GetField(&diConfig, wszCONFIG_SERVER, &strServer); _JumpIfError(hr, error, "Config_GetField");
if ((NULL != pwszMach1 && 0 == mylstrcmpiL(strServer, pwszMach1)) || (NULL != pwszMach2 && 0 == mylstrcmpiL(strServer, pwszMach2))) { pwszSuffix = pwszLocalSuffix; } } hr = ConfigDumpEntry(&diConfig, pwszEntry, Index, pwszSuffix); _JumpIfError(hr, error, "ConfigDumpEntry"); }
error: if (NULL != strServer) { SysFreeString(strServer); } Config_Release(&diConfig); return(hr); }
HRESULT ConfigGetConfig( IN DWORD Flags, IN DWORD dwUIFlag, OUT BSTR *pstrConfig) { HRESULT hr; DISPATCHINTERFACE diConfig;
hr = Config_Init(Flags, &diConfig); _JumpIfError(hr, error, "Config_Init");
hr = Config_GetConfig(&diConfig, dwUIFlag, pstrConfig); _JumpIfError(hr, error, "Config_GetConfig");
error: Config_Release(&diConfig); return(hr); }
DWORD myGetDisplayLength( IN WCHAR const *pwsz) { HRESULT hr; LONG ccol;
CSASSERT(NULL != pwsz);
ccol = WideCharToMultiByte( GetACP(), // CodePage
0, // dwFlags
pwsz, // lpWideCharStr
-1, // cchWideChar, -1 => L'\0' terminated
NULL, // lpMultiByteStr
0, // cbMultiByte
NULL, // lpDefaultChar
NULL); // lpUsedDefaultChar
if (0 >= ccol) { if (0 > ccol || L'\0' != *pwsz) { hr = myHLastError(); _PrintError(hr, "WideCharToMultiByte"); } ccol = wcslen(pwsz); } else { ccol--; // don't include trailing L'\0'
} //error:
return(ccol); }
LONG myConsolePrintString( IN DWORD ccolMin, IN WCHAR const *pwszString) { DWORD ccolDisplay; DWORD ccolRet;
ccolRet = myGetDisplayLength(pwszString); ccolDisplay = ccolRet; if (ccolMin < ccolDisplay) { ccolDisplay = ccolMin; } myConsolePrintf(L"%ws%*ws", pwszString, ccolMin - ccolDisplay, L""); return(ccolRet); }
static BOOL s_fConsolePrintfDisable = FALSE;
BOOL myConsolePrintfDisable( IN BOOL fDisable) { BOOL fDisableOld = s_fConsolePrintfDisable;
s_fConsolePrintfDisable = fDisable; return(fDisableOld); }
// Fall back to stdio if s_fConsolePrintfDisable is set OR
// if _vsnwprintf doesn't exist in ntdll.dll and msvcrt.dll OR
// if we run out of memory allocating a working buffer.
//
// Otherwise:
// if redirected, use WriteFile
// if not redirected, use WriteConsole
#define cwcBUFMIN 512
#define cwcBUFMAX (64 * 1024)
int __cdecl myConsolePrintf( OPTIONAL IN WCHAR const *pwszFmt, ...) { HRESULT hr; va_list pva; int cwc; DWORD cwcOut; HANDLE hStdOut; WCHAR wszBuf[cwcBUFMIN]; WCHAR *pwszBuf = wszBuf; DWORD cwcBuf = ARRAYSIZE(wszBuf); CHAR szAnsi[2 * cwcBUFMIN]; CHAR *pszAnsi = NULL; DWORD cchAnsi;
BOOL fRedirected = FALSE;
typedef int (__cdecl FN_VSNWPRINTF)( OUT wchar_t *, IN size_t, IN const wchar_t *, IN va_list);
HMODULE hModule; static FN_VSNWPRINTF *s_pfn = NULL;
if (NULL == pwszFmt) { pwszFmt = L"(null)"; } if (L'\0' == *pwszFmt) { cwcOut = 0; goto error; } if (NULL == s_pfn) { hModule = GetModuleHandle(TEXT("ntdll.dll")); if (NULL != hModule) { s_pfn = (FN_VSNWPRINTF *) GetProcAddress(hModule, "_vsnwprintf"); } if (NULL == s_pfn) { hModule = GetModuleHandle(TEXT("msvcrt.dll")); s_pfn = (FN_VSNWPRINTF *) GetProcAddress(hModule, "_vsnwprintf"); } } hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); if (NULL == s_pfn || s_fConsolePrintfDisable) { hStdOut = INVALID_HANDLE_VALUE; // use stdio fallback
}
cwc = 0; if (INVALID_HANDLE_VALUE != hStdOut) { for (;;) { va_start(pva, pwszFmt); cwc = (*s_pfn)(pwszBuf, cwcBuf, pwszFmt, pva); va_end(pva);
if (-1 != cwc) { break; } if (cwcBUFMAX <= cwcBuf) { _PrintError( HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW), "_vsnwprintf"); hStdOut = INVALID_HANDLE_VALUE; break; } if (pwszBuf != wszBuf) { LocalFree(pwszBuf); } cwcBuf *= 2; if (cwcBUFMAX < cwcBuf) { cwcBuf = cwcBUFMAX; } pwszBuf = (WCHAR *) LocalAlloc(LMEM_FIXED, cwcBuf * sizeof(WCHAR)); if (NULL == pwszBuf) { _PrintError(E_OUTOFMEMORY, "LocalAlloc"); hStdOut = INVALID_HANDLE_VALUE; break; } } }
if (INVALID_HANDLE_VALUE != hStdOut) { // time for output -- where are we going, to a file or the console?
switch (~FILE_TYPE_REMOTE & GetFileType(hStdOut)) { //case FILE_TYPE_PIPE:
//case FILE_TYPE_DISK:
default: // if redirected to a pipe or a file, don't use WriteConsole;
// it drops redirected output on the floor
fRedirected = TRUE; break;
case FILE_TYPE_UNKNOWN: _PrintError2( E_UNEXPECTED, "GetFileType(FILE_TYPE_UNKNOWN)", E_UNEXPECTED); hStdOut = INVALID_HANDLE_VALUE; s_fConsolePrintfDisable = TRUE; break; case FILE_TYPE_CHAR: break; } }
cwcOut = 0; if (INVALID_HANDLE_VALUE != hStdOut) { if (!fRedirected) { if (!WriteConsole(hStdOut, pwszBuf, cwc, &cwcOut, NULL)) { hr = myHLastError(); _PrintError(hr, "WriteConsole"); hStdOut = INVALID_HANDLE_VALUE; } } else // WriteConsole is out of the question
{ DWORD cch;
// Expand all \n chars to \r\n so the WriteFile ends up clean.
// Alloc new buffer big enough to hold two bytes per WCHAR for
// worst case MultiByte translation + inserted \r chars.
cchAnsi = 2 * (cwc + 1); if (ARRAYSIZE(szAnsi) >= cchAnsi) { pszAnsi = szAnsi; } else { pszAnsi = (LPSTR) LocalAlloc(LMEM_FIXED, cchAnsi); if (NULL == pszAnsi) { _PrintError(E_OUTOFMEMORY, "LocalAlloc"); hStdOut = INVALID_HANDLE_VALUE; } } cch = 0; if (INVALID_HANDLE_VALUE != hStdOut) { // if going to a file, we should not use console codepage, we
// should use ANSI codepage OR write unicode & a unicode
// filemarker at beginning of file.
// Since we don't know if this is the first thing in the file,
// let's go the ANSI route.
cch = WideCharToMultiByte( GetACP(), // GetConsoleOutputCP(),
0, pwszBuf, cwc, pszAnsi, cchAnsi, NULL, NULL); if (0 == cch) { hr = myHLastError(); _PrintError(hr, "WideCharToMultiByte"); _PrintErrorStr(GetACP(), "WideCharToMultiByte", pwszBuf); hStdOut = INVALID_HANDLE_VALUE; } } if (INVALID_HANDLE_VALUE != hStdOut) { CHAR *pchWork = pszAnsi; DWORD cchOut; // expand all \n chars to \r\n
cwcOut = cwc; for (unsigned int j = 0; j < cch; j++, pchWork++) { if (*pchWork == '\n') { // create a 1-char space before \n
MoveMemory(&pchWork[1], pchWork, cch - j);
// Fill with \r and skip past \r (this statement) and
// \n (automatic via loop incr).
*pchWork++ = '\r'; j++; cch++; // write one more char for each \n
} } CSASSERT(pchWork <= &pszAnsi[2 * cwc]); if (!WriteFile(hStdOut, pszAnsi, cch, &cchOut, NULL)) { hr = myHLastError(); _PrintError(hr, "WriteFile"); if (E_HANDLE == hr) { hStdOut = INVALID_HANDLE_VALUE; s_fConsolePrintfDisable = TRUE; } else { // This is the only case we drop output on the floor.
// Most likely cause is disk full, so stdio won't help.
} } } } // else WriteConsole
}
if (INVALID_HANDLE_VALUE == hStdOut) { BOOL fRetried = FALSE; for (;;) { ALIGNIOB(stdout); va_start(pva, pwszFmt); hr = S_OK; __try { cwcOut = vfwprintf(stdout, pwszFmt, pva); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { cwcOut = MAXDWORD; DBGPRINT(( DBG_SS_ERROR, "Exception %x: myConsolePrintf(%ws)", hr, pwszFmt)); } va_end(pva); #pragma warning(push)
#pragma warning(disable: 4127) // conditional expression is constant
if (S_OK == hr || fRetried || !IOBUNALIGNED(stdout)) #pragma warning(pop)
{ break; } fRetried = TRUE; } }
error: if (NULL != pwszBuf && wszBuf != pwszBuf) { LocalFree(pwszBuf); } if (NULL != pszAnsi && szAnsi != pszAnsi) { LocalFree(pszAnsi); } return((int) cwcOut); }
|