//----------------------------------------------------------------------------- // Copyright (C) Microsoft Corporation, 1997 - 1999 // // rpcisapi.cxx // // IIS ISAPI extension part of the RPC proxy over HTTP. // // Exports: // // BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO *pVer ) // // Returns the version of the spec that this server was built with. // // BOOL WINAPI HttpExtensionProc( EXTENSION_CONTROL_BLOCK *pECB ) // // This function does all of the work. // //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Includes: //----------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include "ecblist.h" #include "filter.h" #include "olist.h" #include "server.h" //----------------------------------------------------------------------------- // Globals: //----------------------------------------------------------------------------- extern SERVER_INFO *g_pServerInfo; extern BOOL g_fIsIIS6; //----------------------------------------------------------------------------- // GetExtensionVersion() // //----------------------------------------------------------------------------- BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO *pVer ) { pVer->dwExtensionVersion = MAKELONG( HSE_VERSION_MINOR, HSE_VERSION_MAJOR ); ASSERT( sizeof(EXTENSION_DESCRIPTION) <= HSE_MAX_EXT_DLL_NAME_LEN ); lstrcpy( pVer->lpszExtensionDesc, EXTENSION_DESCRIPTION ); return TRUE; } //----------------------------------------------------------------------------- // ReplyToClient() // //----------------------------------------------------------------------------- BOOL ReplyToClient( EXTENSION_CONTROL_BLOCK *pECB, char *pBuffer, DWORD *pdwSize, DWORD *pdwStatus ) { DWORD dwFlags = (HSE_IO_SYNC | HSE_IO_NODELAY); if (!pECB->WriteClient(pECB->ConnID,pBuffer,pdwSize,dwFlags)) { *pdwStatus = GetLastError(); #ifdef DBG_ERROR DbgPrint("ReplyToClient(): failed: %d\n",*pdwStatus); #endif return FALSE; } *pdwStatus = HSE_STATUS_SUCCESS; return TRUE; } //----------------------------------------------------------------------------- // ParseQueryString() // // The query string is in the format: // // // // Where the index is in ASCII Hex. The index is read and converted back // to a DWORD then used to locate the SERVER_OVERLAPPED. If its found, // return TRUE, else return FALSE. // // NOTE: "&" is the parameter separator if multiple parameters are passed. //----------------------------------------------------------------------------- BOOL ParseQueryString( unsigned char *pszQuery, SERVER_OVERLAPPED **ppOverlapped, DWORD *pdwStatus ) { DWORD dwIndex = 0; pszQuery = AnsiHexToDWORD(pszQuery,&dwIndex,pdwStatus); if (!pszQuery) { return FALSE; } *ppOverlapped = GetOverlapped(dwIndex); if (*ppOverlapped == NULL) { return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // HttpExtensionProc() // //----------------------------------------------------------------------------- DWORD WINAPI HttpExtensionProc( EXTENSION_CONTROL_BLOCK *pECB ) { DWORD dwStatus; DWORD dwFlags; DWORD dwSize; SERVER_INFO *pServerInfo = g_pServerInfo; SERVER_OVERLAPPED *pOverlapped = NULL; HSE_SEND_HEADER_EX_INFO HeaderEx; CHAR *pVerb; pECB->dwHttpStatusCode = STATUS_CONNECTION_OK; if (g_fIsIIS6) { pVerb = RPC_CONNECT; } else { pVerb = POST_STR; } // // The RPC request must be a post (or RPC_CONNECT for 6.0): // if (_mbsicmp(pECB->lpszMethod,pVerb)) { dwSize = sizeof(STATUS_MUST_BE_POST_STR) - 1; // don't want to count trailing 0. ReplyToClient(pECB,STATUS_MUST_BE_POST_STR,&dwSize,&dwStatus); return HSE_STATUS_SUCCESS; } // // Make sure there is no data from the initial BIND in the ECB data buffer: // // ASSERT(pECB->cbTotalBytes == 0); // // Get the connect parameters: // if (!ParseQueryString(pECB->lpszQueryString,&pOverlapped,&dwStatus)) { dwSize = sizeof(STATUS_POST_BAD_FORMAT_STR) - 1; // don't want to count trailing 0. ReplyToClient(pECB,STATUS_POST_BAD_FORMAT_STR,&dwSize,&dwStatus); return HSE_STATUS_SUCCESS; } pOverlapped->pECB = pECB; // // Add the new ECB to the Active ECB List: // if (!AddToECBList(g_pServerInfo->pActiveECBList,pECB)) { #ifdef DBG_ERROR DbgPrint("HttpExtensionProc(): AddToECBList() failed\n"); #endif FreeOverlapped(pOverlapped); pECB->dwHttpStatusCode = STATUS_SERVER_ERROR; return HSE_STATUS_ERROR; } // // Submit the first client async read: // if (!StartAsyncClientRead(pECB,pOverlapped->pConn,&dwStatus)) { #ifdef DBG_ERROR DbgPrint("HttpExtensionProc(): StartAsyncClientRead() failed %d\n",dwStatus); #endif FreeOverlapped(pOverlapped); CleanupECB(pECB); pECB->dwHttpStatusCode = STATUS_SERVER_ERROR; return HSE_STATUS_ERROR; } // // Post the first server read on the new socket: // IncrementECBRefCount(pServerInfo->pActiveECBList,pECB); if (!SubmitNewRead(pServerInfo,pOverlapped,&dwStatus)) { #ifdef DBG_ERROR DbgPrint("HttpExtensionProc(): SubmitNewRead() failed %d\n",dwStatus); #endif FreeOverlapped(pOverlapped); CleanupECB(pECB); pECB->dwHttpStatusCode = STATUS_SERVER_ERROR; return HSE_STATUS_ERROR; } // // Make sure the server receive thread is up and running: // if (!CheckStartReceiveThread(g_pServerInfo,&dwStatus)) { #ifdef DBG_ERROR DbgPrint("HttpExtensionProc(): CheckStartReceiveThread() failed %d\n",dwStatus); #endif FreeOverlapped(pOverlapped); CleanupECB(pECB); pECB->dwHttpStatusCode = STATUS_SERVER_ERROR; return HSE_STATUS_ERROR; } // // Send back connection Ok to client, and also set fKeepConn to FALSE. // dwSize = sizeof(HeaderEx); dwFlags = 0; memset(&HeaderEx,0,dwSize); HeaderEx.fKeepConn = FALSE; if (!pECB->ServerSupportFunction(pECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER_EX, &HeaderEx, &dwSize, &dwFlags)) { #ifdef DBG_ERROR DbgPrint("HttpExtensionProc(): SSF(HSE_REQ_SEND_RESPONSE_HEADER_EX) failed %d\n",dwStatus); #endif FreeOverlapped(pOverlapped); CleanupECB(pECB); pECB->dwHttpStatusCode = STATUS_SERVER_ERROR; return HSE_STATUS_ERROR; } return HSE_STATUS_PENDING; }