|
|
//+-------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1996-1996 // // File: rpc.cpp // // Contents: Cert Server RPC // // History: 03-Sep-96 larrys created // //---------------------------------------------------------------------------
#include <pch.cpp>
#pragma hdrstop
#include <ese.h> #include <lmaccess.h> #include <lmapibuf.h> #include <lmerr.h> #include <stdio.h>
#include "certrpc.h" #include "certcli.h" #include "certlib.h"
#include "cs.h" #include "csext.h" #include "csprop.h"
#include "ese.h" #include "dbtable.h"
CRITICAL_SECTION g_RPCCriticalSection; CERT_CONTEXT const *pPrevCertContext = NULL; RPC_BINDING_VECTOR *pvBindings = NULL;
#define USE_NP 1
#ifdef USE_NP char *pszProtSeq = "ncacn_np"; #else char *pszProtSeq = "ncacn_ip_tcp"; #endif
SERVICE_STATUS g_ssStatus; SERVICE_STATUS_HANDLE g_sshStatusHandle; HANDLE g_hServiceDoneEvent = NULL;
VOID ServiceControlHandler(DWORD dwCtrlCode);
BOOL ReportStatusToSCMgr( DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwCheckPoint, DWORD dwWaitHint);
typedef struct _ATTRIBVALUETABLE { WCHAR *pwAttrib; DWORD cbAttrib; WCHAR *pwValue; DWORD cbValue; } ATTRIBVALUETABLE;
DWORD RPCInit(VOID) { #ifdef USE_NP char * pszEndpoint = "\\pipe\\cert"; #endif SECURITY_DESCRIPTOR *psd; DWORD err;
if ((psd = (SECURITY_DESCRIPTOR *) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, SECURITY_DESCRIPTOR_MIN_LENGTH)) == 0) { DBGERRORPRINTLINE("LocalAlloc", ERROR_NOT_ENOUGH_MEMORY); goto fail; }
#ifdef USE_NP err = RpcServerUseProtseqEpA( (unsigned char *) pszProtSeq, RPC_C_PROTSEQ_MAX_REQS_DEFAULT, (unsigned char *) pszEndpoint, NULL); #else err = RpcServerUseProtseqA( (unsigned char *) pszProtSeq, RPC_C_PROTSEQ_MAX_REQS_DEFAULT, NULL); #endif
if (err != RPC_S_OK) { DBGERRORPRINTLINE("RpcServerUseProtseqA", err); goto fail; }
err = RpcServerInqBindings(&pvBindings); if (err != RPC_S_OK) { DBGERRORPRINTLINE("RpcServerInqBindings", err); goto fail; } err = RpcServerRegisterIf(s_ICertPassage_v0_0_s_ifspec, NULL, NULL); if (err != RPC_S_OK) { DBGERRORPRINTLINE("RpcServerRegisterIf", err); goto fail; } err = RpcEpRegister(s_ICertPassage_v0_0_s_ifspec, pvBindings, NULL, NULL); if (err != RPC_S_OK) { DBGERRORPRINTLINE("RpcEpRegister", err); goto fail; }
// Listen, but don't wait... err = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE); if (err != RPC_S_OK) { DBGERRORPRINTLINE("RpcServerListen", err); goto fail; }
fail: return(err); }
DWORD IsRpcClientAllowed( handle_t h, WCHAR *pwszUserName, DWORD cbUserName, BOOL *pbAllowed) { DWORD entriesread; DWORD totalentries; DWORD resumehandle = 0; LOCALGROUP_MEMBERS_INFO_1 *plgmi = NULL; LOCALGROUP_MEMBERS_INFO_1 *plgmiT; DWORD cnt; DWORD Totalcnt; DWORD err;
*pbAllowed = FALSE; do { err = RpcImpersonateClient((RPC_BINDING_HANDLE) h);
if (RPC_S_OK != err) { continue; // error exit }
if (!GetUserName(pwszUserName, &cbUserName)) { err = GetLastError(); } RpcRevertToSelf(); if (ERROR_SUCCESS != err) { continue; // error exit }
Totalcnt = 0; do { err = NetLocalGroupGetMembers( NULL, g_wszRequestGroupName, 1, (LPBYTE *) &plgmi, 0xffff, &entriesread, &totalentries, &resumehandle); if (NERR_Success != err) { break; }
plgmiT = plgmi;
for (cnt = 0; cnt < entriesread; cnt++) { if (lstrcmpi(plgmiT->lgrmi1_name, pwszUserName) == 0) { CONSOLEPRINT2(( DBG_SS_CERTSRV, "Found user %ws in group %ws\n", pwszUserName, g_wszRequestGroupName)); *pbAllowed = TRUE; break; } Totalcnt++; plgmiT++; } NetApiBufferFree(plgmi); } while (!*pbAllowed && Totalcnt < totalentries);
} while (FALSE);
return(err); }
BOOL IsValidAttributeChar(TCHAR chChar) { BOOL fRetVal=TRUE;
switch(chChar) { case TEXT('\r'): case TEXT('\n'): case TEXT(' '): case TEXT('-'): fRetVal = FALSE; break; }
return fRetVal; }
DWORD ParseAttributes( IN ICertDBRow *prow, IN WCHAR const *pwszAttributes) { HRESULT hr = S_OK; WCHAR *pwb = NULL; WCHAR *pwbEnd; WCHAR *pwAttrib = NULL; WCHAR *pwValue = NULL; WCHAR *pwszTemp = NULL; WCHAR const *pwszPropName; WCHAR *pwbtmp; WCHAR *pwbtmp2; WCHAR *pwbtmp3; WCHAR *pwbtmp4; DWORD cwc; DWORD i; DWORD cwcAttributes; DWORD cbProp;
if (NULL == pwszAttributes) { goto error; // silently ignore empty string } cwcAttributes = wcslen(pwszAttributes);
// Allocate and copy bytes to null terminate pwb = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwcAttributes + 1) * sizeof(WCHAR));
if (NULL == pwb) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); }
wcscpy(pwb, pwszAttributes); pwbEnd = &pwb[cwcAttributes];
pwbtmp = pwb;
while(TRUE) { pwbtmp2 = pwbtmp; pwbtmp = wcschr(pwbtmp, TEXT(':')); if (NULL == pwbtmp) { break; }
// If there's a newline before the next colon, start over.
pwbtmp3 = wcschr(pwbtmp2, TEXT('\n')); if (NULL != pwbtmp3 && pwbtmp3 < pwbtmp) { pwbtmp = pwbtmp3 + 1; continue; }
// Find beginning of Attrib string while(iswspace(*pwbtmp2)) { pwbtmp2++; }
// Count size of Attrib string cwc = pwbtmp - pwbtmp2; pwbtmp3 = pwbtmp;
// move before : pwbtmp3--; while (iswspace(*pwbtmp3) && pwbtmp3 > pwbtmp2) { cwc--; pwbtmp3--; }
pwAttrib = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR)); if (NULL == pwAttrib) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); }
pwbtmp3 = pwAttrib; for (i = 0; i < cwc; i++, pwbtmp2++) { if (IsValidAttributeChar(*pwbtmp2)) { *pwbtmp3++ = *pwbtmp2; } } *pwbtmp3 = L'\0';
// Skip over the colon pwbtmp2 = pwbtmp + 1;
// Find beginning of Value string while(L'\n' != *pwbtmp2 && iswspace(*pwbtmp2)) { pwbtmp2++; }
pwbtmp3 = pwbtmp2;
// find end of Value string pwbtmp4 = wcschr(pwbtmp3, TEXT('\n')); if (NULL == pwbtmp4) { // Check for case when last Value isn't newline terminated if (pwbtmp3 >= pwbEnd) { break; } pwbtmp4 = pwbEnd; }
cwc = pwbtmp4 - pwbtmp3; pwbtmp3 = pwbtmp4;
// move before '\n' or '\0' pwbtmp3--; while (iswspace(*pwbtmp3) && pwbtmp3 > pwbtmp2) { cwc--; pwbtmp3--; }
pwValue = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR)); if (NULL == pwValue) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } memcpy(pwValue, pwbtmp2, cwc * sizeof(WCHAR)); pwValue[cwc] = L'\0';
// if the attribute name and value are both non-empty ...
if (L'\0' != *pwValue && L'\0' != *pwAttrib) { DWORD dwTable = PROPTABLE_REQUEST;
// See if the attribute name can be mapped to a standard property.
pwszPropName = DBMapAttributeName(pwAttrib); if (NULL == pwszPropName || NULL == g_pwszNameSeparator) { if (NULL == pwszPropName) { dwTable = PROPTABLE_ATTRIBUTES; } pwszPropName = pwAttrib; } else { cbProp = 0; hr = prow->GetProperty( pwszPropName, PROPTYPE_STRING | PROPCALLER_SERVER | PROPTABLE_REQUEST, &cbProp, NULL);
if (CERTSRV_E_PROPERTY_EMPTY != hr) { _JumpIfError(hr, error, "GetProperty");
pwszTemp = (WCHAR *) LocalAlloc( LMEM_FIXED, (cbProp + 2 + wcslen(pwValue)) * sizeof(WCHAR)); if (NULL == pwszTemp) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); }
hr = prow->GetProperty( pwszPropName, PROPTYPE_STRING | PROPCALLER_SERVER | PROPTABLE_REQUEST, &cbProp, (BYTE *) pwszTemp); _JumpIfError(hr, error, "GetProperty");
wcscat(pwszTemp, g_pwszNameSeparator); wcscat(pwszTemp, L" "); wcscat(pwszTemp, pwValue); LocalFree(pwValue); pwValue = pwszTemp; pwszTemp = NULL; } }
hr = prow->SetProperty( pwszPropName, dwTable | PROPTYPE_STRING | PROPCALLER_SERVER, MAXDWORD, (BYTE const *) pwValue); _JumpIfError(hr, error, "SetProperty");
if (NULL != pwszTemp) { LocalFree(pwszTemp); pwszTemp = NULL; } }
LocalFree(pwValue); pwValue = NULL;
LocalFree(pwAttrib); pwAttrib = NULL;
if (pwbtmp4 >= pwbEnd) { break; } pwbtmp = pwbtmp4 + 1; }
error: if (NULL != pwAttrib) { LocalFree(pwAttrib); } if (NULL != pwValue) { LocalFree(pwValue); } if (NULL != pwb) { LocalFree(pwb); } if (NULL != pwszTemp) { LocalFree(pwszTemp); } return(hr); }
/* server prototype */ DWORD s_CertServerRequest( /* [in] */ handle_t h, /* [in] */ DWORD dwFlags, /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAuthority, /* [ref][out][in] */ DWORD __RPC_FAR *pdwRequestId, /* [out] */ DWORD __RPC_FAR *pdwDisposition, /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAttributes, /* [ref][in] */ CERTTRANSBLOB const __RPC_FAR *pctbRequest, /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbCertChain, /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbEncodedCert, /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbDispositionMessage) { HRESULT hr = S_OK; BOOL bAllowed = TRUE; WCHAR UserName[MAX_PATH]; DWORD OpRequest;
EnterCriticalSection(&g_RPCCriticalSection);
// Set up default output parameters:
OpRequest = CR_IN_RETRIEVE; if (NULL != pctbRequest->pb) { *pdwRequestId = 0; OpRequest = CR_IN_NEW; } *pdwDisposition = CR_DISP_ERROR;
if (0 != lstrcmpi(pwszAuthority, g_wszAuthority)) { hr = E_INVALIDARG; _JumpError(hr, error, "Bad Authority name"); }
//BUGBUG: do something with the error: pass it in the policy module flags? hr = IsRpcClientAllowed(h, UserName, sizeof(UserName), &bAllowed);
hr = CoreProcessRequest( OpRequest | (dwFlags & CR_IN_FORMATMASK), UserName, pctbRequest->cb, // cbRequest pctbRequest->pb, // pbRequest pwszAttributes, (WCHAR **) &pctbDispositionMessage->pb, pdwRequestId, pdwDisposition, &pctbCertChain->pb, // Allocates returned memory &pctbCertChain->cb, &pctbEncodedCert->pb,// Allocates returned memory &pctbEncodedCert->cb); _JumpIfError(hr, error, "CoreProcessRequest");
error: pctbDispositionMessage->cb = 0; if (NULL != pctbDispositionMessage->pb) { pctbDispositionMessage->cb = (wcslen((WCHAR *) pctbDispositionMessage->pb) + 1) * sizeof(WCHAR); }
LeaveCriticalSection(&g_RPCCriticalSection); PKCSCRLTimerProc(NULL, 0, 0, 0); return(hr); }
typedef struct _CRLELEMENT { LIST_ENTRY Next; CRYPT_INTEGER_BLOB SerialNumber; FILETIME RevocationDate; } CRLELEMENT;
VOID FreeCRLArray( IN DWORD cCRL, IN OUT CRL_ENTRY *aCRL) { if (NULL != aCRL) { CRL_ENTRY *pCRL = &aCRL[cCRL];
while (--pCRL >= aCRL) { if (NULL != pCRL->SerialNumber.pbData) { LocalFree(pCRL->SerialNumber.pbData); } } LocalFree(aCRL); } }
// Convert linked list of CRL_ENTRYs to an array. // If the output array pointer is NULL, just free the list.
HRESULT ConvertOrFreeCRLList( IN OUT LIST_ENTRY *pleCRL, IN DWORD cCRL, OPTIONAL OUT CRL_ENTRY **paCRL) { HRESULT hr; CRL_ENTRY *aCRL = NULL; CRL_ENTRY *pCRL; CRL_ENTRY *pCRLT; DWORD i; LIST_ENTRY *pleNext; CRLELEMENT *pElement;
if (NULL != paCRL) { aCRL = (CRL_ENTRY *) LocalAlloc(LMEM_ZEROINIT, sizeof(aCRL[0]) * cCRL); if (NULL == aCRL) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } }
pCRL = aCRL; pleNext = pleCRL->Flink; for (i = 0; pleNext != pleCRL; i++) { pElement = CONTAINING_RECORD(pleNext, CRLELEMENT, Next); pleNext = pleNext->Flink;
if (NULL != pElement) { if (NULL != pCRL) { pCRL->SerialNumber.pbData = pElement->SerialNumber.pbData; pCRL->SerialNumber.cbData = pElement->SerialNumber.cbData; pCRL->RevocationDate = pElement->RevocationDate; pCRL++; } else { if (NULL != pElement->SerialNumber.pbData) { LocalFree(pElement->SerialNumber.pbData); } } RemoveEntryList(&pElement->Next); LocalFree(pElement); } } CSASSERT(i == cCRL);
if (NULL != paCRL) { *paCRL = aCRL; aCRL = NULL; } hr = S_OK;
error: if (NULL != aCRL) { FreeCRLArray(cCRL, aCRL); } return(hr); }
HRESULT AddCRLElement( IN OUT LIST_ENTRY *pleCRL, WCHAR const *pwszSerialNumber, FILETIME const *pftRevokedEffectiveWhen) { HRESULT hr = S_OK; CRLELEMENT *pElement = NULL;
pElement = (CRLELEMENT *) LocalAlloc(LMEM_ZEROINIT, sizeof(CRLELEMENT)); if (NULL == pElement) { hr = ERROR_NOT_ENOUGH_MEMORY; goto error; }
hr = myWszToMultiByteInteger( pwszSerialNumber, &pElement->SerialNumber.cbData, &pElement->SerialNumber.pbData); _JumpIfError(hr, error, "myWszToMultiByteInteger");
pElement->RevocationDate = *pftRevokedEffectiveWhen;
InsertTailList(pleCRL, &pElement->Next); pElement = NULL;
error: if (NULL != pElement) { LocalFree(pElement); } return(hr); }
DWORD g_aColCRL[] = {
#define ICOL_REQUESTID 0 DTI_CERTIFICATETABLE | DTC_REQUESTID,
#define ICOL_EFFECTIVEWHEN 1 DTI_REQUESTTABLE | DTR_REQUESTREVOKEDEFFECTIVEWHEN,
#define ICOL_SERIAL 2 DTI_CERTIFICATETABLE | DTC_CERTIFICATESERIALNUMBER,
#define ICOL_NOTAFTER 3 DTI_CERTIFICATETABLE | DTC_CERTIFICATENOTAFTERDATE, };
#define CCOL_CRLVIEW (sizeof(g_aColCRL)/sizeof(g_aColCRL[0]))
HRESULT BuildCRLList( OUT LIST_ENTRY *pleCRL, IN DWORD *pcCRL, IN FILETIME ThisUpdate) { HRESULT hr; CERTVIEWRESTRICTION cvr; IEnumCERTDBRESULTROW *pView = NULL; DWORD celtFetched; DWORD Disposition; DWORD i; BOOL fCoInitialized = FALSE; DWORD cCRL = 0; CERTDBRESULTROW Result; BOOL fResultActive = FALSE;
Disposition = CR_DISP_REVOKED;
cvr.ColumnIndex = DTI_REQUESTTABLE | DTR_REQUESTDISPOSITION; cvr.dwSeek = CVR_SEEK_EQ; cvr.pbValue = (BYTE *) &Disposition; cvr.cbValue = sizeof(Disposition);
hr = CoInitialize(NULL); if (S_OK != hr && S_FALSE != hr) { _JumpError(hr, error, "CoInitialize"); } fCoInitialized = TRUE;
hr = g_pCertDB->OpenView( 1, &cvr, CCOL_CRLVIEW, g_aColCRL, &pView); _JumpIfError(hr, error, "OpenView");
while (TRUE) { hr = pView->Next(1, &Result, &celtFetched); if (S_FALSE == hr) { break; } _JumpIfError(hr, error, "Next");
fResultActive = TRUE;
CSASSERT(1 == celtFetched); CSASSERT(CCOL_CRLVIEW == Result.ccol);
CSASSERT(PROPTYPE_LONG == Result.acol[ICOL_REQUESTID].Type); CSASSERT(PROPTYPE_DATE == Result.acol[ICOL_EFFECTIVEWHEN].Type); CSASSERT(PROPTYPE_STRING == Result.acol[ICOL_SERIAL].Type); CSASSERT(PROPTYPE_DATE == Result.acol[ICOL_NOTAFTER].Type);
CSASSERT(NULL != Result.acol[ICOL_REQUESTID].pbValue); CSASSERT(NULL != Result.acol[ICOL_SERIAL].pbValue); CSASSERT(NULL != Result.acol[ICOL_NOTAFTER].pbValue);
CSASSERT(sizeof(DWORD) == Result.acol[ICOL_REQUESTID].cbValue); CSASSERT( sizeof(FILETIME) == Result.acol[ICOL_EFFECTIVEWHEN].cbValue || NULL == Result.acol[ICOL_EFFECTIVEWHEN].pbValue); CSASSERT(0 < Result.acol[ICOL_SERIAL].cbValue); CSASSERT(sizeof(FILETIME) == Result.acol[ICOL_NOTAFTER].cbValue);
if (NULL != Result.acol[ICOL_NOTAFTER].pbValue && NULL != Result.acol[ICOL_EFFECTIVEWHEN].pbValue && NULL != Result.acol[ICOL_SERIAL].pbValue && CompareFileTime( (FILETIME *) Result.acol[ICOL_NOTAFTER].pbValue, &ThisUpdate) > 0 && CompareFileTime( (FILETIME *) Result.acol[ICOL_EFFECTIVEWHEN].pbValue, &ThisUpdate) < 0) { hr = AddCRLElement( pleCRL, (WCHAR const *) Result.acol[ICOL_SERIAL].pbValue, (FILETIME const *) Result.acol[ICOL_EFFECTIVEWHEN].pbValue); _JumpIfError(hr, error, "AddCRLElement");
CONSOLEPRINT1(( DBG_SS_CERTSRV, "Cert is revoked: %ws\n", Result.acol[ICOL_SERIAL].pbValue)); cCRL++; } pView->ReleaseResultRow(1, &Result); fResultActive = FALSE; }
*pcCRL = cCRL; hr = S_OK;
error: if (NULL != pView) { if (fResultActive) { pView->ReleaseResultRow(1, &Result); } pView->Release(); } if (fCoInitialized) { CoUninitialize(); } return(hr); }
HRESULT BuildCRLArray( IN FILETIME ThisUpdate, OUT DWORD *pcCRL, OUT CRL_ENTRY **paCRL) { HRESULT hr; LIST_ENTRY leCRL;
*pcCRL = 0; *paCRL = NULL; InitializeListHead(&leCRL);
hr = BuildCRLList(&leCRL, pcCRL, ThisUpdate); _JumpIfError(hr, error, "BuildCRLList");
hr = ConvertOrFreeCRLList(&leCRL, *pcCRL, paCRL); _JumpIfError(hr, error, "ConvertOrFreeCRLList");
error: ConvertOrFreeCRLList(&leCRL, 0, NULL); return(hr); }
void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t cb) { return(LocalAlloc(LMEM_ZEROINIT, cb)); }
void __RPC_USER MIDL_user_free( void __RPC_FAR * pb) { LocalFree(pb); }
VOID ServiceMain( IN DWORD dwArgc, IN LPWSTR *lpszArgv) { HRESULT hr = S_OK;
g_sshStatusHandle = RegisterServiceCtrlHandler( g_wszCertSrvServiceName, ServiceControlHandler); if (NULL == g_sshStatusHandle) { hr = GetLastError(); _JumpError(hr, error, "RegisterServiceCtrlHandler"); }
g_ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; g_ssStatus.dwServiceSpecificExitCode = 0;
ReportStatusToSCMgr(SERVICE_START_PENDING, hr, 1, 3000); g_hServiceDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (NULL == g_hServiceDoneEvent) { hr = GetLastError(); _JumpError(hr, error, "CreateEvent"); }
if (0 != g_dwDelay2) { DBGPRINT(( DBG_SS_CERTSRV, "ServiceMain: sleeping %u seconds\n", g_dwDelay2)); Sleep(1000 * g_dwDelay2); }
hr = certsrvStartServerThread((VOID *) 0); _JumpIfError(hr, error, "certsrvStartServer");
ReportStatusToSCMgr(SERVICE_RUNNING, hr, 0, 0);
WaitForSingleObject(g_hServiceDoneEvent, INFINITE); DBGPRINT((DBG_SS_CERTSRV, "ServiceMain: Service Done\n"));
error: ReportStatusToSCMgr(SERVICE_STOPPED, hr, 0, 0); if (NULL != g_hServiceDoneEvent) { CloseHandle(g_hServiceDoneEvent); } DBGPRINT((DBG_SS_CERTSRV, "ServiceMain: Exit: %x\n", hr)); }
VOID ServiceControlHandler( IN DWORD dwCtrlCode) { DWORD dwState = SERVICE_RUNNING;
switch (dwCtrlCode) { case SERVICE_CONTROL_PAUSE: if (SERVICE_RUNNING == g_ssStatus.dwCurrentState) { dwState = SERVICE_PAUSED; } break;
case SERVICE_CONTROL_CONTINUE: if (SERVICE_PAUSED == g_ssStatus.dwCurrentState) { dwState = SERVICE_RUNNING; } break;
case SERVICE_CONTROL_STOP: ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 1, 3000); certsrvStopServer(FALSE); SetEvent(g_hServiceDoneEvent); return;
case SERVICE_CONTROL_INTERROGATE: break; } ReportStatusToSCMgr(dwState, NO_ERROR, 0, 0); }
BOOL ReportStatusToSCMgr( IN DWORD dwCurrentState, IN DWORD dwWin32ExitCode, IN DWORD dwCheckPoint, IN DWORD dwWaitHint) { BOOL fResult; HRESULT hr;
g_ssStatus.dwControlsAccepted = SERVICE_START_PENDING == dwCurrentState? 0 : SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
g_ssStatus.dwCurrentState = dwCurrentState; g_ssStatus.dwWin32ExitCode = dwWin32ExitCode; g_ssStatus.dwCheckPoint = dwCheckPoint; g_ssStatus.dwWaitHint = dwWaitHint;
fResult = SetServiceStatus(g_sshStatusHandle, &g_ssStatus); if (!fResult) { hr = GetLastError(); _JumpError(hr, error, "SetServiceStatus"); } DBGPRINT(( DBG_SS_CERTSRV, "ReportStatusToSCMgr(state=%x, hr=%x, ckpt=%x, wait=%x)\n", dwCurrentState, dwWin32ExitCode, dwCheckPoint, dwWaitHint));
error: return(fResult); }
|