int CHttpServer::CallFunction(CHttpServerContext* pCtxt, LPTSTR pszQuery, LPTSTR pszCommand) { int nRet; AFX_PARSEMAP_ENTRY* pParams; const AFX_PARSEMAP* pMap; const AFX_PARSEMAP_ENTRY* pFn; ISAPIASSERT(pCtxt->m_pStream == NULL); pCtxt->m_pStream = ConstructStream(); if (pCtxt->m_pStream == NULL) nRet = callNoStream; else { ISAPIASSERT(pszQuery != NULL); if (pszQuery == NULL) nRet = callBadCommand; else { LPTSTR pszMethod; LPTSTR pszParams; // did the user specify a command via "MfcISAPICommand"? LPTSTR pszHiddenCommand = _tcschr(pszQuery, '='); if (pszHiddenCommand != NULL) { *pszHiddenCommand = '\0'; // is it there? if (_tcsicmp(pszQuery, _T("MfcISAPICommand")) == 0) { // did they have a method, too? pszMethod = pszHiddenCommand+1; if (*pszMethod == '\0') pszParams = pszMethod; else { pszParams = _tcschr(pszMethod, m_cTokenDelimiter); if (pszParams != NULL && *pszParams != '\0') *pszParams++ = '\0'; } // if we find it, we can call it pFn = LookUp(pszMethod, pMap, pParams); if (pFn != NULL) goto MakeTheCall; } // we didn't find the command, or we didn't have // "MfcISAPICommand", so we'll try and process things // normally... *pszHiddenCommand = '='; } if (pszCommand == NULL) { // got something via a GET method // is the first thing a parameter or a command? LPTSTR pszEquals; LPTSTR pszQMark; pszParams = _tcschr(pszQuery, m_cTokenDelimiter); pszQMark = _tcschr(pszQuery, '?'); // Parameters start at the first delimiter if (pszParams == NULL || (pszQMark != NULL && (pszQMark < pszParams))) { pszParams = pszQMark; // if the command ends in question mark // and nothing else, ignore it if (pszQMark != NULL && pszQMark[1] == '\0') { *pszQMark = '\0'; pszParams = NULL; } } // Does an equals sign show up before the first delimiter? pszEquals = _tcschr(pszQuery, '='); if (pszEquals == NULL || pszEquals > pszParams) { // It might be a command. If it isn't blank, // try and find it in the parameter map--if // we can't, then assume it is a parameter. pszMethod = pszQuery; if (*pszMethod != '\0') { TCHAR cTemp; if (pszParams != NULL) { cTemp = *pszParams; *pszParams++ = '\0'; } pFn = LookUp(pszMethod, pMap, pParams); if (pFn != NULL) goto MakeTheCall; if (pszParams != NULL) *--pszParams = cTemp; } } // we can be sure it's a parameter if (pszQMark == NULL || pszQMark >= pszParams) { // default command, params as supplied pszMethod = NULL; pszParams = pszQuery; } else { pszMethod = pszQuery; *pszQMark++ = '\0'; pszParams = pszQMark; } } else { // with a POST, the verb arrives seperately pszMethod = pszCommand; pszParams = pszQuery; } // is it a default verb? if (pszMethod != NULL && _tcslen(pszMethod) == 0) pszMethod = NULL; // is it a useless parameter? if (pszParams != NULL && _tcslen(pszParams) == 0) pszParams = NULL; pFn = LookUp(pszMethod, pMap, pParams); MakeTheCall: if (pFn == NULL) nRet = callBadCommand; else { pCtxt->m_pStream->InitStream(); nRet = CallMemberFunc(pCtxt, pFn, pParams, pszParams); } } } return nRet; }
BOOL CCmdTarget::OnEvent(UINT idCtrl, AFX_EVENT* pEvent, AFX_CMDHANDLERINFO* pHandlerInfo) { HRESULT hResult = S_OK; UINT uArgError = (UINT)-1; // no error yet const AFX_EVENTSINKMAP_ENTRY* pEntry = GetEventSinkEntry(idCtrl, pEvent); // no handler for this event if (pEntry == NULL) return FALSE; if (pHandlerInfo != NULL) { // just fill in the information, don't do it pHandlerInfo->pTarget = this; switch (pEvent->m_eventKind) { case AFX_EVENT::event: case AFX_EVENT::propRequest: pHandlerInfo->pmf = pEntry->dispEntry.pfn; break; case AFX_EVENT::propChanged: pHandlerInfo->pmf = pEntry->dispEntry.pfnSet; break; default: ASSERT(FALSE); // bogus value for pEvent->m_eventKind } return (pHandlerInfo->pmf != NULL); } BOOL bRange = (pEntry->nCtrlIDLast != (UINT)-1); BOOL bHandled = FALSE; TRY { switch (pEvent->m_eventKind) { case AFX_EVENT::event: // do standard method call VARIANT var; AfxVariantInit(&var); DISPPARAMS dispparams; dispparams.rgvarg = NULL; if (bRange) { memcpy(&dispparams, pEvent->m_pDispParams, sizeof(DISPPARAMS)); dispparams.rgvarg = new VARIANT[++dispparams.cArgs]; memcpy(dispparams.rgvarg, pEvent->m_pDispParams->rgvarg, sizeof(VARIANT) * (dispparams.cArgs-1)); VARIANT* pvarID = &dispparams.rgvarg[dispparams.cArgs-1]; V_VT(pvarID) = VT_I4; V_I4(pvarID) = idCtrl; } hResult = CallMemberFunc(&pEntry->dispEntry, DISPATCH_METHOD, &var, (bRange ? &dispparams : pEvent->m_pDispParams), &uArgError); ASSERT(FAILED(hResult) || (V_VT(&var) == VT_BOOL)); bHandled = V_BOOL(&var); if (bRange) delete [] dispparams.rgvarg; break; case AFX_EVENT::propChanged: { if (bRange) { PFN_CHANGED_RANGE pfn = (PFN_CHANGED_RANGE)pEntry->dispEntry.pfnSet; bHandled = (this->*pfn)(idCtrl); } else { PFN_CHANGED pfn = (PFN_CHANGED)pEntry->dispEntry.pfnSet; bHandled = (this->*pfn)(); } hResult = S_OK; } break; case AFX_EVENT::propRequest: { BOOL bAllow = TRUE; if (bRange) { PFN_REQUEST_RANGE pfn = (PFN_REQUEST_RANGE)pEntry->dispEntry.pfn; bHandled = (this->*pfn)(idCtrl, &bAllow); } else { PFN_REQUEST pfn = (PFN_REQUEST)pEntry->dispEntry.pfn; bHandled = (this->*pfn)(&bAllow); } hResult = bAllow ? S_OK : S_FALSE; } break; case AFX_EVENT::propDSCNotify: { BOOL bAllow = TRUE; if (bRange) { PFN_DSCNOTIFY_RANGE pfn = (PFN_DSCNOTIFY_RANGE)pEntry->dispEntry.pfn; bHandled = (this->*pfn)(idCtrl, pEvent->m_nDSCState, pEvent->m_nDSCReason, &bAllow); } else { PFN_DSCNOTIFY pfn = (PFN_DSCNOTIFY)pEntry->dispEntry.pfn; bHandled = (this->*pfn)(pEvent->m_nDSCState, pEvent->m_nDSCReason, &bAllow); } hResult = bAllow ? S_OK : S_FALSE; } break; default: ASSERT(FALSE); // bogus value for pEvent->m_eventKind } } CATCH_ALL(e) { if (pEvent->m_pExcepInfo != NULL) { // fill exception with translation of MFC exception COleDispatchException::Process(pEvent->m_pExcepInfo, e); } DELETE_EXCEPTION(e); hResult = DISP_E_EXCEPTION; } END_CATCH_ALL // fill error argument if one is available if (FAILED(hResult) && pEvent->m_puArgError != NULL && uArgError != -1) *pEvent->m_puArgError = uArgError; // fill result code pEvent->m_hResult = hResult; return bHandled; }