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.
3825 lines
81 KiB
3825 lines
81 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1995 - 1999
|
|
//
|
|
// File: view.cpp
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include <pch.cpp>
|
|
|
|
#pragma hdrstop
|
|
|
|
|
|
#include <esent.h>
|
|
#include <certdb.h>
|
|
#include "csprop.h"
|
|
|
|
#define __dwFILE__ __dwFILE_CERTUTIL_VIEW_CPP__
|
|
|
|
|
|
#define wszQUEUE L"Queue"
|
|
#define wszLOG L"Log"
|
|
#define wszLOGFAIL L"LogFail"
|
|
#define wszREVOKED L"Revoked"
|
|
|
|
#define wszCOLONQUEUE L":" wszQUEUE
|
|
#define wszCOLONLOG L":" wszLOG
|
|
#define wszCOLONLOGFAIL L":" wszLOGFAIL
|
|
#define wszCOLONREVOKED L":" wszREVOKED
|
|
|
|
|
|
ICertDB *g_pdb = NULL;
|
|
|
|
WCHAR const g_wszAttrib[] = L"attrib";
|
|
WCHAR const g_wszExt[] = L"ext";
|
|
WCHAR const g_wszCRL[] = L"CRL";
|
|
|
|
WCHAR const *g_apwszAllowedPrefixes[] =
|
|
{
|
|
g_wszAttrib,
|
|
g_wszExt,
|
|
NULL
|
|
};
|
|
|
|
BOOL
|
|
cuDBIsShutDownInProgress()
|
|
{
|
|
return(NULL == g_pdb);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
ParseToken(
|
|
OUT WCHAR *awcBuf,
|
|
IN DWORD cwcBuf,
|
|
IN BOOL fMatchPrefix,
|
|
OPTIONAL IN WCHAR const *pwszPrefix,
|
|
OPTIONAL IN WCHAR const * const *apwszAllowedPrefixes,
|
|
OPTIONAL OUT BOOL *pfAllColumns,
|
|
OUT WCHAR const **ppwszColumn,
|
|
IN OUT WCHAR const **ppwszNext);
|
|
|
|
|
|
WCHAR const *
|
|
cuwszPropType(
|
|
IN LONG PropType)
|
|
{
|
|
DWORD msgid;
|
|
|
|
switch (PropType)
|
|
{
|
|
case PROPTYPE_DATE:
|
|
msgid = IDS_PROPTYPE_DATE; // "Date"
|
|
break;
|
|
|
|
case PROPTYPE_LONG:
|
|
msgid = IDS_PROPTYPE_LONG; // "Long"
|
|
break;
|
|
|
|
case PROPTYPE_STRING:
|
|
msgid = IDS_PROPTYPE_STRING; // "String"
|
|
break;
|
|
|
|
case PROPTYPE_BINARY:
|
|
msgid = IDS_PROPTYPE_BINARY; // "Binary"
|
|
break;
|
|
|
|
default:
|
|
msgid = IDS_QUESTIONMARKS; // "???"
|
|
break;
|
|
}
|
|
return(myLoadResourceString(msgid));
|
|
}
|
|
|
|
|
|
typedef struct _COLINFO
|
|
{
|
|
BSTR strCol;
|
|
BSTR strColDisplay;
|
|
LONG type;
|
|
LONG maxlen;
|
|
LONG indexed;
|
|
} COLINFO;
|
|
|
|
|
|
VOID
|
|
cuPrintSchemaEntry(
|
|
OPTIONAL IN WCHAR const *pwszName,
|
|
IN WCHAR const *pwszDisplayName,
|
|
IN LONG Type,
|
|
IN LONG cbMax)
|
|
{
|
|
// wprintf(L" %-28ws %-28ws %-6ws", ...);
|
|
// OR
|
|
// wprintf(L"%-30ws %-6ws", ...);
|
|
|
|
if (NULL != pwszName)
|
|
{
|
|
wprintf(L" ");
|
|
myConsolePrintString(28, pwszName);
|
|
wprintf(L" ");
|
|
}
|
|
myConsolePrintString(NULL != pwszName? 28 : 30, pwszDisplayName);
|
|
wprintf(L" ");
|
|
myConsolePrintString(6, cuwszPropType(PROPTYPE_MASK & Type));
|
|
|
|
if (0 != cbMax)
|
|
{
|
|
wprintf(L" %u", cbMax);
|
|
}
|
|
if (PROPFLAGS_INDEXED & Type)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_INDEXED)); // " -- Indexed"
|
|
}
|
|
wprintf(wszNewLine);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DisplaySchema(
|
|
IN DISPATCHINTERFACE *pdiView,
|
|
IN LONG cColOut,
|
|
OPTIONAL IN OUT COLINFO *aColInfo,
|
|
IN BOOL fResult)
|
|
{
|
|
HRESULT hr;
|
|
LONG i;
|
|
BOOL fMustReleaseColumn = FALSE;
|
|
DISPATCHINTERFACE diViewColumn;
|
|
BSTR strCol = NULL;
|
|
BSTR strColDisplay = NULL;
|
|
LONG type;
|
|
LONG maxlen;
|
|
LONG indexed;
|
|
|
|
if (!g_fCryptSilent)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_SCHEMA_COLON)); // "Schema:"
|
|
wprintf(wszNewLine);
|
|
wprintf(myLoadResourceString(IDS_SCHEMA_COLUMNHEADERS)); // "Name..Type..."
|
|
wprintf(wszNewLine);
|
|
wprintf(myLoadResourceString(IDS_SCHEMA_COLUMNUNDERLINE)); // "____...____"
|
|
wprintf(wszNewLine);
|
|
}
|
|
|
|
hr = View_EnumCertViewColumn(
|
|
pdiView,
|
|
fResult? CVRC_COLUMN_RESULT : CVRC_COLUMN_SCHEMA,
|
|
&diViewColumn);
|
|
_JumpIfError(hr, error, "View_EnumCertViewColumn");
|
|
|
|
fMustReleaseColumn = TRUE;
|
|
|
|
for (i = 0; ; i++)
|
|
{
|
|
LONG ielt;
|
|
|
|
hr = ViewColumn_Next(&diViewColumn, &ielt);
|
|
if (S_FALSE == hr || (S_OK == hr && -1 == ielt))
|
|
{
|
|
CSASSERT(-1 == ielt);
|
|
CSASSERT(i == cColOut);
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
_JumpIfError(hr, error, "ViewColumn_Next");
|
|
CSASSERT(-1 != ielt);
|
|
CSASSERT(i < cColOut);
|
|
|
|
hr = ViewColumn_GetName(&diViewColumn, &strCol);
|
|
_JumpIfError(hr, error, "ViewColumn_GetName");
|
|
|
|
hr = ViewColumn_GetDisplayName(&diViewColumn, &strColDisplay);
|
|
_JumpIfError(hr, error, "ViewColumn_GetDisplayName");
|
|
|
|
hr = ViewColumn_GetType(&diViewColumn, &type);
|
|
_JumpIfError(hr, error, "ViewColumn_GetType");
|
|
|
|
hr = ViewColumn_GetMaxLength(&diViewColumn, &maxlen);
|
|
_JumpIfError(hr, error, "ViewColumn_GetType");
|
|
|
|
hr = ViewColumn_IsIndexed(&diViewColumn, &indexed);
|
|
_JumpIfError(hr, error, "ViewColumn_IsIndexed");
|
|
|
|
if (!g_fCryptSilent)
|
|
{
|
|
cuPrintSchemaEntry(
|
|
strCol,
|
|
strColDisplay,
|
|
type | (indexed? PROPFLAGS_INDEXED : 0),
|
|
maxlen);
|
|
}
|
|
if (NULL != aColInfo)
|
|
{
|
|
aColInfo[i].strCol = strCol;
|
|
strCol = NULL;
|
|
aColInfo[i].strColDisplay = strColDisplay;
|
|
strColDisplay = NULL;
|
|
aColInfo[i].type = type;
|
|
aColInfo[i].maxlen = maxlen;
|
|
aColInfo[i].indexed = indexed;
|
|
}
|
|
}
|
|
|
|
error:
|
|
if (NULL != strCol)
|
|
{
|
|
SysFreeString(strCol);
|
|
}
|
|
if (NULL != strColDisplay)
|
|
{
|
|
SysFreeString(strColDisplay);
|
|
}
|
|
if (fMustReleaseColumn)
|
|
{
|
|
ViewColumn_Release(&diViewColumn);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
LONG *g_askip = NULL;
|
|
LONG g_cskip = 0;
|
|
LONG g_iskip = 0;
|
|
BOOL g_fskip = FALSE;
|
|
|
|
LONG
|
|
GetSkip(
|
|
IN BOOL fAdvance)
|
|
{
|
|
LONG cskip = 0;
|
|
|
|
if (g_fskip)
|
|
{
|
|
if (g_iskip >= g_cskip)
|
|
{
|
|
g_iskip = 0;
|
|
}
|
|
cskip = g_askip[g_iskip];
|
|
if (fAdvance)
|
|
{
|
|
g_iskip++;
|
|
}
|
|
}
|
|
return(cskip);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
ParseSkipCounts(
|
|
IN WCHAR const *pwszField)
|
|
{
|
|
HRESULT hr;
|
|
LONG i;
|
|
WCHAR const *pwszNext;
|
|
WCHAR const *pwszColumn;
|
|
WCHAR awc[MAX_PATH];
|
|
|
|
pwszNext = pwszField;
|
|
for (i = 0; ; i++)
|
|
{
|
|
hr = ParseToken(
|
|
awc,
|
|
ARRAYSIZE(awc),
|
|
FALSE,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&pwszColumn,
|
|
&pwszNext);
|
|
if (S_FALSE == hr)
|
|
{
|
|
break;
|
|
}
|
|
_JumpIfError(hr, error, "ParseToken");
|
|
}
|
|
if (0 != i)
|
|
{
|
|
g_askip = (LONG *) LocalAlloc(LMEM_FIXED, i * sizeof(LONG));
|
|
if (NULL == g_askip)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "no memory for skip counts array");
|
|
}
|
|
g_cskip = i;
|
|
g_iskip = 0;
|
|
|
|
pwszNext = pwszField;
|
|
for (i = 0; ; i++)
|
|
{
|
|
hr = ParseToken(
|
|
awc,
|
|
ARRAYSIZE(awc),
|
|
FALSE,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&pwszColumn,
|
|
&pwszNext);
|
|
if (S_FALSE == hr)
|
|
{
|
|
break;
|
|
}
|
|
_JumpIfError(hr, error, "ParseToken");
|
|
|
|
hr = myGetSignedLong(pwszColumn, &g_askip[i]);
|
|
_JumpIfError(hr, error, "myGetLong");
|
|
|
|
//wprintf(L"ParseToken: %u: skip = '%ws' %d\n", i, pwszColumn, g_askip[i]);
|
|
}
|
|
CSASSERT(i == g_cskip);
|
|
g_fskip = TRUE;
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
ParseRestriction(
|
|
IN WCHAR const *pwszField,
|
|
OUT LONG *pColIndex,
|
|
OUT LONG *pSeekOperator,
|
|
OUT LONG *pSortOrder,
|
|
OUT WCHAR **ppwszColName,
|
|
OUT WCHAR **ppwszColValue)
|
|
{
|
|
HRESULT hr;
|
|
DWORD i;
|
|
LONG SortOrder;
|
|
LONG SeekOperator;
|
|
LONG SeekOperator2;
|
|
WCHAR *pwszColName = NULL;
|
|
WCHAR *pwszColValue = NULL;
|
|
|
|
*pColIndex = 0;
|
|
*ppwszColName = NULL;
|
|
*ppwszColValue = NULL;
|
|
|
|
SeekOperator = CVR_SEEK_GE;
|
|
SeekOperator2 = CVR_SEEK_GE; // might be used inadvertantly
|
|
SortOrder = CVR_SORT_NONE;
|
|
if (L'+' == *pwszField)
|
|
{
|
|
SortOrder = CVR_SORT_ASCEND;
|
|
pwszField++;
|
|
}
|
|
else if (myIsMinusSign(*pwszField))
|
|
{
|
|
SortOrder = CVR_SORT_DESCEND;
|
|
pwszField++;
|
|
}
|
|
while (L' ' == *pwszField)
|
|
{
|
|
pwszField++;
|
|
}
|
|
|
|
// Copy the column name into wszBuf, and advance the pointer
|
|
|
|
i = wcscspn(pwszField, L"<>=");
|
|
|
|
pwszColName = (WCHAR *) LocalAlloc(LMEM_FIXED, (i + 1) * sizeof(WCHAR));
|
|
if (NULL == pwszColName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
CopyMemory(pwszColName, pwszField, i * sizeof(WCHAR));
|
|
pwszField += i;
|
|
while (0 < i && L' ' == pwszColName[i - 1])
|
|
{
|
|
i--;
|
|
}
|
|
pwszColName[i] = L'\0';
|
|
|
|
switch (*pwszField)
|
|
{
|
|
case L'\0':
|
|
SeekOperator = CVR_SEEK_NONE;
|
|
break;
|
|
|
|
case L'<':
|
|
SeekOperator = CVR_SEEK_LT; // "<"
|
|
SeekOperator2 = CVR_SEEK_LE; // "<="
|
|
break;
|
|
|
|
case L'>':
|
|
SeekOperator = CVR_SEEK_GT; // ">"
|
|
SeekOperator2 = CVR_SEEK_GE; // ">="
|
|
break;
|
|
|
|
case L'=':
|
|
SeekOperator = CVR_SEEK_EQ; // "="
|
|
SeekOperator2 = CVR_SEEK_EQ; // "=="
|
|
break;
|
|
|
|
default:
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "bad seek operator");
|
|
}
|
|
if (L'\0' != *pwszField)
|
|
{
|
|
if (L'=' == *++pwszField)
|
|
{
|
|
SeekOperator = SeekOperator2;
|
|
pwszField++;
|
|
}
|
|
}
|
|
|
|
while (L' ' == *pwszField)
|
|
{
|
|
pwszField++;
|
|
}
|
|
i = wcslen(pwszField);
|
|
if (0 != i)
|
|
{
|
|
pwszColValue = (WCHAR *) LocalAlloc(
|
|
LMEM_FIXED,
|
|
(i + 1) * sizeof(WCHAR));
|
|
if (NULL == pwszColValue)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
wcscpy(pwszColValue, pwszField);
|
|
while (0 < i && L' ' == pwszColValue[i - 1])
|
|
{
|
|
i--;
|
|
}
|
|
pwszColValue[i] = L'\0';
|
|
cuConvertEscapeSequences(pwszColValue);
|
|
}
|
|
if (NULL == pwszColValue)
|
|
{
|
|
if (0 == LSTRCMPIS(pwszColName, wszCOLONQUEUE))
|
|
{
|
|
*pColIndex = CV_COLUMN_QUEUE_DEFAULT;
|
|
}
|
|
else if (0 == LSTRCMPIS(pwszColName, wszCOLONLOG))
|
|
{
|
|
*pColIndex = CV_COLUMN_LOG_DEFAULT;
|
|
}
|
|
else if (0 == LSTRCMPIS(pwszColName, wszCOLONLOGFAIL))
|
|
{
|
|
*pColIndex = CV_COLUMN_LOG_FAILED_DEFAULT;
|
|
}
|
|
else if (0 == LSTRCMPIS(pwszColName, wszCOLONREVOKED))
|
|
{
|
|
*pColIndex = CV_COLUMN_LOG_REVOKED_DEFAULT;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "bad special column name");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*ppwszColName = pwszColName;
|
|
*ppwszColValue = pwszColValue;
|
|
pwszColName = NULL;
|
|
pwszColValue = NULL;
|
|
}
|
|
*pSortOrder = SortOrder;
|
|
*pSeekOperator = SeekOperator;
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pwszColName)
|
|
{
|
|
LocalFree(pwszColName);
|
|
}
|
|
if (NULL != pwszColValue)
|
|
{
|
|
LocalFree(pwszColValue);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
ParseSpecialColumnValue(
|
|
IN WCHAR const *pwszColValue,
|
|
IN LONG ColType,
|
|
IN OUT LONG *pSeekOperator,
|
|
IN OUT LONG *pSortOrder,
|
|
OUT BOOL *pfOneRow,
|
|
OUT LONG *plSkip)
|
|
{
|
|
HRESULT hr;
|
|
BOOL fFirst;
|
|
|
|
*pfOneRow = FALSE;
|
|
*plSkip = 0;
|
|
|
|
switch (*pwszColValue)
|
|
{
|
|
case '^':
|
|
fFirst = TRUE;
|
|
break;
|
|
|
|
case '$':
|
|
fFirst = FALSE;
|
|
break;
|
|
|
|
default:
|
|
hr = S_OK;
|
|
goto error;
|
|
}
|
|
while (L' ' == *++pwszColValue)
|
|
;
|
|
|
|
if (L'\0' != *pwszColValue)
|
|
{
|
|
BOOL fInvalid;
|
|
|
|
switch (*pwszColValue)
|
|
{
|
|
case '+':
|
|
fInvalid = !fFirst;
|
|
break;
|
|
|
|
case '-':
|
|
fInvalid = fFirst;
|
|
break;
|
|
|
|
default:
|
|
hr = E_INVALIDARG;
|
|
_JumpErrorStr(hr, error, "expected signed skip count", pwszColValue);
|
|
}
|
|
if (fInvalid)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "skip to before start");
|
|
}
|
|
while (L' ' == *++pwszColValue)
|
|
;
|
|
|
|
hr = myGetLong(pwszColValue, plSkip);
|
|
_JumpIfError(hr, error, "bad numeric operand");
|
|
}
|
|
if (CVR_SEEK_EQ != *pSeekOperator || CVR_SORT_NONE != *pSortOrder)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "bad special restriction");
|
|
}
|
|
if (fFirst)
|
|
{
|
|
*pSortOrder = CVR_SORT_ASCEND;
|
|
}
|
|
else
|
|
{
|
|
*pSortOrder = CVR_SORT_DESCEND;
|
|
}
|
|
*pSeekOperator = CVR_SEEK_GE;
|
|
*pfOneRow = TRUE;
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
SetViewRestriction(
|
|
IN DISPATCHINTERFACE *pdiView,
|
|
IN WCHAR const *pwszField,
|
|
OUT BOOL *pfOneRow,
|
|
OUT LONG *plSkip)
|
|
{
|
|
HRESULT hr;
|
|
VARIANT var;
|
|
LONG ColIndex;
|
|
LONG ColType;
|
|
BSTR strColName = NULL;
|
|
LONG SeekOperator;
|
|
LONG SortOrder;
|
|
WCHAR *pwszColName = NULL;
|
|
WCHAR *pwszColValue = NULL;
|
|
BOOL fMustReleaseColumn = FALSE;
|
|
DISPATCHINTERFACE diViewColumn;
|
|
|
|
VariantInit(&var);
|
|
*pfOneRow = FALSE;
|
|
*plSkip = 0;
|
|
|
|
hr = ParseRestriction(
|
|
pwszField,
|
|
&ColIndex,
|
|
&SeekOperator,
|
|
&SortOrder,
|
|
&pwszColName,
|
|
&pwszColValue);
|
|
_JumpIfErrorStr(hr, error, "ParseRestriction", pwszField);
|
|
|
|
// no value to parse if a special column...
|
|
|
|
if (NULL == pwszColName)
|
|
{
|
|
CSASSERT(0 > ColIndex);
|
|
}
|
|
else
|
|
{
|
|
LONG ielt;
|
|
|
|
hr = View_GetColumnIndex(
|
|
pdiView,
|
|
CVRC_COLUMN_SCHEMA,
|
|
pwszColName,
|
|
&ColIndex);
|
|
_JumpIfErrorStr(hr, error, "View_GetColumnIndex", pwszColName);
|
|
|
|
hr = View_EnumCertViewColumn(
|
|
pdiView,
|
|
CVRC_COLUMN_SCHEMA,
|
|
&diViewColumn);
|
|
_JumpIfError(hr, error, "View_EnumCertViewColumn");
|
|
|
|
fMustReleaseColumn = TRUE;
|
|
|
|
hr = ViewColumn_Skip(&diViewColumn, ColIndex);
|
|
_JumpIfError(hr, error, "ViewColumn_Skip");
|
|
|
|
hr = ViewColumn_Next(&diViewColumn, &ielt);
|
|
if (S_OK == hr && -1 == ielt)
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
_JumpIfError(hr, error, "ViewColumn_Next");
|
|
|
|
hr = ViewColumn_GetName(&diViewColumn, &strColName);
|
|
_JumpIfError(hr, error, "GetName");
|
|
|
|
hr = ViewColumn_GetType(&diViewColumn, &ColType);
|
|
_JumpIfError(hr, error, "GetType");
|
|
|
|
hr = ParseSpecialColumnValue(
|
|
pwszColValue,
|
|
ColType,
|
|
&SeekOperator,
|
|
&SortOrder,
|
|
pfOneRow,
|
|
plSkip);
|
|
_JumpIfError(hr, error, "ParseSpecialColumnValue");
|
|
|
|
switch (ColType)
|
|
{
|
|
case PROPTYPE_LONG:
|
|
var.lVal = 0;
|
|
if (!*pfOneRow)
|
|
{
|
|
hr = myGetSignedLong(pwszColValue, &var.lVal);
|
|
_JumpIfError(hr, error, "bad numeric operand");
|
|
}
|
|
var.vt = VT_I4;
|
|
break;
|
|
|
|
case PROPTYPE_DATE:
|
|
var.date = 0;
|
|
if (!*pfOneRow)
|
|
{
|
|
hr = myWszLocalTimeToGMTDate(pwszColValue, &var.date);
|
|
_JumpIfError(hr, error, "invalid date format");
|
|
}
|
|
var.vt = VT_DATE;
|
|
cuDumpDate(&var.date);
|
|
break;
|
|
|
|
case PROPTYPE_STRING:
|
|
{
|
|
WCHAR const *pwsz = L"";
|
|
|
|
var.bstrVal = NULL;
|
|
if (!*pfOneRow)
|
|
{
|
|
pwsz = pwszColValue;
|
|
}
|
|
if (!ConvertWszToBstr(&var.bstrVal, pwsz, MAXDWORD))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "ConvertWszToBstr");
|
|
}
|
|
var.vt = VT_BSTR;
|
|
break;
|
|
}
|
|
|
|
case PROPTYPE_BINARY:
|
|
default:
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "not supported");
|
|
}
|
|
}
|
|
//wprintf(L"ColIndex=%x(%d) vt=%d\n", ColIndex, ColIndex, var.vt);
|
|
|
|
hr = View_SetRestriction(
|
|
pdiView,
|
|
ColIndex, // Restriction ColumnIndex
|
|
SeekOperator,
|
|
SortOrder,
|
|
&var); // pvarValue
|
|
_JumpIfError(hr, error, "View_SetRestriction");
|
|
|
|
error:
|
|
if (NULL != pwszColName)
|
|
{
|
|
LocalFree(pwszColName);
|
|
}
|
|
if (NULL != pwszColValue)
|
|
{
|
|
LocalFree(pwszColValue);
|
|
}
|
|
if (fMustReleaseColumn)
|
|
{
|
|
ViewColumn_Release(&diViewColumn);
|
|
}
|
|
if (NULL != strColName)
|
|
{
|
|
SysFreeString(strColName);
|
|
}
|
|
VariantClear(&var);
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuParseStrings(
|
|
IN WCHAR const *pwszStrings,
|
|
IN BOOL fMatchPrefix,
|
|
OPTIONAL IN WCHAR const *pwszPrefix,
|
|
OPTIONAL IN WCHAR const * const *apwszAllowedPrefixes,
|
|
OUT WCHAR ***papwszStrings,
|
|
OPTIONAL OUT BOOL *pfAllFields)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR const *pwszNext;
|
|
WCHAR awc[MAX_PATH];
|
|
DWORD i;
|
|
WCHAR const *pwszCurrent;
|
|
WCHAR **ppwsz;
|
|
|
|
if (NULL != pfAllFields)
|
|
{
|
|
*pfAllFields = FALSE;
|
|
}
|
|
*papwszStrings = NULL;
|
|
|
|
pwszNext = pwszStrings;
|
|
for (i = 0; ; i++)
|
|
{
|
|
hr = ParseToken(
|
|
awc,
|
|
ARRAYSIZE(awc),
|
|
fMatchPrefix,
|
|
pwszPrefix,
|
|
apwszAllowedPrefixes,
|
|
pfAllFields,
|
|
&pwszCurrent,
|
|
&pwszNext);
|
|
if (S_FALSE == hr)
|
|
{
|
|
break;
|
|
}
|
|
_JumpIfError(hr, error, "ParseToken");
|
|
}
|
|
if (0 != i)
|
|
{
|
|
*papwszStrings = (WCHAR **) LocalAlloc(
|
|
LMEM_FIXED | LMEM_ZEROINIT,
|
|
(i + 1) * sizeof(WCHAR *));
|
|
if (NULL == *papwszStrings)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "no memory for string array");
|
|
}
|
|
|
|
ppwsz = *papwszStrings;
|
|
pwszNext = pwszStrings;
|
|
for ( ; 0 < i; i--)
|
|
{
|
|
hr = ParseToken(
|
|
awc,
|
|
ARRAYSIZE(awc),
|
|
fMatchPrefix,
|
|
pwszPrefix,
|
|
apwszAllowedPrefixes,
|
|
pfAllFields,
|
|
&pwszCurrent,
|
|
&pwszNext);
|
|
CSASSERT(S_FALSE != hr);
|
|
_JumpIfError(hr, error, "ParseToken");
|
|
|
|
hr = myDupString(pwszCurrent, ppwsz);
|
|
_JumpIfError(hr, error, "myDupString");
|
|
|
|
ppwsz++;
|
|
}
|
|
*ppwsz = NULL;
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (S_OK != hr)
|
|
{
|
|
cuFreeStringArray(*papwszStrings);
|
|
*papwszStrings = NULL;
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
ParseViewRestrictions(
|
|
IN WCHAR const *pwszRestrictions,
|
|
OUT WCHAR ***papwszRestrictions)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = cuParseStrings(
|
|
pwszRestrictions,
|
|
FALSE,
|
|
NULL,
|
|
NULL,
|
|
papwszRestrictions,
|
|
NULL);
|
|
_JumpIfError(hr, error, "cuParseStrings");
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
ParseToken(
|
|
OUT WCHAR *awcBuf,
|
|
IN DWORD cwcBuf,
|
|
IN BOOL fMatchPrefix,
|
|
OPTIONAL IN WCHAR const *pwszPrefix,
|
|
OPTIONAL IN WCHAR const * const *apwszAllowedPrefixes,
|
|
OPTIONAL OUT BOOL *pfAllColumns,
|
|
OUT WCHAR const **ppwszColumn,
|
|
IN OUT WCHAR const **ppwszNext)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR const *pwsz;
|
|
WCHAR *pwszT;
|
|
WCHAR *pwszColumn;
|
|
DWORD cwc;
|
|
DWORD cwcPrefix = 0;
|
|
|
|
if (NULL != pwszPrefix)
|
|
{
|
|
cwcPrefix = wcslen(pwszPrefix);
|
|
}
|
|
while (TRUE)
|
|
{
|
|
// Grab the next comma-separated token, and trim white space.
|
|
|
|
awcBuf[0] = L'\0';
|
|
pwsz = *ppwszNext;
|
|
while (L' ' == *pwsz)
|
|
{
|
|
pwsz++;
|
|
}
|
|
cwc = wcscspn(pwsz, L",");
|
|
if (cwc >= cwcBuf)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
|
|
_JumpError(hr, error, "Buffer overflow");
|
|
}
|
|
CopyMemory(awcBuf, pwsz, cwc * sizeof(WCHAR));
|
|
awcBuf[cwc] = L'\0';
|
|
|
|
pwsz += cwc;
|
|
while (L',' == *pwsz)
|
|
{
|
|
pwsz++;
|
|
}
|
|
*ppwszNext = pwsz;
|
|
|
|
while (0 < cwc && L' ' == awcBuf[cwc - 1])
|
|
{
|
|
awcBuf[--cwc] = L'\0';
|
|
}
|
|
|
|
if (0 == cwc)
|
|
{
|
|
if (L'\0' == *pwsz)
|
|
{
|
|
*ppwszColumn = NULL;
|
|
hr = S_FALSE;
|
|
_JumpError2(hr, error, "end of list", hr);
|
|
}
|
|
continue;
|
|
}
|
|
pwszColumn = awcBuf; // assume no prefix
|
|
|
|
if (fMatchPrefix)
|
|
{
|
|
// Look for a colon separator that delimits a matching prefix.
|
|
// The separator must precede any relational operators:
|
|
|
|
cwc = wcscspn(awcBuf, L"<>=:");
|
|
pwszT = &awcBuf[cwc];
|
|
|
|
if (L':' != *pwszT)
|
|
{
|
|
if (NULL != pwszPrefix)
|
|
{
|
|
continue; // prefix missing, but expected
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pwszColumn = pwszT;
|
|
*pwszColumn++ = L'\0';
|
|
while (L' ' == *pwszColumn)
|
|
{
|
|
pwszColumn++;
|
|
}
|
|
while (pwszT > awcBuf && L' ' == *(pwszT - 1))
|
|
{
|
|
*--pwszT = L'\0';
|
|
}
|
|
|
|
if (NULL != apwszAllowedPrefixes)
|
|
{
|
|
WCHAR const * const *ppwsz;
|
|
|
|
for (ppwsz = apwszAllowedPrefixes; NULL != *ppwsz; ppwsz++)
|
|
{
|
|
if (0 == mylstrcmpiS(awcBuf, *ppwsz))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (NULL == *ppwsz)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpErrorStr(hr, error, "bad prefix", awcBuf);
|
|
}
|
|
}
|
|
if (NULL == pwszPrefix)
|
|
{
|
|
continue; // prefix not expected
|
|
}
|
|
if (pwszT - awcBuf != (LONG) cwcPrefix)
|
|
{
|
|
continue; // prefix length doesn't match
|
|
}
|
|
if (0 != mylstrcmpiS(awcBuf, pwszPrefix))
|
|
{
|
|
continue; // prefix doesn't match
|
|
}
|
|
}
|
|
if (NULL != pfAllColumns && 0 == LSTRCMPIS(pwszColumn, L"all"))
|
|
{
|
|
*pfAllColumns = TRUE;
|
|
continue;
|
|
}
|
|
}
|
|
*ppwszColumn = pwszColumn;
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
|
|
error:
|
|
if (S_OK != hr && 0 < cwcBuf)
|
|
{
|
|
awcBuf[0] = L'\0';
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
ParseViewColumns(
|
|
IN WCHAR const *pwszColumns,
|
|
IN WCHAR const *pwszPrefix,
|
|
OPTIONAL IN WCHAR const * const *apwszAllowedPrefixes,
|
|
OUT WCHAR ***papwszColumns,
|
|
OUT BOOL *pfAllColumns)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = cuParseStrings(
|
|
pwszColumns,
|
|
TRUE,
|
|
pwszPrefix,
|
|
apwszAllowedPrefixes,
|
|
papwszColumns,
|
|
pfAllColumns);
|
|
_JumpIfError(hr, error, "cuParseStrings");
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintRowIndex(
|
|
IN LONG iRow,
|
|
IN OUT BOOL *pfPrinted)
|
|
{
|
|
if (!*pfPrinted)
|
|
{
|
|
wprintf(wszNewLine);
|
|
wprintf(myLoadResourceString(IDS_FORMAT_ROWID), iRow); // "Row %u:"
|
|
wprintf(wszNewLine);
|
|
*pfPrinted = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
cuFreeStringArray(
|
|
IN OUT WCHAR **apwsz)
|
|
{
|
|
WCHAR **ppwsz;
|
|
|
|
if (NULL != apwsz)
|
|
{
|
|
for (ppwsz = apwsz; NULL != *ppwsz; ppwsz++)
|
|
{
|
|
myZeroDataString(*ppwsz); // possible password data
|
|
LocalFree(*ppwsz);
|
|
}
|
|
LocalFree(apwsz);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
cuFreeStringArrayA(
|
|
IN OUT char **apsz)
|
|
{
|
|
char **ppsz;
|
|
|
|
if (NULL != apsz)
|
|
{
|
|
for (ppsz = apsz; NULL != *ppsz; ppsz++)
|
|
{
|
|
LocalFree(*ppsz);
|
|
}
|
|
LocalFree(apsz);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpLongValue(
|
|
IN LONG longValue,
|
|
IN WCHAR const *pwszColumnName)
|
|
{
|
|
long aidMsg[20];
|
|
DWORD cidMsg;
|
|
DWORD i;
|
|
WCHAR const *pwszError = NULL;
|
|
WCHAR const *pwszMsg = NULL;
|
|
WCHAR awchr[cwcHRESULTSTRING];
|
|
BOOL fDisplayNumeric = TRUE;
|
|
BOOL fDisplayFlags = FALSE;
|
|
|
|
cidMsg = 0;
|
|
if (0 == LSTRCMPIS(
|
|
pwszColumnName,
|
|
wszPROPREQUESTDOT wszPROPREQUESTDISPOSITION))
|
|
{
|
|
switch (longValue)
|
|
{
|
|
case DB_DISP_ACTIVE: aidMsg[0] = IDS_DISP_ACTIVE; break;
|
|
case DB_DISP_PENDING: aidMsg[0] = IDS_DISP_PENDING; break;
|
|
case DB_DISP_FOREIGN: aidMsg[0] = IDS_DISP_FOREIGN_CERT; break;
|
|
case DB_DISP_KRA_CERT: aidMsg[0] = IDS_DISP_KRA_CERT; break;
|
|
case DB_DISP_CA_CERT: aidMsg[0] = IDS_DISP_CA_CERT; break;
|
|
case DB_DISP_CA_CERT_CHAIN:
|
|
aidMsg[0] = IDS_DISP_CA_CERT_CHAIN; break;
|
|
case DB_DISP_ISSUED: aidMsg[0] = IDS_DISP_ISSUED; break;
|
|
case DB_DISP_REVOKED: aidMsg[0] = IDS_DISP_REVOKED; break;
|
|
case DB_DISP_ERROR: aidMsg[0] = IDS_DISP_ERROR; break;
|
|
case DB_DISP_DENIED: aidMsg[0] = IDS_DISP_DENIED; break;
|
|
default: aidMsg[0] = IDS_QUESTIONMARKS; break;
|
|
}
|
|
cidMsg = 1;
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(pwszColumnName, wszPROPREQUESTDOT wszPROPREQUESTFLAGS))
|
|
{
|
|
if (CR_FLG_RENEWAL & longValue)
|
|
{
|
|
aidMsg[cidMsg++] = IDS_REQFLAGS_RENEWAL;
|
|
}
|
|
if (CR_FLG_FORCETELETEX & longValue)
|
|
{
|
|
aidMsg[cidMsg++] = IDS_REQFLAGS_FORCETELETEX;
|
|
}
|
|
if (CR_FLG_FORCEUTF8 & longValue)
|
|
{
|
|
aidMsg[cidMsg++] = IDS_REQFLAGS_FORCEUTF8;
|
|
}
|
|
if (CR_FLG_CAXCHGCERT & longValue)
|
|
{
|
|
aidMsg[cidMsg++] = IDS_REQFLAGS_CAXCHGCERT;
|
|
}
|
|
if (CR_FLG_ENROLLONBEHALFOF & longValue)
|
|
{
|
|
aidMsg[cidMsg++] = IDS_REQFLAGS_ENROLLONBEHALFOF;
|
|
}
|
|
if (CR_FLG_SUBJECTUNMODIFIED & longValue)
|
|
{
|
|
aidMsg[cidMsg++] = IDS_REQFLAGS_SUBJECTUNMODIFIED;
|
|
}
|
|
if (CR_FLG_VALIDENCRYPTEDKEYHASH & longValue)
|
|
{
|
|
aidMsg[cidMsg++] = IDS_REQFLAGS_VALIDENCRYPTEDKEYHASH;
|
|
}
|
|
if (CR_FLG_PUBLISHERROR & longValue)
|
|
{
|
|
aidMsg[cidMsg++] = IDS_REQFLAGS_PUBLISHERROR;
|
|
}
|
|
if (CR_FLG_CACROSSCERT & longValue)
|
|
{
|
|
aidMsg[cidMsg++] = IDS_REQFLAGS_CACROSSCERT;
|
|
}
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(pwszColumnName, wszPROPREQUESTDOT wszPROPREQUESTTYPE))
|
|
{
|
|
switch (CR_IN_FORMATMASK & longValue)
|
|
{
|
|
case CR_IN_FORMATANY: aidMsg[0] = IDS_REQTYPE_ANY; break;
|
|
case CR_IN_PKCS10: aidMsg[0] = IDS_REQTYPE_PKCS10; break;
|
|
case CR_IN_KEYGEN: aidMsg[0] = IDS_REQTYPE_KEYGEN; break;
|
|
case CR_IN_PKCS7: aidMsg[0] = IDS_REQTYPE_PKCS7; break;
|
|
case CR_IN_CMC: aidMsg[0] = IDS_REQTYPE_CMC; break;
|
|
default: aidMsg[0] = IDS_REQTYPE_UNKNOWN; break;
|
|
}
|
|
cidMsg = 1;
|
|
if (CR_IN_CRLS & longValue)
|
|
{
|
|
aidMsg[cidMsg++] = IDS_REQTYPE_CRLS;
|
|
}
|
|
if (CR_IN_FULLRESPONSE & longValue)
|
|
{
|
|
aidMsg[cidMsg++] = IDS_REQTYPE_FULLRESPONSE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(
|
|
pwszColumnName,
|
|
wszPROPREQUESTDOT wszPROPREQUESTSTATUSCODE) ||
|
|
0 == LSTRCMPIS(pwszColumnName, wszPROPCRLPUBLISHSTATUSCODE))
|
|
{
|
|
pwszError = myGetErrorMessageText(longValue, FALSE);
|
|
wprintf(L" %ws -- %ws", myHResultToString(awchr, longValue), pwszError);
|
|
fDisplayNumeric = FALSE;
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(
|
|
pwszColumnName,
|
|
wszPROPREQUESTDOT wszPROPREQUESTREVOKEDREASON))
|
|
{
|
|
aidMsg[0] = cuidCRLReason(longValue);
|
|
cidMsg = 1;
|
|
}
|
|
else
|
|
{
|
|
fDisplayFlags = TRUE;
|
|
}
|
|
|
|
if (fDisplayNumeric)
|
|
{
|
|
wprintf(L" 0x%x", longValue);
|
|
if (0 > longValue || 9 < longValue)
|
|
{
|
|
wprintf(L" (%d)", longValue);
|
|
}
|
|
}
|
|
if (0 != cidMsg)
|
|
{
|
|
WCHAR const *pwszComma = myLoadResourceString(IDS_SEPARATOR); // ", "
|
|
|
|
wprintf(L" -- ");
|
|
for (i = 0; i < cidMsg; i++)
|
|
{
|
|
wprintf(
|
|
L"%ws%ws",
|
|
0 == i? L"" : pwszComma,
|
|
myLoadResourceString(aidMsg[i]));
|
|
}
|
|
}
|
|
if (0 == LSTRCMPIS(pwszColumnName, wszPROPEXTFLAGS))
|
|
{
|
|
wprintf(L" -- %ws", cuwszFromExtFlags(longValue));
|
|
}
|
|
else if (0 == LSTRCMPIS(pwszColumnName, wszPROPCERTIFICATEISSUERNAMEID) ||
|
|
0 == LSTRCMPIS(pwszColumnName, wszPROPCRLNAMEID))
|
|
{
|
|
cuPrintPossibleObjectIdName(TEXT(szOID_CERTSRV_CA_VERSION));
|
|
wprintf(
|
|
L" %u.%u",
|
|
CANAMEIDTOICERT(longValue),
|
|
CANAMEIDTOIKEY(longValue));
|
|
}
|
|
wprintf(wszNewLine);
|
|
if (fDisplayFlags)
|
|
{
|
|
cuRegPrintDwordValue(FALSE, pwszColumnName, pwszColumnName, longValue);
|
|
}
|
|
if (NULL != pwszError)
|
|
{
|
|
LocalFree(const_cast<WCHAR *>(pwszError));
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT
|
|
GetBinaryColumnFormat(
|
|
IN WCHAR const *pwszColumnName,
|
|
OUT LONG *pFormat)
|
|
{
|
|
LONG Format = CV_OUT_BINARY;
|
|
|
|
if (0 == LSTRCMPIS(
|
|
pwszColumnName,
|
|
wszPROPREQUESTDOT wszPROPREQUESTRAWREQUEST))
|
|
{
|
|
Format = CV_OUT_BASE64REQUESTHEADER;
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(pwszColumnName, wszPROPRAWCERTIFICATE) ||
|
|
0 == LSTRCMPIS(
|
|
pwszColumnName,
|
|
wszPROPREQUESTDOT wszPROPREQUESTRAWOLDCERTIFICATE) ||
|
|
0 == LSTRCMPIS(pwszColumnName, wszPROPCERTIFICATERAWSMIMECAPABILITIES))
|
|
{
|
|
Format = CV_OUT_BASE64HEADER;
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(pwszColumnName, wszPROPCRLRAWCRL))
|
|
{
|
|
Format = CV_OUT_BASE64X509CRLHEADER;
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(pwszColumnName, wszPROPCERTIFICATERAWPUBLICKEY))
|
|
{
|
|
Format = CV_OUT_HEXADDR;
|
|
}
|
|
else
|
|
{
|
|
Format = CV_OUT_HEXASCIIADDR;
|
|
}
|
|
*pFormat = Format;
|
|
return(S_OK);
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpBinaryValue(
|
|
IN WCHAR const *pwszColName,
|
|
OPTIONAL IN WCHAR const *pwszObjId,
|
|
IN LONG Format,
|
|
IN BYTE const *pb,
|
|
IN DWORD cb,
|
|
OPTIONAL IN WCHAR const *pwszStringValue)
|
|
{
|
|
wprintf(wszNewLine);
|
|
if (NULL == pwszObjId ||
|
|
0 != LSTRCMPIS(pwszColName, wszPROPEXTRAWVALUE) ||
|
|
!cuDumpFormattedExtension(pwszObjId, pb, cb) ||
|
|
g_fVerbose)
|
|
{
|
|
if (NULL != pwszStringValue)
|
|
{
|
|
cuPrintCRLFString(NULL, pwszStringValue);
|
|
wprintf(wszNewLine);
|
|
}
|
|
else
|
|
{
|
|
DumpHex(
|
|
DH_NOADDRESS |
|
|
(CV_OUT_HEX == Format? DH_NOASCIIHEX : 0),
|
|
pb,
|
|
cb);
|
|
}
|
|
}
|
|
if (g_fVerbose &&
|
|
(CV_OUT_BASE64HEADER == Format ||
|
|
CV_OUT_BASE64REQUESTHEADER == Format ||
|
|
CV_OUT_BASE64X509CRLHEADER == Format))
|
|
{
|
|
BOOL fVerboseOld = g_fVerbose;
|
|
|
|
if (g_fVerbose)
|
|
{
|
|
g_fVerbose--;
|
|
}
|
|
cuDumpAsnBinary(pb, cb, MAXDWORD);
|
|
g_fVerbose = fVerboseOld;
|
|
wprintf(wszNewLine);
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
ShouldDisplay(
|
|
IN WCHAR const *pwszName,
|
|
IN BOOL fDisplay,
|
|
IN WCHAR const * const *apwsz)
|
|
{
|
|
if (!fDisplay)
|
|
{
|
|
WCHAR const * const *ppwsz;
|
|
|
|
for (ppwsz = apwsz; NULL != *ppwsz; ppwsz++)
|
|
{
|
|
if (0 == mylstrcmpiL(pwszName, *ppwsz))
|
|
{
|
|
fDisplay = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return(fDisplay);
|
|
}
|
|
|
|
typedef struct _DBSTATS
|
|
{
|
|
DWORD cTotal;
|
|
DWORD cbTotal;
|
|
DWORD cbMax;
|
|
} DBSTATS;
|
|
|
|
|
|
VOID
|
|
UpdateStats(
|
|
IN OUT DBSTATS *pstats,
|
|
IN DWORD cbProp)
|
|
{
|
|
if (0 != cbProp)
|
|
{
|
|
pstats->cTotal++;
|
|
pstats->cbTotal += cbProp;
|
|
if (pstats->cbMax < cbProp)
|
|
{
|
|
pstats->cbMax = cbProp;
|
|
}
|
|
//wprintf(L"c=%u cb=%x(%x)\n", pstats->cTotal, pstats->cbTotal, cbProp);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
CombineStats(
|
|
IN OUT DBSTATS *pstats,
|
|
IN DBSTATS const *pstats2)
|
|
{
|
|
pstats->cTotal += pstats2->cTotal;
|
|
pstats->cbTotal += pstats2->cbTotal;
|
|
if (pstats->cbMax < pstats2->cbMax)
|
|
{
|
|
pstats->cbMax = pstats2->cbMax;
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpStats(
|
|
IN DBSTATS const *pstats,
|
|
IN DWORD idStats)
|
|
{
|
|
wprintf(
|
|
myLoadResourceString(IDS_VIEW_STATS), // "%u %ws, Total Size = %u, Max Size = %u, Ave Size = %u",
|
|
pstats->cTotal,
|
|
myLoadResourceString(idStats),
|
|
pstats->cbTotal,
|
|
pstats->cbMax,
|
|
0 != pstats->cTotal? pstats->cbTotal / pstats->cTotal : 0);
|
|
wprintf(wszNewLine);
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpViewStats(
|
|
IN DWORD cRowTotal,
|
|
IN DBSTATS const *pstatsRowProperties,
|
|
IN DBSTATS const *pstatsAttributes,
|
|
IN DBSTATS const *pstatsExtensions)
|
|
{
|
|
if (!g_fCryptSilent)
|
|
{
|
|
DBSTATS statsSum;
|
|
|
|
wprintf(wszNewLine);
|
|
wprintf(
|
|
myLoadResourceString(IDS_VIEW_ROWS), // "%u Rows"
|
|
cRowTotal);
|
|
wprintf(wszNewLine);
|
|
|
|
DumpStats(pstatsRowProperties, IDS_VIEW_ROWPROPERTIES); // "Row Properties"
|
|
DumpStats(pstatsAttributes, IDS_VIEW_ATTRIBUTES); // "Request Attributes"
|
|
DumpStats(pstatsExtensions, IDS_VIEW_EXTENSIONS); // "Certificate Extensions"
|
|
|
|
statsSum = *pstatsRowProperties;
|
|
CombineStats(&statsSum, pstatsAttributes);
|
|
CombineStats(&statsSum, pstatsExtensions);
|
|
|
|
DumpStats(&statsSum, IDS_VIEW_TOTALFIELDS); // "Total Fields"
|
|
}
|
|
}
|
|
|
|
|
|
#define VDQ_NONE 0
|
|
#define VDQ_SCHEMA 1
|
|
#define VDQ_QUEUE 2
|
|
#define VDQ_LOG 3
|
|
#define VDQ_LOGFAIL 4
|
|
#define VDQ_REVOKED 5
|
|
|
|
|
|
HRESULT
|
|
verbViewDump(
|
|
IN WCHAR const *pwszOption,
|
|
IN WCHAR const *pwszTable,
|
|
IN WCHAR const *pwszSkipCounts,
|
|
IN WCHAR const *pwszField3,
|
|
IN WCHAR const *pwszField4)
|
|
{
|
|
HRESULT hr;
|
|
BOOL fSchema = g_wszSchema == pwszOption;
|
|
DWORD vdq = VDQ_NONE;
|
|
LONG cvColDefault = 0;
|
|
DISPATCHINTERFACE diView;
|
|
DISPATCHINTERFACE diViewColumn;
|
|
DISPATCHINTERFACE diViewRow;
|
|
DISPATCHINTERFACE diViewAttribute;
|
|
DISPATCHINTERFACE diViewExtension;
|
|
BOOL fMustRelease = FALSE;
|
|
BOOL fMustReleaseColumn = FALSE;
|
|
BOOL fMustReleaseAttribute = FALSE;
|
|
BOOL fMustReleaseExtension = FALSE;
|
|
BOOL fMustReleaseRow = FALSE;
|
|
LONG i;
|
|
LONG cColFull;
|
|
LONG cColOut;
|
|
COLINFO *aColInfo = NULL;
|
|
LONG iRow;
|
|
LONG RowIndex;
|
|
LONG iCol;
|
|
LONG ColIndex;
|
|
LONG iAttribute;
|
|
LONG AttributeIndex;
|
|
LONG iExtension;
|
|
LONG ExtensionIndex;
|
|
BSTR strName = NULL;
|
|
BSTR strObjId = NULL;
|
|
BSTR strValue = NULL;
|
|
BSTR strValueBinary = NULL;
|
|
WCHAR const *pwszExtensionFormat;
|
|
WCHAR **apwszRestrictions = NULL;
|
|
WCHAR **apwszColumns = NULL;
|
|
WCHAR **apwszAttributes = NULL;
|
|
WCHAR **apwszExtensions = NULL;
|
|
WCHAR **ppwsz;
|
|
BOOL fOneRow = FALSE;
|
|
LONG lSkip = 0;
|
|
BOOL fAllColumns;
|
|
BOOL fAllAttributes = FALSE;
|
|
BOOL fAllExtensions = FALSE;
|
|
BOOL fSkip;
|
|
DWORD cbProp;
|
|
DWORD cRowTotal = 0;
|
|
DBSTATS statsRowProperties;
|
|
DBSTATS statsAttributes;
|
|
DBSTATS statsExtensions;
|
|
DWORD cvrcTable = CVRC_TABLE_REQCERT;
|
|
WCHAR const *pwszDefaultRestriction = NULL;
|
|
|
|
if (NULL != pwszTable)
|
|
{
|
|
if (0 == mylstrcmpiS(pwszTable, g_wszSchema))
|
|
{
|
|
fSchema = TRUE;
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(pwszTable, wszQUEUE))
|
|
{
|
|
vdq = VDQ_QUEUE;
|
|
pwszDefaultRestriction = wszCOLONQUEUE;
|
|
cvColDefault = CV_COLUMN_QUEUE_DEFAULT;
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(pwszTable, wszLOG))
|
|
{
|
|
vdq = VDQ_LOG;
|
|
pwszDefaultRestriction = wszCOLONLOG;
|
|
cvColDefault = CV_COLUMN_LOG_DEFAULT;
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(pwszTable, wszLOGFAIL))
|
|
{
|
|
vdq = VDQ_LOGFAIL;
|
|
pwszDefaultRestriction = wszCOLONLOGFAIL;
|
|
cvColDefault = CV_COLUMN_LOG_DEFAULT;
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(pwszTable, wszREVOKED))
|
|
{
|
|
vdq = VDQ_REVOKED;
|
|
pwszDefaultRestriction = wszCOLONREVOKED;
|
|
cvColDefault = CV_COLUMN_LOG_REVOKED_DEFAULT;
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(pwszTable, g_wszExt))
|
|
{
|
|
cvrcTable = CVRC_TABLE_EXTENSIONS;
|
|
//cvColDefault = CV_COLUMN_EXTENSION_DEFAULT;
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(pwszTable, g_wszAttrib))
|
|
{
|
|
cvrcTable = CVRC_TABLE_ATTRIBUTES;
|
|
//cvColDefault = CV_COLUMN_ATTRIBUTE_DEFAULT;
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(pwszTable, g_wszCRL))
|
|
{
|
|
cvrcTable = CVRC_TABLE_CRL;
|
|
//cvColDefault = CV_COLUMN_CRL_DEFAULT;
|
|
}
|
|
else if (NULL == pwszSkipCounts && iswdigit(*pwszTable))
|
|
{
|
|
pwszSkipCounts = pwszTable;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "bad view/table name");
|
|
}
|
|
}
|
|
|
|
if (NULL != pwszSkipCounts)
|
|
{
|
|
hr = ParseSkipCounts(pwszSkipCounts);
|
|
_JumpIfError(hr, error, "ParseSkipCounts");
|
|
}
|
|
|
|
hr = View_Init(g_DispatchFlags, &diView);
|
|
_JumpIfError(hr, error, "View_Init");
|
|
|
|
fMustRelease = TRUE;
|
|
|
|
hr = View_OpenConnection(&diView, g_pwszConfig);
|
|
_JumpIfError(hr, error, "View_OpenConnection");
|
|
|
|
if (CVRC_TABLE_REQCERT != cvrcTable)
|
|
{
|
|
hr = View2_SetTable(&diView, cvrcTable);
|
|
_JumpIfError(hr, error, "View2_SetTable");
|
|
}
|
|
|
|
if (NULL != g_pwszRestrict)
|
|
{
|
|
hr = ParseViewRestrictions(g_pwszRestrict, &apwszRestrictions);
|
|
_JumpIfError(hr, error, "ParseViewRestrictions");
|
|
|
|
if (NULL == apwszRestrictions)
|
|
{
|
|
hr = E_POINTER; // would have AV'd anyway
|
|
_JumpError(hr, error, "apwszRestrictions==NULL");
|
|
}
|
|
|
|
for (ppwsz = apwszRestrictions; NULL != *ppwsz; ppwsz++)
|
|
{
|
|
BOOL f;
|
|
LONG l;
|
|
|
|
hr = SetViewRestriction(&diView, *ppwsz, &f, &l);
|
|
_JumpIfErrorStr(hr, error, "SetViewRestriction", *ppwsz);
|
|
|
|
if (f)
|
|
{
|
|
fOneRow = TRUE;
|
|
lSkip = l;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if (NULL != pwszDefaultRestriction)
|
|
{
|
|
hr = SetViewRestriction(&diView, pwszDefaultRestriction, &fOneRow, &lSkip);
|
|
_JumpIfError(hr, error, "SetViewRestriction");
|
|
}
|
|
|
|
// If not a special default view, and no output columns were specified
|
|
// for the requests+certs table, include all attributes and extensions.
|
|
|
|
if (NULL == pwszDefaultRestriction &&
|
|
NULL == g_pwszOut &&
|
|
CVRC_TABLE_REQCERT == cvrcTable)
|
|
{
|
|
fAllAttributes = TRUE;
|
|
fAllExtensions = TRUE;
|
|
}
|
|
|
|
hr = View_GetColumnCount(&diView, CVRC_COLUMN_SCHEMA, &cColFull);
|
|
_JumpIfError(hr, error, "View_GetColumnCount");
|
|
|
|
if (NULL != g_pwszOut)
|
|
{
|
|
hr = ParseViewColumns(
|
|
g_pwszOut,
|
|
NULL,
|
|
NULL,
|
|
&apwszColumns,
|
|
&fAllColumns);
|
|
_JumpIfError(hr, error, "ParseViewColumns");
|
|
|
|
hr = ParseViewColumns(
|
|
g_pwszOut,
|
|
g_wszAttrib,
|
|
g_apwszAllowedPrefixes,
|
|
&apwszAttributes,
|
|
&fAllAttributes);
|
|
_JumpIfError(hr, error, "ParseViewColumns");
|
|
|
|
hr = ParseViewColumns(
|
|
g_pwszOut,
|
|
g_wszExt,
|
|
NULL,
|
|
&apwszExtensions,
|
|
&fAllExtensions);
|
|
_JumpIfError(hr, error, "ParseViewColumns");
|
|
|
|
if (NULL == apwszColumns)
|
|
{
|
|
if (!g_fReverse)
|
|
{
|
|
hr = View_SetResultColumnCount(&diView, 0);
|
|
_JumpIfError(hr, error, "View_SetResultColumnCount");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (ppwsz = apwszColumns; NULL != *ppwsz; ppwsz++)
|
|
;
|
|
|
|
hr = View_SetResultColumnCount(
|
|
&diView,
|
|
SAFE_SUBTRACT_POINTERS(ppwsz, apwszColumns));
|
|
_JumpIfError(hr, error, "View_SetResultColumnCount");
|
|
|
|
for (ppwsz = apwszColumns; NULL != *ppwsz; ppwsz++)
|
|
{
|
|
hr = View_GetColumnIndex(
|
|
&diView,
|
|
CVRC_COLUMN_SCHEMA,
|
|
*ppwsz,
|
|
&ColIndex);
|
|
_JumpIfErrorStr(hr, error, "View_GetColumnIndex", *ppwsz);
|
|
|
|
hr = View_SetResultColumn(&diView, ColIndex);
|
|
_JumpIfError(hr, error, "View_SetResultColumn");
|
|
}
|
|
}
|
|
}
|
|
else if (NULL == pwszDefaultRestriction)
|
|
{
|
|
if (g_fReverse)
|
|
{
|
|
hr = View_SetResultColumnCount(&diView, cColFull + 1);
|
|
_JumpIfError(hr, error, "View_SetResultColumnCount");
|
|
|
|
hr = View_SetResultColumn(&diView, 0);
|
|
_JumpIfError(hr, error, "View_SetResultColumn(0)");
|
|
|
|
for (i = cColFull; i > 0; i--)
|
|
{
|
|
hr = View_SetResultColumn(&diView, i - 1);
|
|
_JumpIfError(hr, error, "View_SetResultColumn");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = View_SetResultColumnCount(&diView, cColFull);
|
|
_JumpIfError(hr, error, "View_SetResultColumnCount");
|
|
|
|
for (i = 0; i < cColFull; i++)
|
|
{
|
|
hr = View_SetResultColumn(&diView, i);
|
|
_JumpIfError(hr, error, "View_SetResultColumn");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Use the default set of columns for the specified special view.
|
|
|
|
CSASSERT(0 > cvColDefault);
|
|
|
|
hr = View_SetResultColumnCount(&diView, cvColDefault);
|
|
_JumpIfError(hr, error, "View_SetResultColumnCount");
|
|
}
|
|
|
|
hr = View_OpenView(&diView, &diViewRow);
|
|
_JumpIfError(hr, error, "View_OpenView");
|
|
fMustReleaseRow = TRUE;
|
|
|
|
hr = View_GetColumnCount(&diView, CVRC_COLUMN_RESULT, &cColOut);
|
|
_JumpIfError(hr, error, "View_GetColumnCount");
|
|
|
|
aColInfo = (COLINFO *) LocalAlloc(
|
|
LMEM_FIXED | LMEM_ZEROINIT,
|
|
cColOut * sizeof(aColInfo[0]));
|
|
if (NULL == aColInfo)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "no memory for column info array");
|
|
}
|
|
|
|
if (fSchema)
|
|
{
|
|
hr = DisplaySchema(&diView, cColFull, NULL, FALSE);
|
|
_JumpIfError(hr, error, "DisplaySchema");
|
|
|
|
goto error;
|
|
}
|
|
|
|
if (0 != cColOut)
|
|
{
|
|
hr = DisplaySchema(&diView, cColOut, aColInfo, TRUE);
|
|
_JumpIfError(hr, error, "DisplaySchema");
|
|
}
|
|
|
|
ZeroMemory(&statsRowProperties, sizeof(statsRowProperties));
|
|
ZeroMemory(&statsAttributes, sizeof(statsAttributes));
|
|
ZeroMemory(&statsExtensions, sizeof(statsExtensions));
|
|
|
|
hr = ViewRow_Skip(&diViewRow, lSkip);
|
|
_JumpIfError(hr, error, "ViewRow_Skip");
|
|
|
|
for (iRow = 1; ; iRow++)
|
|
{
|
|
BOOL fRowPrinted;
|
|
BOOL fHeaderPrinted;
|
|
BOOL fExtraNewLine;
|
|
LONG cskip;
|
|
|
|
if (NULL != strObjId)
|
|
{
|
|
SysFreeString(strObjId);
|
|
strObjId = NULL;
|
|
}
|
|
cskip = GetSkip(TRUE);
|
|
switch (cskip)
|
|
{
|
|
case 0:
|
|
break;
|
|
|
|
case 101:
|
|
hr = ViewRow_Reset(&diViewRow);
|
|
_JumpIfError(hr, error, "ViewRow_Reset");
|
|
|
|
iRow = 1;
|
|
break;
|
|
|
|
case 102:
|
|
{
|
|
DISPATCHINTERFACE diViewRowClone;
|
|
|
|
hr = ViewRow_Clone(&diViewRow, &diViewRowClone);
|
|
_JumpIfError(hr, error, "ViewRow_Clone");
|
|
|
|
ViewRow_Release(&diViewRow);
|
|
diViewRow = diViewRowClone; // structure assignment
|
|
goto done;
|
|
}
|
|
|
|
case 103:
|
|
goto done;
|
|
|
|
default:
|
|
hr = ViewRow_Skip(&diViewRow, cskip);
|
|
_JumpIfError(hr, error, "ViewRow_Skip");
|
|
|
|
iRow += cskip;
|
|
}
|
|
|
|
hr = ViewRow_Next(&diViewRow, &RowIndex);
|
|
if (S_FALSE == hr || (S_OK == hr && -1 == RowIndex))
|
|
{
|
|
LONG MaxIndex;
|
|
|
|
hr = ViewRow_GetMaxIndex(&diViewRow, &MaxIndex);
|
|
_JumpIfError(hr, error, "ViewRow_GetMaxIndex");
|
|
|
|
if (!g_fCryptSilent)
|
|
{
|
|
wprintf(
|
|
L"\n%ws: %u\n",
|
|
myLoadResourceString(IDS_MAXINDEX), // "Maximum Row Index"
|
|
MaxIndex);
|
|
}
|
|
if (101 == GetSkip(FALSE))
|
|
{
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
_JumpIfError(hr, error, "ViewRow_Next");
|
|
CSASSERT(RowIndex == iRow + lSkip);
|
|
|
|
cRowTotal++;
|
|
fRowPrinted = FALSE;
|
|
fExtraNewLine = FALSE;
|
|
|
|
if (fMustReleaseColumn)
|
|
{
|
|
ViewColumn_Release(&diViewColumn);
|
|
fMustReleaseColumn = FALSE;
|
|
}
|
|
|
|
hr = ViewRow_EnumCertViewColumn(&diViewRow, &diViewColumn);
|
|
_JumpIfError(hr, error, "ViewRow_EnumCertViewColumn");
|
|
|
|
fMustReleaseColumn = TRUE;
|
|
|
|
for (iCol = 0; ; iCol++)
|
|
{
|
|
LONG Format;
|
|
LONG longValue;
|
|
DATE dateValue;
|
|
VOID *pretval;
|
|
|
|
if (NULL != strValue)
|
|
{
|
|
SysFreeString(strValue);
|
|
strValue = NULL;
|
|
}
|
|
if (NULL != strValueBinary)
|
|
{
|
|
SysFreeString(strValueBinary);
|
|
strValueBinary = NULL;
|
|
}
|
|
hr = ViewColumn_Next(&diViewColumn, &ColIndex);
|
|
if (S_FALSE == hr || (S_OK == hr && -1 == ColIndex))
|
|
{
|
|
break;
|
|
}
|
|
_JumpIfError(hr, error, "ViewColumn_Next");
|
|
CSASSERT(ColIndex == iCol);
|
|
|
|
hr = ViewColumn_GetType(&diViewColumn, &i);
|
|
_JumpIfError(hr, error, "GetType");
|
|
|
|
CSASSERT(i == aColInfo[iCol].type);
|
|
|
|
PrintRowIndex(iRow, &fRowPrinted);
|
|
fExtraNewLine = TRUE;
|
|
|
|
wprintf(L" %ws:", aColInfo[iCol].strColDisplay);
|
|
|
|
Format = CV_OUT_BINARY;
|
|
switch (aColInfo[iCol].type)
|
|
{
|
|
case PROPTYPE_LONG:
|
|
pretval = &longValue;
|
|
break;
|
|
|
|
case PROPTYPE_DATE:
|
|
pretval = &dateValue;
|
|
break;
|
|
|
|
case PROPTYPE_STRING:
|
|
pretval = &strValue;
|
|
break;
|
|
|
|
case PROPTYPE_BINARY:
|
|
pretval = &strValue;
|
|
hr = GetBinaryColumnFormat(aColInfo[iCol].strCol, &Format);
|
|
_JumpIfError(hr, error, "GetBinaryColumnFormat");
|
|
|
|
break;
|
|
|
|
default:
|
|
hr = E_FAIL;
|
|
_JumpError(hr, error, "bad proptype");
|
|
}
|
|
hr = ViewColumn_GetValue(
|
|
&diViewColumn,
|
|
Format,
|
|
aColInfo[iCol].type,
|
|
pretval);
|
|
if (S_OK != hr)
|
|
{
|
|
wprintf(L" ");
|
|
wprintf(myLoadResourceString(IDS_PROP_EMPTY)); // "EMPTY"
|
|
wprintf(wszNewLine);
|
|
_PrintIfErrorStr2(
|
|
hr,
|
|
"ViewColumn_GetValue",
|
|
aColInfo[iCol].strColDisplay,
|
|
CERTSRV_E_PROPERTY_EMPTY);
|
|
}
|
|
else
|
|
{
|
|
|
|
cbProp = 0;
|
|
switch (aColInfo[iCol].type)
|
|
{
|
|
case PROPTYPE_LONG:
|
|
DumpLongValue(longValue, aColInfo[iCol].strCol);
|
|
cbProp = sizeof(LONG);
|
|
break;
|
|
|
|
case PROPTYPE_DATE:
|
|
cuDumpDate(&dateValue);
|
|
cbProp = sizeof(DATE);
|
|
break;
|
|
|
|
case PROPTYPE_BINARY:
|
|
if (CV_OUT_BINARY != Format)
|
|
{
|
|
hr = ViewColumn_GetValue(
|
|
&diViewColumn,
|
|
CV_OUT_BINARY,
|
|
PROPTYPE_BINARY,
|
|
&strValueBinary);
|
|
_JumpIfError(hr, error, "ViewColumn_GetValue");
|
|
}
|
|
else
|
|
{
|
|
strValueBinary = strValue;
|
|
strValue = NULL;
|
|
}
|
|
cbProp = SysStringByteLen(strValueBinary);
|
|
DumpBinaryValue(
|
|
aColInfo[iCol].strCol,
|
|
strObjId,
|
|
Format,
|
|
(BYTE *) strValueBinary,
|
|
cbProp,
|
|
strValue);
|
|
break;
|
|
|
|
case PROPTYPE_STRING:
|
|
wprintf(L" \"");
|
|
cuPrintCRLFString(NULL, strValue);
|
|
wprintf(L"\"");
|
|
cuPrintPossibleObjectIdName(strValue);
|
|
wprintf(wszNewLine);
|
|
if (g_fVerbose)
|
|
{
|
|
DumpHex(
|
|
0,
|
|
(BYTE *) strValue,
|
|
SysStringByteLen(strValue));
|
|
wprintf(wszNewLine);
|
|
}
|
|
cbProp = wcslen(strValue) * sizeof(WCHAR);
|
|
if (0 == LSTRCMPIS(
|
|
aColInfo[iCol].strCol,
|
|
wszPROPEXTNAME))
|
|
{
|
|
if (NULL != strObjId)
|
|
{
|
|
SysFreeString(strObjId);
|
|
}
|
|
strObjId = SysAllocString(strValue);
|
|
}
|
|
break;
|
|
}
|
|
UpdateStats(&statsRowProperties, cbProp);
|
|
}
|
|
}
|
|
|
|
fSkip = TRUE;
|
|
if (fAllAttributes || NULL != apwszAttributes)
|
|
{
|
|
// Enumerate Request Attributes
|
|
|
|
hr = ViewRow_EnumCertViewAttribute(&diViewRow, 0, &diViewAttribute);
|
|
if (CERTSRV_E_PROPERTY_EMPTY == hr)
|
|
{
|
|
_PrintError2(hr, "ViewRow_EnumCertViewAttribute", hr);
|
|
}
|
|
else
|
|
{
|
|
_JumpIfError(hr, error, "ViewRow_EnumCertViewAttribute");
|
|
|
|
fSkip = FALSE;
|
|
fMustReleaseAttribute = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!fSkip)
|
|
{
|
|
fHeaderPrinted = FALSE;
|
|
|
|
for (iAttribute = 0; ; iAttribute++)
|
|
{
|
|
hr = ViewAttribute_Next(&diViewAttribute, &AttributeIndex);
|
|
if (S_FALSE == hr || (S_OK == hr && -1 == AttributeIndex))
|
|
{
|
|
break;
|
|
}
|
|
_JumpIfError(hr, error, "ViewAttribute_Next");
|
|
CSASSERT(AttributeIndex == iAttribute);
|
|
|
|
hr = ViewAttribute_GetName(&diViewAttribute, &strName);
|
|
_JumpIfError(hr, error, "GetName");
|
|
|
|
if (ShouldDisplay(strName, fAllAttributes, apwszAttributes))
|
|
{
|
|
if (!fHeaderPrinted)
|
|
{
|
|
PrintRowIndex(iRow, &fRowPrinted);
|
|
if (fExtraNewLine)
|
|
{
|
|
wprintf(wszNewLine);
|
|
}
|
|
wprintf(
|
|
L" %ws\n",
|
|
myLoadResourceString(IDS_REQUEST_ATTRIBUTES)); // "Request Attributes:"
|
|
fHeaderPrinted = TRUE;
|
|
fExtraNewLine = TRUE;
|
|
}
|
|
|
|
if (NULL != strValue)
|
|
{
|
|
SysFreeString(strValue);
|
|
strValue = NULL;
|
|
}
|
|
hr = ViewAttribute_GetValue(&diViewAttribute, &strValue);
|
|
_JumpIfError(hr, error, "GetValue");
|
|
|
|
wprintf(L" %ws: \"%ws\"\n", strName, strValue);
|
|
|
|
UpdateStats(
|
|
&statsAttributes,
|
|
(wcslen(strName) + wcslen(strValue)) *
|
|
sizeof(WCHAR) +
|
|
sizeof(LONG)); // for RequestId
|
|
}
|
|
}
|
|
ViewAttribute_Release(&diViewAttribute);
|
|
fMustReleaseAttribute = FALSE;
|
|
}
|
|
|
|
fSkip = TRUE;
|
|
if (fAllExtensions || NULL != apwszExtensions)
|
|
{
|
|
// Enumerate Certificate Extensions
|
|
|
|
hr = ViewRow_EnumCertViewExtension(&diViewRow, 0, &diViewExtension);
|
|
if (CERTSRV_E_PROPERTY_EMPTY == hr)
|
|
{
|
|
_PrintError2(hr, "ViewRow_EnumCertViewExtension", hr);
|
|
}
|
|
else
|
|
{
|
|
_JumpIfError(hr, error, "ViewRow_EnumCertViewExtension");
|
|
|
|
fSkip = FALSE;
|
|
fMustReleaseExtension = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!fSkip)
|
|
{
|
|
fHeaderPrinted = FALSE;
|
|
|
|
pwszExtensionFormat = myLoadResourceString(IDS_FORMAT_EXTENSION); // "%ws: Flags = %x%ws, Length = %x"
|
|
|
|
for (iExtension = 0; ; iExtension++)
|
|
{
|
|
LONG ExtFlags;
|
|
|
|
hr = ViewExtension_Next(&diViewExtension, &ExtensionIndex);
|
|
if (S_FALSE == hr || (S_OK == hr && -1 == ExtensionIndex))
|
|
{
|
|
break;
|
|
}
|
|
_JumpIfError(hr, error, "ViewExtension_Next");
|
|
CSASSERT(ExtensionIndex == iExtension);
|
|
|
|
hr = ViewExtension_GetName(&diViewExtension, &strName);
|
|
_JumpIfError(hr, error, "GetName");
|
|
|
|
if (ShouldDisplay(strName, fAllExtensions, apwszExtensions))
|
|
{
|
|
DWORD cbValue;
|
|
|
|
if (!fHeaderPrinted)
|
|
{
|
|
PrintRowIndex(iRow, &fRowPrinted);
|
|
if (fExtraNewLine)
|
|
{
|
|
wprintf(wszNewLine);
|
|
}
|
|
wprintf(
|
|
L" %ws\n",
|
|
myLoadResourceString(IDS_CERTIFICATE_EXTENSIONS)); // "Certificate Extensions:"
|
|
fHeaderPrinted = TRUE;
|
|
}
|
|
|
|
hr = ViewExtension_GetFlags(&diViewExtension, &ExtFlags);
|
|
_JumpIfError(hr, error, "GetFlags");
|
|
|
|
if (NULL != strValue)
|
|
{
|
|
SysFreeString(strValue);
|
|
strValue = NULL;
|
|
}
|
|
hr = ViewExtension_GetValue(
|
|
&diViewExtension,
|
|
PROPTYPE_BINARY,
|
|
CV_OUT_BINARY,
|
|
&strValue);
|
|
if (CERTSRV_E_PROPERTY_EMPTY != hr)
|
|
{
|
|
_JumpIfError(hr, error, "GetValue");
|
|
}
|
|
cbValue = NULL == strValue? 0 : SysStringByteLen(strValue);
|
|
|
|
wprintf(g_wszPad4);
|
|
wprintf(
|
|
pwszExtensionFormat,
|
|
strName,
|
|
ExtFlags,
|
|
cuwszFromExtFlags(ExtFlags),
|
|
cbValue);
|
|
wprintf(wszNewLine);
|
|
|
|
if (0 == cbValue)
|
|
{
|
|
wprintf(g_wszPad4);
|
|
wprintf(myLoadResourceString(IDS_PROP_EMPTY)); // "EMPTY"
|
|
wprintf(wszNewLine);
|
|
}
|
|
else
|
|
{
|
|
if (!cuDumpFormattedExtension(
|
|
strName,
|
|
(BYTE const *) strValue,
|
|
SysStringByteLen(strValue)) ||
|
|
g_fVerbose)
|
|
{
|
|
wprintf(wszNewLine);
|
|
DumpHex(
|
|
DH_NOTABPREFIX | 4,
|
|
(BYTE const *) strValue,
|
|
SysStringByteLen(strValue));
|
|
}
|
|
}
|
|
wprintf(wszNewLine);
|
|
|
|
UpdateStats(
|
|
&statsExtensions,
|
|
wcslen(strName) * sizeof(WCHAR) +
|
|
cbValue + // for ext
|
|
sizeof(LONG) + // for RequestId
|
|
sizeof(ExtFlags)); // for ExtensionFlags
|
|
}
|
|
}
|
|
ViewExtension_Release(&diViewExtension);
|
|
fMustReleaseExtension = FALSE;
|
|
}
|
|
if (fOneRow)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
done:
|
|
DumpViewStats(
|
|
cRowTotal,
|
|
&statsRowProperties,
|
|
&statsAttributes,
|
|
&statsExtensions);
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != aColInfo)
|
|
{
|
|
for (i = 0; i < cColOut; i++)
|
|
{
|
|
if (NULL != aColInfo[i].strCol)
|
|
{
|
|
SysFreeString(aColInfo[i].strCol);
|
|
}
|
|
if (NULL != aColInfo[i].strColDisplay)
|
|
{
|
|
SysFreeString(aColInfo[i].strColDisplay);
|
|
}
|
|
}
|
|
LocalFree(aColInfo);
|
|
}
|
|
|
|
cuFreeStringArray(apwszRestrictions);
|
|
cuFreeStringArray(apwszColumns);
|
|
cuFreeStringArray(apwszAttributes);
|
|
cuFreeStringArray(apwszExtensions);
|
|
|
|
if (NULL != strObjId)
|
|
{
|
|
SysFreeString(strObjId);
|
|
}
|
|
if (NULL != strName)
|
|
{
|
|
SysFreeString(strName);
|
|
}
|
|
if (NULL != strValue)
|
|
{
|
|
SysFreeString(strValue);
|
|
}
|
|
if (NULL != strValueBinary)
|
|
{
|
|
SysFreeString(strValueBinary);
|
|
}
|
|
if (fMustReleaseAttribute)
|
|
{
|
|
ViewAttribute_Release(&diViewAttribute);
|
|
}
|
|
if (fMustReleaseExtension)
|
|
{
|
|
ViewExtension_Release(&diViewExtension);
|
|
}
|
|
if (fMustReleaseColumn)
|
|
{
|
|
ViewColumn_Release(&diViewColumn);
|
|
}
|
|
if (fMustReleaseRow)
|
|
{
|
|
ViewRow_Release(&diViewRow);
|
|
}
|
|
if (fMustRelease)
|
|
{
|
|
View_Release(&diView);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DBShutDown(
|
|
IN ICertDB *pdb)
|
|
{
|
|
HRESULT hr;
|
|
|
|
CSASSERT(NULL != pdb);
|
|
hr = pdb->ShutDown(0);
|
|
pdb->Release();
|
|
return(hr);
|
|
}
|
|
|
|
|
|
// Control-C handler to shut down DB
|
|
|
|
BOOL
|
|
cuDBAbortShutDown(
|
|
IN DWORD dwCtrlType)
|
|
{
|
|
HRESULT hr;
|
|
ICertDB *pdb;
|
|
|
|
EnterCriticalSection(&g_DBCriticalSection);
|
|
pdb = g_pdb;
|
|
g_pdb = NULL;
|
|
if (NULL != pdb)
|
|
{
|
|
DBShutDown(pdb);
|
|
SetConsoleCtrlHandler(cuDBAbortShutDown, FALSE);
|
|
}
|
|
LeaveCriticalSection(&g_DBCriticalSection);
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DBOpen(
|
|
IN WCHAR const *pwszAuthority,
|
|
IN BOOL fReadOnly,
|
|
OUT ICertDB **ppdb)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD cb;
|
|
DWORD i;
|
|
HKEY hkey = NULL;
|
|
WCHAR awszDatabase[MAX_PATH];
|
|
WCHAR awszLogDir[MAX_PATH];
|
|
WCHAR awszSystemDir[MAX_PATH];
|
|
WCHAR awszTempDir[MAX_PATH];
|
|
DWORD DBFlags;
|
|
|
|
WCHAR *pawszDirBuf[4] =
|
|
{
|
|
awszDatabase,
|
|
awszLogDir,
|
|
awszSystemDir,
|
|
awszTempDir
|
|
};
|
|
|
|
WCHAR *pawszRegNames[4] =
|
|
{
|
|
wszREGDBDIRECTORY,
|
|
wszREGDBLOGDIRECTORY,
|
|
wszREGDBSYSDIRECTORY,
|
|
wszREGDBTEMPDIRECTORY
|
|
};
|
|
|
|
// get info from registry
|
|
|
|
hr = RegOpenKey(HKEY_LOCAL_MACHINE, wszREGKEYCONFIGPATH, &hkey);
|
|
_JumpIfError(hr, error, "RegOpenKey(CAName)");
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
cb = sizeof(WCHAR) * MAX_PATH;
|
|
hr = RegQueryValueEx(
|
|
hkey,
|
|
pawszRegNames[i],
|
|
NULL,
|
|
NULL,
|
|
(BYTE *) pawszDirBuf[i],
|
|
&cb);
|
|
_JumpIfError(hr, error, "RegQueryValueEx(DB*Dir)");
|
|
}
|
|
if (wcslen(awszDatabase) +
|
|
1 +
|
|
wcslen(pwszAuthority) +
|
|
wcslen(wszDBFILENAMEEXT) >= ARRAYSIZE(awszDatabase))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
|
|
_JumpErrorStr(hr, error, "awszDatabase", pwszAuthority);
|
|
}
|
|
wcscat(awszDatabase, L"\\");
|
|
wcscat(awszDatabase, pwszAuthority);
|
|
wcscat(awszDatabase, wszDBFILENAMEEXT);
|
|
|
|
cb = sizeof(DBFlags);
|
|
hr = RegQueryValueEx(
|
|
hkey,
|
|
wszREGDBFLAGS,
|
|
NULL,
|
|
NULL,
|
|
(BYTE *) &DBFlags,
|
|
&cb);
|
|
if (S_OK != hr)
|
|
{
|
|
_PrintErrorStr(hr, "RegQueryValueEx", wszREGDBFLAGS);
|
|
DBFlags = DBFLAGS_DEFAULT;
|
|
}
|
|
DBFlags &= ~DBFLAGS_READONLY;
|
|
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_OPENING_DB), // "Opening Database %ws"
|
|
awszDatabase);
|
|
wprintf(wszNewLine);
|
|
|
|
hr = CoCreateInstance(
|
|
CLSID_CCertDB,
|
|
NULL, // pUnkOuter
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_ICertDB,
|
|
(VOID **) ppdb);
|
|
_JumpIfError(hr, error, "CoCreateInstance(ICertDB)");
|
|
|
|
if (fReadOnly)
|
|
{
|
|
DBFlags |= DBFLAGS_READONLY;
|
|
}
|
|
else if (g_fForce)
|
|
{
|
|
DBFlags |= DBFLAGS_CREATEIFNEEDED;
|
|
}
|
|
hr = (*ppdb)->Open(
|
|
DBFlags,
|
|
2, // cSession
|
|
L"certutil.exe", // pwszEventSource
|
|
awszDatabase, // pwszDBFile
|
|
awszLogDir, // pwszLogDir
|
|
awszSystemDir, // pwszSystemDir
|
|
awszTempDir); // pwszTempDir
|
|
_JumpIfError(hr, error, "ICertDB::Open");
|
|
|
|
error:
|
|
if (S_OK != hr)
|
|
{
|
|
if (NULL != *ppdb)
|
|
{
|
|
(*ppdb)->Release();
|
|
*ppdb = NULL;
|
|
}
|
|
}
|
|
if (NULL != hkey)
|
|
{
|
|
RegCloseKey(hkey);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDBOpen(
|
|
IN WCHAR const *pwszAuthority,
|
|
IN BOOL fReadOnly,
|
|
OUT ICertDB **ppdb)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszSanitizedCA = NULL;
|
|
|
|
hr = mySanitizeName(pwszAuthority, &pwszSanitizedCA);
|
|
_JumpIfError(hr, error, "mySanitizeName");
|
|
|
|
SetConsoleCtrlHandler(NULL, TRUE); // ignore CTL-C during cuDBOpen
|
|
hr = DBOpen(pwszSanitizedCA, fReadOnly, ppdb);
|
|
if (S_OK != hr)
|
|
{
|
|
cuPrintError(IDS_DB_OPEN_FAILURE, hr);
|
|
if (myJetHResult(JET_errFileAccessDenied) == hr)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_DB_ACCESS_STOP_SERVER));
|
|
wprintf(wszNewLine);
|
|
}
|
|
else
|
|
{
|
|
wprintf(myLoadResourceString(IDS_DB_ACCESS_INSTALL_SERVER)); // "Ensure the server is correctly installed and retry."
|
|
wprintf(wszNewLine);
|
|
}
|
|
_JumpError(hr, error, "DBOpen");
|
|
}
|
|
g_pdb = *ppdb;
|
|
SetConsoleCtrlHandler(cuDBAbortShutDown, TRUE);
|
|
SetConsoleCtrlHandler(NULL, FALSE); // allow CTL-C
|
|
|
|
error:
|
|
if (NULL != pwszSanitizedCA)
|
|
{
|
|
LocalFree(pwszSanitizedCA);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
CERTDBCOLUMN g_adcRequests[50];
|
|
DWORD g_cdcRequests;
|
|
|
|
CERTDBCOLUMN g_adcCertificates[50];
|
|
DWORD g_cdcCertificates;
|
|
|
|
HRESULT
|
|
DBLoadSchema(
|
|
IN ICertDB *pdb)
|
|
{
|
|
HRESULT hr;
|
|
IEnumCERTDBCOLUMN *penum = NULL;
|
|
CERTDBCOLUMN acol[2];
|
|
DWORD ccol;
|
|
DWORD i;
|
|
CERTDBCOLUMN *pdc;
|
|
CERTDBCOLUMN const *pdcEnd;
|
|
CERTDBCOLUMN *pdcReq = g_adcRequests;
|
|
CERTDBCOLUMN *pdcCert = g_adcCertificates;
|
|
DWORD *pcdc;
|
|
|
|
hr = pdb->EnumCertDBColumn(CVRC_TABLE_REQCERT, &penum);
|
|
_JumpIfError(hr, error, "EnumCertDBColumn");
|
|
|
|
while (TRUE)
|
|
{
|
|
hr = penum->Next(ARRAYSIZE(acol), acol, &ccol);
|
|
if (S_FALSE != hr)
|
|
{
|
|
_JumpIfError(hr, error, "Next");
|
|
}
|
|
for (i = 0; i < ccol; i++)
|
|
{
|
|
if (0 == _wcsnicmp(
|
|
wszPROPREQUESTDOT,
|
|
acol[i].pwszName,
|
|
WSZARRAYSIZE(wszPROPREQUESTDOT)))
|
|
{
|
|
pdc = pdcReq++;
|
|
pcdc = &g_cdcRequests;
|
|
pdcEnd = &g_adcRequests[ARRAYSIZE(g_adcRequests) - 1];
|
|
}
|
|
else
|
|
{
|
|
pdc = pdcCert++;
|
|
pcdc = &g_cdcCertificates;
|
|
pdcEnd = &g_adcCertificates[ARRAYSIZE(g_adcCertificates) - 1];
|
|
}
|
|
if (pdc >= pdcEnd)
|
|
{
|
|
//wprintf(L"Property Name Table overflow\n");
|
|
hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
|
|
_JumpError(hr, error, "Property Name Table overflow");
|
|
}
|
|
*pdc = acol[i];
|
|
(*pcdc)++;
|
|
}
|
|
if (S_FALSE == hr)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != penum)
|
|
{
|
|
penum->Release();
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DBLookupColumnInfo1(
|
|
IN CERTDBCOLUMN const *pdc,
|
|
IN DWORD ColIndex,
|
|
OUT CERTDBCOLUMN const **ppdc)
|
|
{
|
|
HRESULT hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
|
|
|
*ppdc = NULL;
|
|
for ( ; NULL != pdc->pwszName; pdc++)
|
|
{
|
|
if (pdc->Index == ColIndex)
|
|
{
|
|
*ppdc = pdc;
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DBLookupColumnInfo(
|
|
IN DWORD ColIndex,
|
|
OUT CERTDBCOLUMN const **ppdc,
|
|
OUT DWORD *pdwTable)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = DBLookupColumnInfo1(
|
|
g_adcRequests,
|
|
ColIndex,
|
|
ppdc);
|
|
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
|
|
{
|
|
_JumpIfError(hr, error, "DBLookupColumnInfo1");
|
|
|
|
*pdwTable = PROPTABLE_REQUEST;
|
|
}
|
|
else
|
|
{
|
|
hr = DBLookupColumnInfo1(
|
|
g_adcCertificates,
|
|
ColIndex,
|
|
ppdc);
|
|
*pdwTable = PROPTABLE_CERTIFICATE;
|
|
}
|
|
_JumpIfError(hr, error, "DBLookupColumnInfo1");
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DBDumpColumn(
|
|
IN CERTDBCOLUMN const *pdc)
|
|
{
|
|
HRESULT hr;
|
|
|
|
cuPrintSchemaEntry(
|
|
pdc->pwszName,
|
|
pdc->pwszDisplayName,
|
|
pdc->Type,
|
|
pdc->cbMax);
|
|
hr = S_OK;
|
|
|
|
//error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DBDumpSchema1(
|
|
IN CERTDBCOLUMN const *pdc)
|
|
{
|
|
HRESULT hr;
|
|
CERTDBCOLUMN const *pdcEnd;
|
|
|
|
for ( ; NULL != pdc->pwszName; pdc++)
|
|
{
|
|
hr = DBDumpColumn(pdc);
|
|
_JumpIfError(hr, error, "DBDumpColumn");
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DBDumpSchema(
|
|
IN ICertDB *pdb,
|
|
OPTIONAL IN DWORD const *pcol,
|
|
IN DWORD ccol)
|
|
{
|
|
HRESULT hr;
|
|
DWORD acol[100];
|
|
DWORD i;
|
|
|
|
if (1 == ccol && NULL != pcol && 0 > (LONG) *pcol)
|
|
{
|
|
hr = pdb->GetDefaultColumnSet(*pcol, ARRAYSIZE(acol), acol, &ccol);
|
|
_JumpIfError(hr, error, "GetDefaultColumnSet");
|
|
|
|
if (ARRAYSIZE(acol) == ccol)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
|
|
_JumpError(hr, error, "GetDefaultColumnSet");
|
|
}
|
|
pcol = acol;
|
|
}
|
|
|
|
wprintf(myLoadResourceString(IDS_SCHEMA_COLON)); // "Schema:"
|
|
wprintf(wszNewLine);
|
|
wprintf(myLoadResourceString(IDS_SCHEMA_COLUMNHEADERS)); // "Name..Type..."
|
|
wprintf(wszNewLine);
|
|
wprintf(myLoadResourceString(IDS_SCHEMA_COLUMNUNDERLINE)); // "____...____"
|
|
wprintf(wszNewLine);
|
|
|
|
if (NULL != pcol)
|
|
{
|
|
for (i = 0; i < ccol; i++)
|
|
{
|
|
CERTDBCOLUMN const *pdc;
|
|
DWORD dwTable;
|
|
|
|
hr = DBLookupColumnInfo(pcol[i], &pdc, &dwTable);
|
|
_JumpIfError(hr, error, "DBLookupColumnInfo");
|
|
|
|
hr = DBDumpColumn(pdc);
|
|
_JumpIfError(hr, error, "DBDumpColumn");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = DBDumpSchema1(g_adcRequests);
|
|
_JumpIfError(hr, error, "DBDumpSchema1");
|
|
|
|
hr = DBDumpSchema1(g_adcCertificates);
|
|
_JumpIfError(hr, error, "DBDumpSchema1");
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
VOID
|
|
DBFreeSchema1(
|
|
IN CERTDBCOLUMN const *pdc,
|
|
IN DWORD cdc)
|
|
{
|
|
CERTDBCOLUMN const *pdcEnd;
|
|
|
|
for (pdcEnd = &pdc[cdc]; pdc < pdcEnd; pdc++)
|
|
{
|
|
if (NULL != pdc->pwszName)
|
|
{
|
|
CoTaskMemFree(pdc->pwszName);
|
|
}
|
|
if (NULL != pdc->pwszDisplayName)
|
|
{
|
|
CoTaskMemFree(pdc->pwszDisplayName);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
DBFreeSchema()
|
|
{
|
|
DBFreeSchema1(g_adcRequests, g_cdcRequests);
|
|
DBFreeSchema1(g_adcCertificates, g_cdcCertificates);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DBGetColumnInfo1(
|
|
IN CERTDBCOLUMN const *pdc,
|
|
IN WCHAR const *pwszColName,
|
|
OUT WCHAR const **ppwszColNameActual,
|
|
OUT DWORD *pColIndex,
|
|
OUT LONG *pColType)
|
|
{
|
|
HRESULT hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
|
|
|
*ppwszColNameActual = NULL;
|
|
for ( ; NULL != pdc->pwszName; pdc++)
|
|
{
|
|
if (0 == mylstrcmpiL(pwszColName, pdc->pwszName))
|
|
{
|
|
*ppwszColNameActual = pdc->pwszName;
|
|
}
|
|
else
|
|
if (NULL != pdc->pwszDisplayName &&
|
|
0 == mylstrcmpiL(pwszColName, pdc->pwszDisplayName))
|
|
{
|
|
*ppwszColNameActual = pdc->pwszDisplayName;
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
*pColIndex = pdc->Index;
|
|
*pColType = pdc->Type;
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
|
|
//error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DBGetColumnInfo(
|
|
IN ICertDB *pdb,
|
|
IN WCHAR const *pwszColName,
|
|
OUT WCHAR const **ppwszColNameActual,
|
|
OUT DWORD *pColIndex,
|
|
OUT LONG *pColType)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwsz;
|
|
WCHAR *pwszRequestColName = NULL;
|
|
|
|
hr = DBGetColumnInfo1(
|
|
g_adcRequests,
|
|
pwszColName,
|
|
ppwszColNameActual,
|
|
pColIndex,
|
|
pColType);
|
|
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
|
|
{
|
|
_JumpIfError(hr, error, "DBGetColumnInfo1");
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT((DBG_SS_CERTUTILI, "DBGetColumnInfo1(req, %ws) = %x\n", pwszColName, hr));
|
|
hr = DBGetColumnInfo1(
|
|
g_adcCertificates,
|
|
pwszColName,
|
|
ppwszColNameActual,
|
|
pColIndex,
|
|
pColType);
|
|
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
|
|
{
|
|
_JumpIfError(hr, error, "DBGetColumnInfo1");
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT((DBG_SS_CERTUTILI, "DBGetColumnInfo1(cert, %ws) = %x\n", pwszColName, hr));
|
|
pwsz = wcschr(pwszColName, L'.');
|
|
if (NULL == pwsz)
|
|
{
|
|
pwszRequestColName = (WCHAR *) LocalAlloc(
|
|
LMEM_FIXED,
|
|
(WSZARRAYSIZE(wszPROPREQUESTDOT) + wcslen(pwszColName) + 1) *
|
|
sizeof(WCHAR));
|
|
if (NULL == pwszRequestColName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
wcscpy(pwszRequestColName, wszPROPREQUESTDOT);
|
|
wcscat(pwszRequestColName, pwszColName);
|
|
hr = DBGetColumnInfo1(
|
|
g_adcRequests,
|
|
pwszRequestColName,
|
|
ppwszColNameActual,
|
|
pColIndex,
|
|
pColType);
|
|
DBGPRINT((DBG_SS_CERTUTILI, "DBGetColumnInfo1(req, %ws) = %x\n", pwszRequestColName, hr));
|
|
}
|
|
}
|
|
_JumpIfError(hr, error, "DBGetColumnInfo1");
|
|
}
|
|
|
|
error:
|
|
if (NULL != pwszRequestColName)
|
|
{
|
|
LocalFree(pwszRequestColName);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDBPrintProperty(
|
|
OPTIONAL IN ICertDBRow *prow,
|
|
IN DWORD Type,
|
|
IN WCHAR const *pwszColName,
|
|
IN WCHAR const *pwszDisplayName,
|
|
OPTIONAL IN BYTE const *pbValue,
|
|
IN DWORD cbValue,
|
|
OUT DWORD *pcbValue)
|
|
{
|
|
HRESULT hr;
|
|
DWORD cb = 0;
|
|
BYTE *pb = NULL;
|
|
LONG Format;
|
|
WCHAR *pwszOut = NULL;
|
|
|
|
EnterCriticalSection(&g_DBCriticalSection);
|
|
*pcbValue = 0;
|
|
if (cuDBIsShutDownInProgress())
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
|
|
_JumpError(hr, error, "cuDBIsShutDownInProgress");
|
|
}
|
|
wprintf(L" %ws:", pwszDisplayName);
|
|
if (NULL == pbValue)
|
|
{
|
|
cb = 0;
|
|
hr = prow->GetProperty(pwszColName, Type, NULL, &cb, pb);
|
|
if (S_OK == hr)
|
|
{
|
|
pb = (BYTE *) LocalAlloc(LMEM_FIXED, cb);
|
|
if (NULL == pb)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
hr = prow->GetProperty(pwszColName, Type, NULL, &cb, pb);
|
|
}
|
|
if (S_OK != hr)
|
|
{
|
|
wprintf(L" ");
|
|
if (CERTSRV_E_PROPERTY_EMPTY != hr)
|
|
{
|
|
cuPrintError(IDS_FORMAT_ERROR, hr); // "error = %ws"
|
|
_JumpError(hr, error, "GetProperty");
|
|
}
|
|
wprintf(myLoadResourceString(IDS_PROP_EMPTY)); // "EMPTY"
|
|
wprintf(wszNewLine);
|
|
cb = 0;
|
|
}
|
|
else
|
|
{
|
|
pbValue = pb;
|
|
cbValue = cb;
|
|
}
|
|
}
|
|
if (NULL != pbValue)
|
|
{
|
|
switch (PROPTYPE_MASK & Type)
|
|
{
|
|
case PROPTYPE_LONG:
|
|
DumpLongValue(*(DWORD *) pbValue, pwszColName);
|
|
break;
|
|
|
|
case PROPTYPE_DATE:
|
|
hr = cuDumpFileTime(0, NULL, (FILETIME const *) pbValue);
|
|
_JumpIfError(hr, error, "cuDumpFileTime");
|
|
break;
|
|
|
|
case PROPTYPE_BINARY:
|
|
hr = GetBinaryColumnFormat(pwszColName, &Format);
|
|
_JumpIfError(hr, error, "GetBinaryColumnFormat");
|
|
|
|
if (CV_OUT_BINARY != Format)
|
|
{
|
|
CSASSERT(CV_OUT_BASE64HEADER == CRYPT_STRING_BASE64HEADER);
|
|
CSASSERT(CV_OUT_BASE64 == CRYPT_STRING_BASE64);
|
|
CSASSERT(
|
|
CV_OUT_BASE64REQUESTHEADER == CRYPT_STRING_BASE64REQUESTHEADER);
|
|
CSASSERT(CV_OUT_HEX == CRYPT_STRING_HEX);
|
|
CSASSERT(CV_OUT_HEXASCII == CRYPT_STRING_HEXASCII);
|
|
CSASSERT(CV_OUT_HEXADDR == CRYPT_STRING_HEXADDR);
|
|
CSASSERT(CV_OUT_HEXASCIIADDR == CRYPT_STRING_HEXASCIIADDR);
|
|
|
|
hr = myCryptBinaryToString(
|
|
pbValue,
|
|
cbValue,
|
|
Format,
|
|
&pwszOut);
|
|
_JumpIfError(hr, error, "myCryptBinaryToString");
|
|
}
|
|
DumpBinaryValue(
|
|
pwszColName,
|
|
NULL, // pwszObjId
|
|
Format,
|
|
pbValue,
|
|
cbValue,
|
|
pwszOut);
|
|
break;
|
|
|
|
case PROPTYPE_STRING:
|
|
wprintf(L" \"");
|
|
cuPrintCRLFString(NULL, (WCHAR const *) pbValue);
|
|
wprintf(L"\"");
|
|
cuPrintPossibleObjectIdName((WCHAR const *) pbValue);
|
|
wprintf(wszNewLine);
|
|
break;
|
|
}
|
|
}
|
|
*pcbValue = cb;
|
|
hr = S_OK;
|
|
|
|
error:
|
|
LeaveCriticalSection(&g_DBCriticalSection);
|
|
if (NULL != pb)
|
|
{
|
|
LocalFree(pb);
|
|
}
|
|
if (NULL != pwszOut)
|
|
{
|
|
LocalFree(pwszOut);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DBPrintRow(
|
|
IN ICertDB *pdb,
|
|
IN DWORD iRow,
|
|
IN DWORD RowId,
|
|
OPTIONAL IN CERTDBRESULTROW const *pResultRow,
|
|
OPTIONAL IN DWORD const *acol,
|
|
IN DWORD ccol,
|
|
IN BOOL fAllColumns,
|
|
IN OUT DBSTATS *pstatsRowProperties,
|
|
OPTIONAL IN WCHAR const * const *apwszAttributes,
|
|
IN BOOL fAllAttributes,
|
|
IN OUT DBSTATS *pstatsAttributes,
|
|
OPTIONAL IN WCHAR const * const *apwszExtensions,
|
|
IN BOOL fAllExtensions,
|
|
IN OUT DBSTATS *pstatsExtensions)
|
|
{
|
|
HRESULT hr;
|
|
ICertDBRow *prow = NULL;
|
|
DWORD ReqId;
|
|
CERTDBCOLUMN const *pdc;
|
|
LONG cskip;
|
|
IEnumCERTDBNAME *penum = NULL;
|
|
ULONG celtFetched;
|
|
CERTDBNAME cdbn;
|
|
BYTE abValue[64+1024];
|
|
DWORD dwTable;
|
|
DWORD i;
|
|
DWORD cb;
|
|
|
|
BOOL fRowPrinted = FALSE;
|
|
BOOL fExtraNewLine = FALSE;
|
|
BOOL fHeaderPrinted;
|
|
|
|
cdbn.pwszName = NULL;
|
|
|
|
hr = pdb->OpenRow(
|
|
PROPOPEN_READONLY | PROPTABLE_REQCERT,
|
|
RowId,
|
|
NULL,
|
|
&prow);
|
|
_JumpIfError2(hr, error, "OpenRow", CERTSRV_E_PROPERTY_EMPTY);
|
|
|
|
prow->GetRowId(&ReqId);
|
|
|
|
if (NULL != pResultRow)
|
|
{
|
|
#if 0
|
|
wprintf(
|
|
L"Row %u: ReqId=%u, ccol=%u, type=%x, index=%x, cb=%u, value=%u\n",
|
|
iRow,
|
|
pResultRow->rowid,
|
|
pResultRow->ccol,
|
|
pResultRow->acol[0].Type,
|
|
pResultRow->acol[0].Index,
|
|
pResultRow->acol[0].cbValue,
|
|
*(DWORD *) pResultRow->acol[0].pbValue);
|
|
#endif
|
|
for (i = 0; i < pResultRow->ccol; i++)
|
|
{
|
|
CERTDBRESULTCOLUMN *pcol = &pResultRow->acol[i];
|
|
|
|
hr = DBLookupColumnInfo(pcol->Index, &pdc, &dwTable);
|
|
_JumpIfError(hr, error, "DBLookupColumnInfo");
|
|
|
|
CSASSERT(pcol->Type == pdc->Type);
|
|
|
|
PrintRowIndex(iRow, &fRowPrinted);
|
|
fExtraNewLine = TRUE;
|
|
|
|
hr = cuDBPrintProperty(
|
|
prow,
|
|
dwTable | pcol->Type,
|
|
pdc->pwszName,
|
|
pdc->pwszDisplayName,
|
|
pcol->pbValue,
|
|
pcol->cbValue,
|
|
&cb);
|
|
_JumpIfError(hr, error, "cuDBPrintProperty");
|
|
|
|
UpdateStats(pstatsRowProperties, cb);
|
|
}
|
|
}
|
|
else if (NULL != acol)
|
|
{
|
|
for (i = 0; i < ccol; i++)
|
|
{
|
|
PrintRowIndex(iRow, &fRowPrinted);
|
|
fExtraNewLine = TRUE;
|
|
|
|
hr = DBLookupColumnInfo(acol[i], &pdc, &dwTable);
|
|
_JumpIfError(hr, error, "DBLookupColumnInfo");
|
|
|
|
hr = cuDBPrintProperty(
|
|
prow,
|
|
dwTable | pdc->Type,
|
|
pdc->pwszName,
|
|
pdc->pwszDisplayName,
|
|
NULL, // pbValue
|
|
0, // cbValue
|
|
&cb);
|
|
_JumpIfError(hr, error, "cuDBPrintProperty");
|
|
|
|
UpdateStats(pstatsRowProperties, cb);
|
|
}
|
|
}
|
|
else if (fAllColumns)
|
|
{
|
|
PrintRowIndex(iRow, &fRowPrinted);
|
|
fExtraNewLine = TRUE;
|
|
|
|
for (pdc = g_adcRequests; NULL != pdc->pwszName; pdc++)
|
|
{
|
|
hr = cuDBPrintProperty(
|
|
prow,
|
|
PROPTABLE_REQUEST | pdc->Type,
|
|
pdc->pwszName,
|
|
pdc->pwszDisplayName,
|
|
NULL, // pbValue
|
|
0, // cbValue
|
|
&cb);
|
|
_JumpIfError(hr, error, "cuDBPrintProperty");
|
|
|
|
UpdateStats(pstatsRowProperties, cb);
|
|
}
|
|
|
|
wprintf(wszNewLine);
|
|
wprintf(L" ");
|
|
wprintf(myLoadResourceString(IDS_CERT_PROPERTIES)); // "Certificate Properties:"
|
|
wprintf(wszNewLine);
|
|
|
|
for (pdc = g_adcCertificates; NULL != pdc->pwszName; pdc++)
|
|
{
|
|
hr = cuDBPrintProperty(
|
|
prow,
|
|
PROPTABLE_CERTIFICATE | pdc->Type,
|
|
pdc->pwszName,
|
|
pdc->pwszDisplayName,
|
|
NULL, // pbValue
|
|
0, // cbValue
|
|
&cb);
|
|
_JumpIfError(hr, error, "cuDBPrintProperty");
|
|
|
|
UpdateStats(pstatsRowProperties, cb);
|
|
}
|
|
wprintf(wszNewLine);
|
|
}
|
|
|
|
if (fAllAttributes || NULL != apwszAttributes)
|
|
{
|
|
fHeaderPrinted = FALSE;
|
|
|
|
hr = prow->EnumCertDBName(CIE_TABLE_ATTRIBUTES, &penum);
|
|
_JumpIfError(hr, error, "EnumCertDBName");
|
|
|
|
while (TRUE)
|
|
{
|
|
hr = penum->Next(1, &cdbn, &celtFetched);
|
|
if (S_FALSE == hr)
|
|
{
|
|
break;
|
|
}
|
|
_JumpIfError(hr, error, "Next");
|
|
|
|
CSASSERT(1 == celtFetched);
|
|
CSASSERT(NULL != cdbn.pwszName);
|
|
|
|
if (ShouldDisplay(cdbn.pwszName, fAllAttributes, apwszAttributes))
|
|
{
|
|
if (!fHeaderPrinted)
|
|
{
|
|
PrintRowIndex(iRow, &fRowPrinted);
|
|
if (fExtraNewLine)
|
|
{
|
|
wprintf(wszNewLine);
|
|
}
|
|
wprintf(
|
|
L" %ws\n",
|
|
myLoadResourceString(IDS_REQUEST_ATTRIBUTES)); // "Request Attributes:"
|
|
fHeaderPrinted = TRUE;
|
|
fExtraNewLine = TRUE;
|
|
}
|
|
hr = cuDBPrintProperty(
|
|
prow,
|
|
PROPTABLE_ATTRIBUTE | PROPTYPE_STRING,
|
|
cdbn.pwszName,
|
|
cdbn.pwszName,
|
|
NULL, // pbValue
|
|
0, // cbValue
|
|
&cb); // returned cbValue
|
|
_JumpIfError(hr, error, "cuDBPrintProperty");
|
|
|
|
UpdateStats(
|
|
pstatsAttributes,
|
|
wcslen(cdbn.pwszName) * sizeof(WCHAR) +
|
|
cb +
|
|
sizeof(LONG)); // for RequestId
|
|
}
|
|
CoTaskMemFree(cdbn.pwszName);
|
|
cdbn.pwszName = NULL;
|
|
}
|
|
penum->Release();
|
|
penum = NULL;
|
|
}
|
|
|
|
if (fAllExtensions || NULL != apwszExtensions)
|
|
{
|
|
fHeaderPrinted = FALSE;
|
|
|
|
hr = prow->EnumCertDBName(CIE_TABLE_EXTENSIONS, &penum);
|
|
_JumpIfError(hr, error, "EnumCertDBName");
|
|
|
|
while (TRUE)
|
|
{
|
|
DWORD ExtFlags;
|
|
|
|
hr = penum->Next(1, &cdbn, &celtFetched);
|
|
if (S_FALSE == hr)
|
|
{
|
|
break;
|
|
}
|
|
_JumpIfError(hr, error, "Next");
|
|
|
|
CSASSERT(1 == celtFetched);
|
|
CSASSERT(NULL != cdbn.pwszName);
|
|
|
|
if (ShouldDisplay(cdbn.pwszName, fAllExtensions, apwszExtensions))
|
|
{
|
|
if (!fHeaderPrinted)
|
|
{
|
|
PrintRowIndex(iRow, &fRowPrinted);
|
|
if (fExtraNewLine)
|
|
{
|
|
wprintf(wszNewLine);
|
|
}
|
|
wprintf(
|
|
L" %ws\n",
|
|
myLoadResourceString(IDS_CERTIFICATE_EXTENSIONS)); // "Certificate Extensions:"
|
|
fHeaderPrinted = TRUE;
|
|
}
|
|
cb = sizeof(abValue);
|
|
hr = prow->GetExtension(cdbn.pwszName, &ExtFlags, &cb, abValue);
|
|
_JumpIfError(hr, error, "GetExtension");
|
|
|
|
wprintf(g_wszPad4);
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_EXTENSION), // "%ws: Flags = %x%ws, Length = %x"
|
|
cdbn.pwszName,
|
|
ExtFlags,
|
|
cuwszFromExtFlags(ExtFlags),
|
|
cb);
|
|
wprintf(wszNewLine);
|
|
|
|
if (!cuDumpFormattedExtension(cdbn.pwszName, abValue, cb) ||
|
|
g_fVerbose)
|
|
{
|
|
wprintf(wszNewLine);
|
|
DumpHex(DH_NOTABPREFIX | 4, abValue, cb);
|
|
}
|
|
wprintf(wszNewLine);
|
|
|
|
UpdateStats(
|
|
pstatsExtensions,
|
|
wcslen(cdbn.pwszName) * sizeof(WCHAR) +
|
|
cb + // for ext
|
|
sizeof(LONG) + // for RequestId
|
|
sizeof(ExtFlags)); // for ExtensionFlags
|
|
}
|
|
CoTaskMemFree(cdbn.pwszName);
|
|
cdbn.pwszName = NULL;
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != cdbn.pwszName)
|
|
{
|
|
CoTaskMemFree(cdbn.pwszName);
|
|
}
|
|
if (NULL != penum)
|
|
{
|
|
penum->Release();
|
|
}
|
|
if (NULL != prow)
|
|
{
|
|
prow->Release();
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
WCHAR const *
|
|
wszSeekOperator(
|
|
IN LONG SeekOperator)
|
|
{
|
|
WCHAR const *pwsz;
|
|
static WCHAR s_wszBuf[10 + cwcDWORDSPRINTF];
|
|
|
|
switch (CVR_SEEK_MASK & SeekOperator)
|
|
{
|
|
case CVR_SEEK_NONE: pwsz = L"None"; break;
|
|
case CVR_SEEK_EQ: pwsz = L"=="; break;
|
|
case CVR_SEEK_LT: pwsz = L"<"; break;
|
|
case CVR_SEEK_LE: pwsz = L"<="; break;
|
|
case CVR_SEEK_GE: pwsz = L">="; break;
|
|
case CVR_SEEK_GT: pwsz = L">"; break;
|
|
default:
|
|
wsprintf(s_wszBuf, L"???=%x", SeekOperator);
|
|
pwsz = s_wszBuf;
|
|
break;
|
|
}
|
|
if (s_wszBuf != pwsz && (CVR_SEEK_NODELTA & SeekOperator))
|
|
{
|
|
wcscpy(s_wszBuf, pwsz);
|
|
wcscat(s_wszBuf, L",NoDelta");
|
|
pwsz = s_wszBuf;
|
|
}
|
|
|
|
return(pwsz);
|
|
}
|
|
|
|
|
|
WCHAR const *
|
|
wszSortOperator(
|
|
IN LONG SortOrder)
|
|
{
|
|
WCHAR const *pwsz;
|
|
static WCHAR s_wszBuf[10 + cwcDWORDSPRINTF];
|
|
|
|
switch (SortOrder)
|
|
{
|
|
case CVR_SORT_NONE: pwsz = L"None"; break;
|
|
case CVR_SORT_ASCEND: pwsz = L"Ascend"; break;
|
|
case CVR_SORT_DESCEND: pwsz = L"Descend"; break;
|
|
default:
|
|
wsprintf(s_wszBuf, L"???=%x", SortOrder);
|
|
pwsz = s_wszBuf;
|
|
break;
|
|
}
|
|
return(pwsz);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DBParseRestriction(
|
|
IN ICertDB *pdb,
|
|
IN WCHAR const *pwszRestriction,
|
|
OUT CERTVIEWRESTRICTION *pcvr,
|
|
OUT BOOL *pfOneRow,
|
|
OUT LONG *plSkip)
|
|
{
|
|
HRESULT hr;
|
|
LONG ColType;
|
|
WCHAR *pwszColName = NULL;
|
|
WCHAR *pwszColValue = NULL;
|
|
WCHAR const *pwszColNameActual;
|
|
LONG lVal;
|
|
DATE date;
|
|
BYTE const *pb;
|
|
|
|
*pfOneRow = FALSE;
|
|
*plSkip = 0;
|
|
|
|
hr = ParseRestriction(
|
|
pwszRestriction,
|
|
(LONG *) &pcvr->ColumnIndex,
|
|
&pcvr->SeekOperator,
|
|
&pcvr->SortOrder,
|
|
&pwszColName,
|
|
&pwszColValue);
|
|
_JumpIfErrorStr(hr, error, "ParseRestriction", pwszRestriction);
|
|
|
|
// no value to parse if a special column...
|
|
|
|
if (NULL == pwszColName)
|
|
{
|
|
CSASSERT(0 > (LONG) pcvr->ColumnIndex);
|
|
pcvr->cbValue = 0;
|
|
pb = NULL; // no source data
|
|
pwszColNameActual = L"";
|
|
}
|
|
else
|
|
{
|
|
hr = DBGetColumnInfo(
|
|
pdb,
|
|
pwszColName,
|
|
&pwszColNameActual,
|
|
&pcvr->ColumnIndex,
|
|
&ColType);
|
|
_JumpIfErrorStr(hr, error, "DBGetColumnInfo", pwszColName);
|
|
|
|
hr = ParseSpecialColumnValue(
|
|
pwszColValue,
|
|
PROPTYPE_MASK & ColType,
|
|
&pcvr->SeekOperator,
|
|
&pcvr->SortOrder,
|
|
pfOneRow,
|
|
plSkip);
|
|
_JumpIfError(hr, error, "ParseSpecialColumnValue");
|
|
|
|
switch (PROPTYPE_MASK & ColType)
|
|
{
|
|
case PROPTYPE_LONG:
|
|
lVal = 0;
|
|
if (!*pfOneRow)
|
|
{
|
|
hr = myGetSignedLong(pwszColValue, &lVal);
|
|
_JumpIfError(hr, error, "bad numeric operand");
|
|
}
|
|
pb = (BYTE const *) &lVal;
|
|
pcvr->cbValue = sizeof(lVal);
|
|
break;
|
|
|
|
case PROPTYPE_DATE:
|
|
date = 0;
|
|
if (!*pfOneRow)
|
|
{
|
|
hr = myWszLocalTimeToGMTDate(pwszColValue, &date);
|
|
_JumpIfError(hr, error, "invalid date format");
|
|
}
|
|
pb = (BYTE const *) &date;
|
|
pcvr->cbValue = sizeof(date);
|
|
cuDumpDate(&date);
|
|
break;
|
|
|
|
case PROPTYPE_STRING:
|
|
{
|
|
WCHAR const *pwsz = L"";
|
|
|
|
if (!*pfOneRow)
|
|
{
|
|
pwsz = pwszColValue;
|
|
}
|
|
pb = (BYTE const *) pwsz;
|
|
pcvr->cbValue = (wcslen(pwsz) + 1) * sizeof(WCHAR);
|
|
break;
|
|
}
|
|
|
|
case PROPTYPE_BINARY:
|
|
default:
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "not supported");
|
|
}
|
|
}
|
|
|
|
pcvr->pbValue = (BYTE *) LocalAlloc(LMEM_FIXED, pcvr->cbValue);
|
|
if (NULL == pcvr->pbValue)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
if (NULL != pb)
|
|
{
|
|
CopyMemory(pcvr->pbValue, pb, pcvr->cbValue);
|
|
}
|
|
|
|
#ifdef DBG_CERTSRV_DEBUG_PRINT
|
|
WCHAR wszSkip[cwcDWORDSPRINTF];
|
|
|
|
wszSkip[0] = L'\0';
|
|
if (0 != *plSkip)
|
|
{
|
|
wsprintf(wszSkip, L"%d", *plSkip);
|
|
}
|
|
#endif // DBG_CERTSRV_DEBUG_PRINT
|
|
|
|
DBGPRINT((
|
|
DBG_SS_CERTUTILI,
|
|
"Restriction: Col=%ws Index=%x Seek='%ws'%ws Sort=%ws cb=%x, pb=%x\n",
|
|
pwszColNameActual,
|
|
pcvr->ColumnIndex,
|
|
wszSeekOperator(pcvr->SeekOperator),
|
|
wszSkip,
|
|
wszSortOperator(pcvr->SortOrder),
|
|
pcvr->cbValue,
|
|
pcvr->pbValue));
|
|
DBGDUMPHEX((DBG_SS_CERTUTILI, 0, pcvr->pbValue, pcvr->cbValue));
|
|
|
|
error:
|
|
if (NULL != pwszColName)
|
|
{
|
|
LocalFree(pwszColName);
|
|
}
|
|
if (NULL != pwszColValue)
|
|
{
|
|
LocalFree(pwszColValue);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
verbDBDump(
|
|
IN WCHAR const *pwszOption,
|
|
IN WCHAR const *pwszRequestId,
|
|
IN WCHAR const *pwszArg2,
|
|
IN WCHAR const *pwszArg3,
|
|
IN WCHAR const *pwszArg4)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR const *pwsz;
|
|
ICertDB *pdb = NULL;
|
|
ICertDBRow *prow = NULL;
|
|
IEnumCERTDBRESULTROW *penum = NULL;
|
|
DWORD i;
|
|
DWORD imin = 1;
|
|
DWORD RequestId;
|
|
LONG cskip;
|
|
WCHAR **apwszRestrictions = NULL;
|
|
WCHAR **apwszColumns = NULL;
|
|
WCHAR **apwszAttributes = NULL;
|
|
WCHAR **apwszExtensions = NULL;
|
|
WCHAR **ppwsz;
|
|
BOOL fOneRow = FALSE;
|
|
LONG lSkip = 0;
|
|
BOOL fAllColumns;
|
|
BOOL fAllAttributes;
|
|
BOOL fAllExtensions;
|
|
CERTVIEWRESTRICTION *acvr = NULL;
|
|
DWORD ccvr;
|
|
DWORD *acol = NULL;
|
|
DWORD ccol;
|
|
CERTDBRESULTROW arow[35];
|
|
DWORD crow;
|
|
BOOL fReleaseRows = FALSE;
|
|
DWORD iRow;
|
|
DBSTATS statsRowProperties;
|
|
DBSTATS statsAttributes;
|
|
DBSTATS statsExtensions;
|
|
|
|
ZeroMemory(&statsRowProperties, sizeof(statsRowProperties));
|
|
ZeroMemory(&statsAttributes, sizeof(statsAttributes));
|
|
ZeroMemory(&statsExtensions, sizeof(statsExtensions));
|
|
|
|
if (NULL != pwszRequestId)
|
|
{
|
|
if (L'+' == *pwszRequestId)
|
|
{
|
|
hr = ParseSkipCounts(&pwszRequestId[1]);
|
|
_JumpIfError(hr, error, "ParseSkipCounts");
|
|
}
|
|
else
|
|
{
|
|
hr = myGetLong(pwszRequestId, (LONG *) &RequestId);
|
|
_JumpIfError(hr, error, "RequestId must be a number");
|
|
|
|
imin = RequestId;
|
|
fOneRow = TRUE;
|
|
}
|
|
}
|
|
pwsz = wcschr(g_pwszConfig, L'\\');
|
|
if (NULL != pwsz)
|
|
{
|
|
pwsz++;
|
|
}
|
|
else
|
|
{
|
|
pwsz = g_pwszConfig;
|
|
}
|
|
|
|
hr = cuDBOpen(pwsz, TRUE, &pdb);
|
|
_JumpIfError(hr, error, "cuDBOpen");
|
|
|
|
hr = DBLoadSchema(pdb);
|
|
_JumpIfError(hr, error, "DBLoadSchema");
|
|
|
|
if (1 < g_fVerbose)
|
|
{
|
|
hr = DBDumpSchema(pdb, NULL, 0);
|
|
_JumpIfError(hr, error, "DBDumpSchema");
|
|
}
|
|
|
|
ccvr = 0;
|
|
if (NULL != g_pwszRestrict)
|
|
{
|
|
hr = ParseViewRestrictions(g_pwszRestrict, &apwszRestrictions);
|
|
_JumpIfError(hr, error, "ParseViewRestrictions");
|
|
|
|
for (ppwsz = apwszRestrictions; NULL != *ppwsz; ppwsz++)
|
|
;
|
|
ccvr = (DWORD) (ppwsz - apwszRestrictions);
|
|
acvr = (CERTVIEWRESTRICTION *) LocalAlloc(
|
|
LMEM_FIXED | LMEM_ZEROINIT,
|
|
ccvr * sizeof(acvr[0]));
|
|
if (NULL == acvr)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
for (i = 0; i < ccvr; i++)
|
|
{
|
|
BOOL f;
|
|
LONG l;
|
|
|
|
hr = DBParseRestriction(pdb, apwszRestrictions[i], &acvr[i], &f, &l);
|
|
_JumpIfErrorStr(
|
|
hr,
|
|
error,
|
|
"DBParseRestriction",
|
|
apwszRestrictions[i]);
|
|
|
|
if (f)
|
|
{
|
|
fOneRow = TRUE;
|
|
lSkip = l;
|
|
}
|
|
}
|
|
}
|
|
|
|
ccol = 0;
|
|
fAllColumns = TRUE;
|
|
fAllAttributes = TRUE;
|
|
fAllExtensions = TRUE;
|
|
if (NULL != g_pwszOut)
|
|
{
|
|
fAllAttributes = FALSE;
|
|
fAllExtensions = FALSE;
|
|
|
|
hr = ParseViewColumns(
|
|
g_pwszOut,
|
|
NULL,
|
|
NULL,
|
|
&apwszColumns,
|
|
&fAllColumns);
|
|
_JumpIfError(hr, error, "ParseViewColumns");
|
|
|
|
if (NULL != apwszColumns)
|
|
{
|
|
for (ppwsz = apwszColumns; NULL != *ppwsz; ppwsz++)
|
|
;
|
|
|
|
ccol = (DWORD) (ppwsz - apwszColumns);
|
|
}
|
|
|
|
hr = ParseViewColumns(
|
|
g_pwszOut,
|
|
g_wszAttrib,
|
|
g_apwszAllowedPrefixes,
|
|
&apwszAttributes,
|
|
&fAllAttributes);
|
|
_JumpIfError(hr, error, "ParseViewColumns");
|
|
|
|
hr = ParseViewColumns(
|
|
g_pwszOut,
|
|
g_wszExt,
|
|
NULL,
|
|
&apwszExtensions,
|
|
&fAllExtensions);
|
|
_JumpIfError(hr, error, "ParseViewColumns");
|
|
}
|
|
|
|
if (fAllColumns)
|
|
{
|
|
ccol = g_cdcRequests + g_cdcCertificates;
|
|
}
|
|
if (0 != ccol)
|
|
{
|
|
acol = (DWORD *) LocalAlloc(LMEM_FIXED, ccol * sizeof(acol[0]));
|
|
if (NULL == acol)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
if (fAllColumns)
|
|
{
|
|
for (i = 0; i < ccol; i++)
|
|
{
|
|
CERTDBCOLUMN const *pdc;
|
|
|
|
pdc = (i < g_cdcRequests)?
|
|
&g_adcRequests[i] :
|
|
&g_adcCertificates[i - g_cdcRequests];
|
|
acol[i] = pdc->Index;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CSASSERT(NULL != apwszColumns);
|
|
for (i = 0; i < ccol; i++)
|
|
{
|
|
WCHAR const *pwszColNameActual;
|
|
LONG ColType;
|
|
|
|
hr = DBGetColumnInfo(
|
|
pdb,
|
|
apwszColumns[i],
|
|
&pwszColNameActual,
|
|
&acol[i],
|
|
&ColType);
|
|
_JumpIfErrorStr(hr, error, "DBGetColumnInfo", apwszColumns[i]);
|
|
}
|
|
}
|
|
}
|
|
if (!g_fCryptSilent)
|
|
{
|
|
hr = DBDumpSchema(pdb, acol, ccol);
|
|
_JumpIfError(hr, error, "DBDumpSchema");
|
|
}
|
|
if (NULL != g_pwszRestrict)
|
|
{
|
|
BOOL fNoMore;
|
|
LONG lIndex;
|
|
|
|
hr = pdb->OpenView(ccvr, acvr, ccol, acol, 0x0, &penum);
|
|
_JumpIfError(hr, error, "OpenView");
|
|
|
|
hr = penum->Skip(lSkip, &lIndex);
|
|
_JumpIfError(hr, error, "Skip");
|
|
|
|
iRow = 1;
|
|
fNoMore = FALSE;
|
|
while (!fNoMore)
|
|
{
|
|
hr = penum->Next(
|
|
NULL,
|
|
(ULONG)(fOneRow? 1 : ARRAYSIZE(arow)),
|
|
arow,
|
|
&crow);
|
|
if (S_FALSE == hr)
|
|
{
|
|
hr = S_OK;
|
|
fNoMore = TRUE;
|
|
}
|
|
_JumpIfError(hr, error, "Next");
|
|
|
|
fReleaseRows = TRUE;
|
|
|
|
//wprintf(L"celtFetched = %u\n", crow);
|
|
for (i = 0; i < crow; i++, iRow++)
|
|
{
|
|
hr = DBPrintRow(
|
|
pdb,
|
|
iRow,
|
|
arow[i].rowid,
|
|
&arow[i],
|
|
NULL, // acol
|
|
0, // ccol
|
|
FALSE, // fAllColumns
|
|
&statsRowProperties,
|
|
apwszAttributes,
|
|
fAllAttributes,
|
|
&statsAttributes,
|
|
apwszExtensions,
|
|
fAllExtensions,
|
|
&statsExtensions);
|
|
_JumpIfError(hr, error, "DBPrintRow");
|
|
}
|
|
|
|
if (fNoMore)
|
|
{
|
|
CSASSERT(ARRAYSIZE(arow) > crow);
|
|
CSASSERT(i == crow);
|
|
CSASSERT(arow[i].rowid == ~arow[i].ccol);
|
|
wprintf(
|
|
L"\n%ws: %u\n",
|
|
myLoadResourceString(IDS_MAXINDEX), // "Maximum Row Index"
|
|
arow[i].rowid);
|
|
}
|
|
|
|
hr = penum->ReleaseResultRow(crow, arow);
|
|
_JumpIfError(hr, error, "ReleaseResultRow");
|
|
|
|
fReleaseRows = FALSE;
|
|
|
|
if (fOneRow)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DWORD imax;
|
|
|
|
iRow = 1;
|
|
imax = fOneRow? imin + 1 : MAXDWORD;
|
|
for (i = imin; i < imax; i++, iRow++)
|
|
{
|
|
hr = DBPrintRow(
|
|
pdb,
|
|
iRow,
|
|
i, // RowId
|
|
NULL, // pResultRow
|
|
acol,
|
|
ccol,
|
|
fAllColumns,
|
|
&statsRowProperties,
|
|
apwszAttributes,
|
|
fAllAttributes,
|
|
&statsAttributes,
|
|
apwszExtensions,
|
|
fAllExtensions,
|
|
&statsExtensions);
|
|
if (CERTSRV_E_PROPERTY_EMPTY == hr) // RowId doesn't exist
|
|
{
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
_JumpIfError(hr, error, "DBPrintRow");
|
|
}
|
|
}
|
|
DumpViewStats(
|
|
iRow - 1,
|
|
&statsRowProperties,
|
|
&statsAttributes,
|
|
&statsExtensions);
|
|
|
|
error:
|
|
cuFreeStringArray(apwszRestrictions);
|
|
cuFreeStringArray(apwszColumns);
|
|
cuFreeStringArray(apwszAttributes);
|
|
cuFreeStringArray(apwszExtensions);
|
|
|
|
if (NULL != acvr)
|
|
{
|
|
for (i = 0; i < ccvr; i++)
|
|
{
|
|
if (NULL != acvr[i].pbValue)
|
|
{
|
|
LocalFree(acvr[i].pbValue);
|
|
}
|
|
}
|
|
LocalFree(acvr);
|
|
}
|
|
if (NULL != acol)
|
|
{
|
|
LocalFree(acol);
|
|
}
|
|
DBFreeSchema();
|
|
|
|
if (fReleaseRows)
|
|
{
|
|
hr = penum->ReleaseResultRow(crow, arow);
|
|
_JumpIfError(hr, error, "ReleaseResultRow");
|
|
}
|
|
|
|
// Take critical section to make sure we wait for CTL-C DB shutdown.
|
|
|
|
EnterCriticalSection(&g_DBCriticalSection);
|
|
if (cuDBIsShutDownInProgress())
|
|
{
|
|
if (myJetHResult(JET_errTermInProgress) == hr)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (NULL != penum)
|
|
{
|
|
penum->Release();
|
|
}
|
|
if (NULL != prow)
|
|
{
|
|
prow->Release();
|
|
}
|
|
}
|
|
LeaveCriticalSection(&g_DBCriticalSection);
|
|
cuDBAbortShutDown(0);
|
|
return(hr);
|
|
}
|