home *** CD-ROM | disk | FTP | other *** search
- /*
-
- OLEISAPI.CPP
-
- Copyright (c)1995 Microsoft Corporation, All Right Reserved
-
- Implements an ISAPI dll that will invoke OLE Automation objects
- using IDispatch. Any object that has a PROGID and implements one
- or more methods with the following signature can be called by this dll:
-
- HRESULT SomeMethod(BSTR request, BSTR response)
-
- The first BSTR will contain either the HTTP query string (in the case
- of a "GET" request) or the data contained in the HTTP request (in the
- case of a "POST" request). The second BSTR should be set by the object
- to contain the HTTP response. Note that the beginning of this string
- should always be "Content-Type: " followed by a valid MIME type.
-
- URLs that invoke this service from a link will look like this:
-
- http://machine/path/progid.method?foo=bar&baz=bleh
-
- This dll will also work with HTML forms that use the POST method,
- in which case the parameters to the call will come from the form
- elements rather than the URL. Any parameters sent as part of the
- action URL will not be passed on to the OLE object.
-
- Exports:
-
- BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO *pVer )
- BOOL WINAPI HttpExtensionProc( EXTENSION_CONTROL_BLOCK *pECB )
- DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID pvReserved)
-
- */
-
- #include <windows.h>
- #include <httpext.h>
- #include <memory.h>
- #include <stdio.h>
-
- #define PARAMLEN 1024
- #define BUFLEN 4096
-
- // TLS is used to store OLE initialization flag
- static DWORD g_dwTLSIndex = (DWORD)-1;
-
- // Many OA objects are not threadsafe, so we only allow one at a time
- static CRITICAL_SECTION g_csRuntime;
-
- HRESULT HResultFromLastError()
- {
- DWORD dwLastError = GetLastError();
- return HRESULT_FROM_WIN32(dwLastError);
- }
-
- //
- // Retrieve the class Id from the registry given its program id name.
- // The program ID name is converted from ASCII to wide char here since
- // URL strings are always ASCII.
- //
- HRESULT GetClsidFromProgIdA(LPCLSID pclsid, CHAR* pszName, long cbName)
- {
- HRESULT hr;
- // Allocate a wide char string for the Prog Id name.
- OLECHAR *lpWideCharProgId = new WCHAR[cbName];
- if (NULL == lpWideCharProgId) {
- hr = ResultFromScode(E_OUTOFMEMORY);
- goto LError;
- }
-
- // Convert the ProgId name to wide chars.
- if (0 == MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, pszName, -1,
- lpWideCharProgId, cbName) ) {
- hr = (HResultFromLastError());
- goto LError;
- }
-
- // Now get the class Id from the Program Id.
- hr = CLSIDFromProgID(lpWideCharProgId, pclsid);
-
- LError:
- if (NULL != lpWideCharProgId) {
- delete [] lpWideCharProgId;
- }
- return(hr);
- }
-
- //
- // Invoke obtains the prog ID and method to be invoked and blasts away.
- // If successful, it returns a string to be forced back up the pipe, else NULL
- //
- BOOL CallObject(EXTENSION_CONTROL_BLOCK *pECB,
- CHAR *pszProgid,
- CHAR *pszMethod)
- {
- BOOL fSuccess = FALSE;
- BOOL fInCritSec = FALSE;
- HRESULT hr;
- CLSID clsid;
- IDispatch *pdispObj = NULL;
- IUnknown *punkObj = NULL;
- OLECHAR wzMethod[PARAMLEN];
- OLECHAR wzParams[PARAMLEN];
- BSTR bstrParams = NULL;
- BSTR bstrRetval = NULL;
- CHAR *pszResults = NULL;
- DWORD buflen = 0;
-
- OLECHAR *pwzName;
- DISPID dispidMethod;
- DISPPARAMS dispparms;
- VARIANTARG varg[2];
- EXCEPINFO excep;
-
- // initialize everything up front so cleanup is safe
- memset(&dispparms, 0, sizeof(DISPPARAMS));
- memset(&varg, 0, sizeof(VARIANTARG) * 2);
- memset(&excep, 0, sizeof(EXCEPINFO));
- memset(wzParams, 0, PARAMLEN);
-
- VariantInit(&varg[0]);
- VariantInit(&varg[1]);
-
- // convert progid to clsid
- hr = GetClsidFromProgIdA(&clsid, pszProgid, lstrlen(pszProgid)+1);
- if (FAILED(hr)) goto Err;
-
- // Grab critical section
- EnterCriticalSection(&g_csRuntime);
- fInCritSec = TRUE;
-
- // instantiate object
- CoCreateInstance(clsid, NULL, CLSCTX_SERVER, IID_IUnknown, (LPVOID *) &punkObj);
- if (punkObj == NULL) goto Err;
- hr = punkObj->QueryInterface(IID_IDispatch, (void**)&pdispObj);
- if (FAILED(hr) || pdispObj == NULL) goto Err;
- punkObj->Release();
- punkObj = NULL;
-
- // Convert the method name and args to Wide character.
- if (0 == MultiByteToWideChar(CP_ACP, 0, pszMethod, -1, wzMethod, PARAMLEN) ) {
- goto Err;
- }
-
- // If POST, grab data from control block
- if (0 == strcmp(pECB->lpszMethod, "POST")) {
- if (0 == MultiByteToWideChar(CP_ACP, 0, (const char*)pECB->lpbData, pECB->cbAvailable, wzParams, PARAMLEN) ) {
- goto Err;
- }
- }
- // otherwise, get it from the query string
- else if (NULL != pECB->lpszQueryString) {
- if (0 == MultiByteToWideChar(CP_ACP, 0, pECB->lpszQueryString, -1, wzParams, PARAMLEN) ) {
- goto Err;
- }
- } else {
- wzParams[0] = (WCHAR)0;
- }
- bstrParams = SysAllocString(wzParams);
- if (NULL == bstrParams) goto Err;
- bstrRetval = SysAllocString(L"");
- if (NULL == bstrRetval) goto Err;
-
- // Find method name
- pwzName = wzMethod;
- hr = pdispObj->GetIDsOfNames(IID_NULL, &pwzName, 1, LOCALE_USER_DEFAULT, &dispidMethod);
- if (FAILED(hr)) goto Err;
-
- // Setup parameters
- dispparms.rgvarg = varg;
- dispparms.rgdispidNamedArgs = NULL;
- dispparms.cArgs = 2;
- dispparms.cNamedArgs = 0;
-
- // Push in reverse order
- varg[0].vt = VT_BSTR | VT_BYREF;
- varg[0].pbstrVal = &bstrRetval;
- varg[1].vt = VT_BSTR | VT_BYREF;
- varg[1].pbstrVal = &bstrParams;
-
- // Now make the invocation.
- hr = pdispObj->Invoke(dispidMethod, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD,
- &dispparms, NULL, &excep, NULL);
- if (FAILED(hr)) goto Err;
-
- // Release critical section
- fInCritSec = FALSE;
- LeaveCriticalSection(&g_csRuntime);
-
- // Assemble result
- buflen = wcslen(*(varg[0].pbstrVal));
- if (buflen > 0) {
- pszResults = (CHAR*)malloc(buflen + 1);
- if (0 == WideCharToMultiByte(CP_ACP, 0, *(varg[0].pbstrVal), -1, pszResults, BUFLEN, NULL, NULL)) {
- goto Err;
- }
- // null terminate string
- *(pszResults + buflen) = 0;
- }
-
- pECB->ServerSupportFunction(pECB->ConnID,
- HSE_REQ_SEND_RESPONSE_HEADER,
- (LPDWORD) "200 means groovy",
- NULL,
- (LPDWORD)(pszResults));
- fSuccess = TRUE;
-
- // Always fall through to cleanup
- Err:
- if (fInCritSec) {
- // Release critical section
- LeaveCriticalSection(&g_csRuntime);
- }
- if (pdispObj != NULL) {
- pdispObj->Release();
- }
- VariantClear(&varg[1]);
- VariantClear(&varg[2]);
- if (NULL != pszResults) {
- free(pszResults);
- }
- return fSuccess;
- }
-
- void ErrorResponse(EXTENSION_CONTROL_BLOCK *pECB,
- CHAR *pszProgid,
- CHAR *pszMethod)
- {
- CHAR pszBuf[BUFLEN];
-
- _snprintf(pszBuf, BUFLEN, "Content-Type: text/html\r\n\r\n<body><h1>"
- "OLEISAPI call failed</h1><p><b>Progid is:</b> %s\n<p><b>Method is:</b> %s\n<p>"
- "<b>GET parameters are:</b> %s\n<p><b>POST parameters are:</b> %.*s</b></body>",
- ((NULL != pszProgid) ? pszProgid : ""),
- ((NULL != pszMethod) ? pszMethod : ""),
- ((NULL != pECB->lpszQueryString) ? pECB->lpszQueryString : ""),
- (pECB->cbAvailable > 0 ? pECB->cbAvailable : 1),
- (pECB->cbAvailable > 0 ? (CHAR*)pECB->lpbData : ""));
-
- pECB->ServerSupportFunction(pECB->ConnID,
- HSE_REQ_SEND_RESPONSE_HEADER,
- (LPDWORD) "200 Baaaad Request",
- NULL,
- (LPDWORD)pszBuf);
- }
-
- BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer)
- {
- pVer->dwExtensionVersion = MAKELONG( HSE_VERSION_MINOR, HSE_VERSION_MAJOR );
-
- strncpy(pVer->lpszExtensionDesc,
- "OLE Automation Gateway",
- HSE_MAX_EXT_DLL_NAME_LEN);
- return TRUE;
- }
-
- DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pECB)
- {
- CHAR pszPathString[PARAMLEN];
- CHAR *pszProgid = NULL;
- CHAR *pszMethod = NULL;
- CHAR *pszTemp = NULL;
-
- if (FALSE == TlsGetValue(g_dwTLSIndex)) {
- OleInitialize(NULL);
- TlsSetValue(g_dwTLSIndex, (void*)TRUE);
- }
-
- // only GET and POST supported
- if (strcmp(pECB->lpszMethod, "GET") && strcmp(pECB->lpszMethod, "POST"))
- {
- return HSE_STATUS_ERROR;
- }
-
- // extract progid & method name from path info
- strncpy(pszPathString, pECB->lpszPathInfo, PARAMLEN);
- if ('/' == *pszPathString) {
- pszProgid = pszPathString + 1;
- }
- pszMethod = strchr(pszPathString, '.');
- if (NULL != pszMethod) {
- // progids can have zero or one periods in them
- pszTemp = strchr(pszMethod + 1, '.');
- // separate progid from args
- if (NULL != pszTemp) {
- *pszTemp = '\0';
- pszMethod = pszTemp + 1;
- } else {
- *pszMethod = '\0';
- pszMethod++;
- }
- }
-
- // startup object, invoke method, and return results
- if (FALSE == CallObject(pECB, pszProgid, pszMethod)) {
- ErrorResponse(pECB, pszProgid, pszMethod);
- return HSE_STATUS_ERROR;
- }
- return HSE_STATUS_SUCCESS;
- }
-
- BOOL WINAPI DllMain(HMODULE hMod, DWORD fReason, LPVOID pvRes)
- {
- switch (fReason) {
- case DLL_PROCESS_ATTACH:
- g_dwTLSIndex = TlsAlloc();
- InitializeCriticalSection(&g_csRuntime);
- if (-1 == g_dwTLSIndex)
- return FALSE;
- break;
-
- case DLL_THREAD_ATTACH:
- // set this flag to true once ole has been initialized
- TlsSetValue(g_dwTLSIndex, FALSE);
- break;
-
- case DLL_PROCESS_DETACH:
- // clean up global resources
- if (-1 != g_dwTLSIndex)
- TlsFree(g_dwTLSIndex);
- DeleteCriticalSection(&g_csRuntime);
- break;
-
- case DLL_THREAD_DETACH:
- break;
- }
- return TRUE;
- }