home *** CD-ROM | disk | FTP | other *** search
- /*
-
- FOXISAPI.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:
-
-
- 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)
-
- Debug instructions:
- Start IIS, find the process ID of INETINFO, start MSDEV -p pid
- use a browser (from another machine perhaps) and hit the page
- Use IIS to stop/restart WWW services
-
- From MSDevStudio Technote 63:
-
- If you have written an Internet Server Extension DLL, you might be interested in getting it
- running under the debugger so you can trace its execution, set breakpoints, or monitor variable
- values after the extension is called. Getting the Microsoft Internet Information Server up and
- running with your DLL in the debugger is possible, but a little tricky.
- You will need to first find a quiet server where you can debug your DLL in a controlled
- setting. Once you've found such a resource, you can start debugging your DLL by following
- these steps:
- 1. Stop the Internet Information Server publishing services by using the Internet
- Information Server Manager, or by stopping the services with the Services icon
- in the Windows NT Advanced Server Control Panel. Note that you must stop all
- three services even though you are only debugging extensions to the World-Wide
- Web publishing service. To make things easier, you might wish to make the services
- "Manually" started in Control Panel so you can avoid this step later in your
- development.
- 2. Start Microsoft Developer Studio, and click the Close Workspace command on the File
- menu to close any opened workspace.
- 3. On the File menu, click Open Workspace to open the INETINFO.EXE program. This file is
- in the directory where you installed the Microsoft Internet Information Server.
- 4. On the Build menu, click Settings, then click the Debug tab in the Project Settings
- dialog box.
- 5. With General selected in the Category box, type the following in the Program Arguments
- text box:
-
- -e W3Svc
-
- 6. Choose Additional DLLs from the Category drop-down list. Then, in the Local Names box,
- specify the complete path and name of your extension DLL or DLLs. Make sure the check
- box next to each is marked.
- 7. Click OK to close the Project Settings dialog box.
- 8. Make sure that the .PDB file for your DLL is in the same directory as the DLLs you plan
- to debug.
-
- Debugging Tips
- The Internet server can be run as an interactive application. This makes debugging it much
- easier. To do this you need to make a few changes to your system. For the user account that
- you are going to run the server under, you need to add a few privileges.
- To add privileges, run User Manager (MUSRMGR.EXE), and select User Rights from the Policies
- menu. Check the Show Advanced User Rights check box. Then select "Act as part of the
- operating system" from the Right drop-down list, and add the user account.
- Repeat this process with "Generate Security Audits" (also in the Rights drop-down list).
- Make sure that all Internet Services (WWW, ftp & gopher) are stopped and INetInfo.Exe is
- not running (use TLIST to check). Log off and log back on. You can then load the Internet
- Server with the command line:
-
- INetInfo.Exe -e W3Svc
-
-
- If you want to load this under a debugger just make sure that the command line to
- INetInfo.Exe is "-e W3Svc". (For example, to load it into WinDbg the command line is:
- WinDbg INetInfo.Exe -e W3Svc
- You are ready to go. In Developer Studio, point to Debug on the Build menu and then choose
- Go. This action starts the WWW publishing service, and the debugger will be aware of
- symbols in your DLL. You'll get a warning that this file doesn't have debugging
- information in it, but you can ignore that message.
- When you leave Microsoft Developer Studio, you will probably want to make sure that you
- let Developer Studio save the workspace for INETINFO.EXE. This will let you avoid
- reentering all of the settings you need to make instead, you can just open the
- INETINFO.MDS workspace file when you are ready to start the debugger again.
-
- Cached DLLs
- You can adjust the registry setting at
- HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/W3SVC/Parameters/CacheExtensions
- to have the server reinitialize DLLs each time they are used. If this setting is 1,
- the server will keep DLLs loaded in memory as long as possible. This is the default
- setting for the server, since it helps the server achieve peak performance, and should
- only be changed if you are using the server for debugging. If you make the setting zero,
- the server will always reload extension DLLs each time they are used.
- Forcing the server to reload your DLL is very helpful when your DLL might be crashing or
- upsetting any per-instance data that it maintains. By forcing the server to reinitialize
- the DLL, you can get your DLL back into a predictable state with very little effort.
- You should make sure you test your DLL using the normal CacheExtensions setting, however,
- to make sure code in your DLL isn't completely dependent on that initial state.
-
-
- You can start and stop a service from the dos command prompt:
- net start <service name>
- or
- net start "world wide web publishing service"
-
-
-
-
- */
-
- #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;
-
- //the full path dir of this dll
- static char gszAppDir[MAX_PATH];
-
- static char szErrorMessage[MAX_PATH];
-
- // 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, CHAR * lpszIniFile)
- {
- BOOL fSuccess = FALSE;
- BOOL fInCritSec = FALSE;
- HRESULT hr;
- CLSID clsid;
- IDispatch *pdispObj = NULL;
- IUnknown *punkObj = NULL;
- OLECHAR wzMethod[PARAMLEN];
- OLECHAR wzParams[PARAMLEN];
- OLECHAR wzIniFile[MAX_PATH * 2];
- BSTR bstrParams = NULL;
- BSTR bstrIniFile = NULL;
- CHAR *pszResults = NULL;
- DWORD buflen = 0;
-
- OLECHAR *pwzName;
- DISPID dispidMethod;
- DISPPARAMS dispparms;
- VARIANTARG varg[3];
- VARIANTARG vResult;
- EXCEPINFO excep;
-
- IDispatch * pdispDoRelease;
-
- // initialize everything up front so cleanup is safe
- *szErrorMessage = '\0';
- memset(&dispparms, 0, sizeof(DISPPARAMS));
- memset(&varg, 0, sizeof(VARIANTARG) * 3);
- memset(&excep, 0, sizeof(EXCEPINFO));
- memset(wzParams, 0, PARAMLEN);
-
- VariantInit(&varg[0]);
- VariantInit(&varg[1]);
- VariantInit(&varg[2]);
- VariantInit(&vResult);
-
- // convert progid to clsid
- hr = GetClsidFromProgIdA(&clsid, pszProgid, lstrlen(pszProgid)+1);
- if (FAILED(hr)) {
- char szSysMsg[100];
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,hr,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),szSysMsg,sizeof(szSysMsg),0);
-
- sprintf(szErrorMessage,"Class id for %s not found. Err code = %08x: %s",
- pszProgid,hr,szSysMsg);
- goto Err;
- }
- // Grab critical section
- EnterCriticalSection(&g_csRuntime);
- fInCritSec = TRUE;
-
- //See if we can get an existing instance
- hr = GetActiveObject(clsid,NULL,&punkObj);
- if (FAILED(hr))
- {
- // instantiate object
- hr = CoCreateInstance(clsid, NULL, CLSCTX_SERVER, IID_IUnknown, (LPVOID *) &punkObj);
- }
- if (FAILED(hr) || punkObj == NULL) {
- char szSysMsg[100];
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,hr,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),szSysMsg,sizeof(szSysMsg),0);
-
- sprintf(szErrorMessage,"CoCreateInstance failed with err code %08x: %s",hr,szSysMsg);
- goto Err;
- }
- hr = punkObj->QueryInterface(IID_IDispatch, (void**)&pdispObj);
- if (FAILED(hr) || pdispObj == NULL) {
- char szSysMsg[100];
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,hr,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),szSysMsg,sizeof(szSysMsg),0);
-
- sprintf(szErrorMessage,"QueryInterface failed with err code %08x: %s",hr,szSysMsg);
- 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) ) {
- sprintf(szErrorMessage,"MultiByteToWideChar failed");
- 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) ) {
- sprintf(szErrorMessage,"MultiByteToWideChar failed");
- 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) ) {
- sprintf(szErrorMessage,"MultiByteToWideChar failed");
- goto Err;
- }
- } else {
- wzParams[0] = (WCHAR)0;
- }
- if (0 == MultiByteToWideChar(CP_ACP, 0, (const char*)lpszIniFile, -1, wzIniFile, sizeof(wzIniFile)) ) {
- sprintf(szErrorMessage,"MultiByteToWideChar failed");
- goto Err;
- }
- bstrParams = SysAllocString(wzParams);
- if (NULL == bstrParams) {
- sprintf(szErrorMessage,"SysAllocString failed");
- goto Err;
- }
- bstrIniFile = SysAllocString(wzIniFile);
- if (NULL == bstrIniFile) {
- sprintf(szErrorMessage,"SysAllocString failed");
- goto Err;
- }
- // Find method name
- pwzName = wzMethod;
- hr = pdispObj->GetIDsOfNames(IID_NULL, &pwzName, 1, LOCALE_USER_DEFAULT, &dispidMethod);
- if (FAILED(hr)) {
- char szSysMsg[100];
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,hr,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),szSysMsg,sizeof(szSysMsg),0);
-
- sprintf(szErrorMessage,"GetIDsOfNames failed with err code %08x: %s",hr,szSysMsg);
- goto Err;
- }
- // Setup parameters
- dispparms.rgvarg = varg;
- dispparms.rgdispidNamedArgs = NULL;
- dispparms.cArgs = 3;
- dispparms.cNamedArgs = 0;
- pdispDoRelease = pdispObj;
-
- // Push in reverse order
- varg[0].vt = VT_I4 | VT_BYREF ;
- varg[0].plVal = (long *)&pdispDoRelease;
- varg[1].vt = VT_BSTR ;
- varg[1].bstrVal = bstrIniFile;
- varg[2].vt = VT_BSTR ;
- varg[2].bstrVal = bstrParams;
-
- // Now make the invocation.
- hr = pdispObj->Invoke(dispidMethod, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD,
- &dispparms, &vResult, &excep, NULL);
- if (FAILED(hr)) {
- char szSysMsg[100];
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,hr,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),szSysMsg,sizeof(szSysMsg),0);
-
- sprintf(szErrorMessage,"Invoke failed with err code %08x: %s",hr,szSysMsg);
- goto Err;
- }
- // Release critical section
- fInCritSec = FALSE;
- LeaveCriticalSection(&g_csRuntime);
-
- // Assemble result
-
- buflen = wcslen((unsigned short *)vResult.pbstrVal);
- if (buflen > 0) {
- pszResults = (CHAR*)malloc(buflen + 1);
- if (0 == WideCharToMultiByte(CP_ACP, 0, (unsigned short *)vResult.pbstrVal, -1, pszResults, buflen + 1, NULL, NULL)) {
- sprintf(szErrorMessage,"WideCharToMultiByte failed");
- goto Err;
- }
- // null terminate string
- *(pszResults + buflen) = 0;
- }
- buflen++;
- if (pECB->WriteClient(pECB->ConnID,(void *)pszResults,&buflen,0) == FALSE) {
- char szSysMsg[100];
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,hr,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),szSysMsg,sizeof(szSysMsg),0);
-
- sprintf(szErrorMessage,"WriteClient failed",szSysMsg);
- goto Err;
- }
-
- fSuccess = TRUE;
- SysFreeString(wzParams);
- SysFreeString(wzIniFile);
- // Always fall through to cleanup
- Err:
- DeleteFile(lpszIniFile); //delete the .INI
- if (fInCritSec) {
- // Release critical section
- LeaveCriticalSection(&g_csRuntime);
- }
- /*
- For each Web site hit, the OLE server gets instantiated. If the Release() call
- below is executed, then the Server gets released after generating
- an HTML page. This means the entire VFP runtime will start up and shut down for
- each web hit.
- If the OLE Custom Server is registered as Multi-Use, and the following Release()
- call is not executed, then the OLE Server will be left in memory with a reference to it,
- but subsequent web hits will use the same instance of the server, making performance
- much better.
- */
-
- if (pdispObj != NULL) {
- if (pdispDoRelease != 0) {
- pdispObj->Release(); //nonzero, so release the current object
- if (pdispObj != pdispDoRelease) {
- __try { //now release the object the OLE object wants to release
- (pdispDoRelease)->Release();
- } __except (EXCEPTION_EXECUTE_HANDLER) {
-
- }
- }
- }
- }
- VariantClear(&varg[0]);
- VariantClear(&varg[1]);
- VariantClear(&varg[2]);
- VariantClear(&vResult);
- 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>"
- "FOXISAPI call failed</h1><p><b>Progid is:</b> %s\n<p><b>Method is:</b> %s\n<p>"
- "<b>Parameters are:</b> %s\n<p><b> parameters are:</b> %.*s\n</b>"
- "<p><b>%s\n</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 : ""),szErrorMessage);
-
- pECB->ServerSupportFunction(pECB->ConnID,
- HSE_REQ_SEND_RESPONSE_HEADER,
- (LPDWORD) "200 Baaaad Request",
- NULL,
- (LPDWORD)pszBuf);
- }
-
- // CREATE_INI_FILE will create a temp INI file and pass it to the Fox automation object as
- // the second parameter. This INI file contains extra info available from the
- // IIS
-
-
- //
- // GetVarAndWriteKey obtains an environment variable and saves it
- // to the specified key in the profile. This function cleans
- // up the Fill code a lot.
- //
-
- void GetVarAndWriteKey (EXTENSION_CONTROL_BLOCK *pECB,char *lpszIniFile,
- LPCTSTR lpszSection,
- LPCTSTR lpszVar, LPCTSTR lpszKey)
- {
- TCHAR szBuffer[MAX_PATH];
- DWORD dwBufferSize;
- BOOL bReturn;
-
- // Call server to get environment variable
- dwBufferSize = MAX_PATH;
- bReturn = pECB->GetServerVariable (pECB->ConnID,
- (LPTSTR) lpszVar,
- szBuffer,
- &dwBufferSize);
-
- if (!bReturn)
- return;
-
- // Write variable to profile if data exists
- if (szBuffer[0]) {
- WritePrivateProfileString (lpszSection,
- lpszKey,
- szBuffer,
- lpszIniFile);
- }
- }
-
-
- int LogExtraInfo(EXTENSION_CONTROL_BLOCK *pECB,char *lpszIniFile) {
- DWORD dwBufferSize;
- BOOL bReturn;
- TCHAR *pChar, *pOpts, *pEnd;
- TCHAR szBuffer[MAX_PATH];
-
-
- //create a temp INI file name
- GetTempFileName(gszAppDir,
- "FOX", //prefix
- 0,
- lpszIniFile);
- DeleteFile(lpszIniFile); //delete the .TMP
- *strrchr(lpszIniFile,'.') = '\0';
- strcat(lpszIniFile,".ini");
-
- WritePrivateProfileString ("FOXISAPI","Request Method", pECB->lpszMethod, lpszIniFile);
- WritePrivateProfileString ("FOXISAPI","Query String", pECB->lpszQueryString, lpszIniFile);
- WritePrivateProfileString ("FOXISAPI","Logical Path", pECB->lpszPathInfo, lpszIniFile);
- WritePrivateProfileString ("FOXISAPI","Physical Path", pECB->lpszPathTranslated, lpszIniFile);
- WritePrivateProfileString ("FOXISAPI","FoxISAPI Version", "FoxISAPI v1.0", lpszIniFile);
- //
- // Get server variables and write the values to the profile
- //
-
- GetVarAndWriteKey (pECB, lpszIniFile, "FOXISAPI",
- TEXT("SERVER_PROTOCOL"), TEXT("Request Protocol"));
-
- GetVarAndWriteKey (pECB, lpszIniFile, "FOXISAPI",
- TEXT("SCRIPT_NAME"), TEXT("Referer"));
-
- GetVarAndWriteKey (pECB, lpszIniFile, "FOXISAPI",
- TEXT("SERVER_SOFTWARE"), TEXT("Server Software"));
-
- GetVarAndWriteKey (pECB, lpszIniFile, "FOXISAPI",
- TEXT("SERVER_NAME"), TEXT("Server Name"));
-
- GetVarAndWriteKey (pECB, lpszIniFile, "FOXISAPI",
- TEXT("SERVER_PORT"), TEXT("Server Port"));
-
- GetVarAndWriteKey (pECB, lpszIniFile, "FOXISAPI",
- TEXT("REMOTE_HOST"), TEXT("Remote Host"));
-
- GetVarAndWriteKey (pECB, lpszIniFile, "FOXISAPI",
- TEXT("REMOTE_ADDR"), TEXT("Remote Address"));
-
- GetVarAndWriteKey (pECB, lpszIniFile, "FOXISAPI",
- TEXT("AUTHTEXTYPE"), TEXT("Authentication Method"));
-
- GetVarAndWriteKey (pECB, lpszIniFile, "FOXISAPI",
- TEXT("REMOTE_USER"), TEXT("Authenticated Username"));
-
-
- // Keys not supported:
- //
- // Executable Path
- // From
- // Server Admin
- // Authentication Realm (goes with Authenticated Username)
-
- // Retrieve ALL_HTTP
-
- dwBufferSize = sizeof (szBuffer);
- bReturn = pECB->GetServerVariable (pECB->ConnID,
- TEXT("ALL_HTTP"),
- szBuffer,
- &dwBufferSize);
-
- if (bReturn) { // expected symbol is found
- //
- // Find lines, split key/data pair and write them to profile
- //
-
- pChar = szBuffer;
- while (*pChar) {
- if (*pChar == TEXT('\r') || *pChar == TEXT ('\n')) {
- pChar++;
- continue;
- }
-
- pOpts = strchr (pChar, TEXT(':')); // look for separator
- if (!pOpts)
- break;
- if (!*pOpts)
- break;
-
- pEnd = pOpts;
- while (*pEnd && *pEnd != TEXT('\r') && *pEnd != TEXT('\n'))
- pEnd++;
-
- *pOpts = 0; // split strings
- *pEnd = 0;
-
- WritePrivateProfileString ("All_HTTP",pChar, pOpts + 1, lpszIniFile);
-
- pChar = pEnd + 1;
- }
- }
-
-
-
- //
- // Accept section provides info about the client's capabilities. We use
- // the header information stored in the HTTP_ACCEPT environment variable.
- //
- // The format of this variable is:
- //
- // type/subtype [;opt. parameters] [, type/subtype [;params]] [, ...]
- //
- // For example:
- // */*; q=0.300, audio/x-aiff, audio/basic, image/jpeg, image/gif, text/plain, text/html
- //
- // The above example becomes:
- //
- // [Accept]
- // */*=q=0.300
- // audio/x-aiff=Yes
- // audio/basic=Yes
- // image/jpeg=Yes
- // image/gif=Yes
- // text/plain=Yes
- // text/html=Yes
- //
-
-
- //
- // Get the inbound accept line
- //
-
- dwBufferSize = MAX_PATH;
- bReturn = pECB->GetServerVariable (pECB->ConnID,
- TEXT("HTTP_ACCEPT"),
- szBuffer,
- &dwBufferSize);
-
-
- if (bReturn) { // expected symbol is found
-
- //
- // Skip leading spaces and grab entire type/subtype[;opts] string
- //
-
- pChar = strtok (szBuffer, TEXT(" ,"));
- while (pChar) {
- pOpts = strchr (pChar, TEXT(';')); // look for opts, if any
-
- WritePrivateProfileString ("Accept",pChar,
- pOpts == NULL ? TEXT("Yes") : pOpts, lpszIniFile);
-
- pChar = strtok (NULL, TEXT(" ,")); // get next type/subtype pair
- }
- }
-
- //
- // The [System] section must be filled out with GMT Offset
- //
- // GMT offset is the number of seconds added to GMT time to reach local
- // time. For example, PST = GMT - 8 hours; GMT offset would equal
- // -28,800. Win32 call GetTimeZoneInformation returns the number of
- // minutes to subtract from GMT (UTC) to get local time.
- //
- // So, GMT Offset = -60*TZI.Bias.
- //
- TIME_ZONE_INFORMATION tzi = {0};
- GetTimeZoneInformation (&tzi);
- wsprintf(szBuffer,"%i", -60 * tzi.Bias);
- WritePrivateProfileString ("SYSTEM","GMT Offset", szBuffer, lpszIniFile);
-
- return 0;
- }
-
-
-
- BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer)
- {
- pVer->dwExtensionVersion = MAKELONG( HSE_VERSION_MINOR, HSE_VERSION_MAJOR );
-
- strncpy(pVer->lpszExtensionDesc,
- "FOX 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;
- char lpszIniFile[MAX_PATH];
- int hr;
-
- #ifdef _DEBUG
- __try { //uncomment the next line for a breakpoint
- // _asm int 3
- }
- __except (UnhandledExceptionFilter(GetExceptionInformation())) {
- int i;
- i=5; //so we can set a breakpoint here
- }
- #endif
- 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;
- }
- if (hr = LogExtraInfo(pECB,lpszIniFile)) //assignment
- return hr;
-
- // 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,lpszIniFile)) {
- 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:
- GetModuleFileName(hMod,gszAppDir,sizeof(gszAppDir));
- *strrchr(gszAppDir,'\\') = '\0';
- 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;
- }