home *** CD-ROM | disk | FTP | other *** search
- /*
- * ======================================================================= *
- * File: cgiwrap.c *
- * Demonstrates an executable which can be used to load an ISAPI DLL like *
- * a CGI script. *
- * ======================================================================= *
- */
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #include <httpext.h>
- #include <stdio.h>
- #include <stdlib.h>
-
- // These are things that go out in the Response Header
- //
- #define HTTP_VER "HTTP/1.0"
- #define SERVER_VERSION "Http-Srv-Beta2/1.0"
-
- //
- // Simple wrappers for the heap APIS
- //
- #define xmalloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s))
- #define xfree(s) HeapFree(GetProcessHeap(),0,(s))
-
- //
- // The mandatory exports from the ISAPI DLL
- //
- typedef BOOL (WINAPI *VersionProc)(HSE_VERSION_INFO *) ;
- typedef DWORD ( *HttpExtProc)(EXTENSION_CONTROL_BLOCK *);
-
-
- //
- // Prototypes of the functions this sample implements
- //
- BOOL WINAPI FillExtensionControlBlock(EXTENSION_CONTROL_BLOCK *) ;
- BOOL WINAPI GetServerVariable(HCONN, LPSTR, LPVOID, LPDWORD );
- BOOL WINAPI ReadClient(HCONN,LPVOID,LPDWORD);
- BOOL WINAPI WriteClient(HCONN,LPVOID,LPDWORD,DWORD);
- BOOL WINAPI ServerSupportFunction(HCONN,DWORD,LPVOID,LPDWORD,LPDWORD);
- char * MakeDateStr(VOID);
- char * GetEnv(char *);
-
- /*
- * ======================================================================= *
- * In the startup of this program, we look at our executable name and *
- * replace the ".EXE" with ".DLL" to find the ISAPI DLL we need to load. *
- * This means that the executable need only be given the same "name" as *
- * the DLL to load. There is no recompilation required. *
- * ======================================================================= *
- */
- int _CRTAPI1 main(int argc, char **argv) {
-
- HINSTANCE hDll;
- VersionProc GetExtensionVersion;
- HttpExtProc HttpExtensionProc;
- HSE_VERSION_INFO version_info;
- EXTENSION_CONTROL_BLOCK ECB;
- DWORD rc;
- char szModuleFileName[256],*c;
-
-
- if (!GetModuleFileName(NULL,szModuleFileName,256)){
- fprintf(stderr,"cannot get ModuleFileName %d\n",GetLastError());
- return -1;
- }
- rc = strlen(szModuleFileName);
- c = szModuleFileName + rc -4; // Go back to the last "."
- c[1] = 'D';
- c[2] = 'L';
- c[3] = 'L';
-
- hDll = LoadLibrary(szModuleFileName); // Load our DLL
-
- if(!hDll) {
- fprintf(stderr,"Error: Dll %s not found %d\n",
- argv[0],GetLastError());
- return -1;
- }
-
- //
- // Find the exported functions
-
- GetExtensionVersion = (VersionProc)GetProcAddress(hDll,"GetExtensionVersion");
- if (!GetExtensionVersion) {
- fprintf(stderr,"Can't Get Extension Version %d\n",GetLastError());
- return -1;
- }
- HttpExtensionProc = (HttpExtProc)GetProcAddress(hDll,"HttpExtensionProc");
- if (!HttpExtensionProc) {
- fprintf(stderr,"Can't Get Extension proc %d\n",GetLastError());
- return -1;
- }
-
- // This should really check if the version information matches what we
- // expect.
- //
- __try {
- if (!GetExtensionVersion(&version_info) ) {
- fprintf(stderr,"Fatal: GetExtensionVersion failed\n");
- return -1;
- }
- }
- __except(1) {
- return -1;
- }
-
- //
- // Fill the ECB with the necessary information
- //
- if(!FillExtensionControlBlock(&ECB) ) {
- fprintf(stderr,"Fill Ext Block Failed\n");
- return -1;
- }
-
- // Call the DLL
- //
- __try {
- rc = HttpExtensionProc(&ECB);
- }
- __except(1) {
- return -1;
- }
-
-
- // We should really free memory (e.g., from GetEnv), but we'll be dead
- // soon enough
-
-
- if (rc == HSE_STATUS_PENDING) // We will exit in ServerSupportFunction
- Sleep(INFINITE);
-
- return 0;
-
- }
- //
- // GetServerVariable() is how the DLL calls the main program to figure out
- // the environment variables it needs. This is a required function.
- //
- BOOL WINAPI GetServerVariable(HCONN hConn, LPSTR lpszVariableName,
- LPVOID lpBuffer, LPDWORD lpdwSize){
-
- DWORD rc;
- //
- // We don't really have an HCONN, so we assume a value of 0 (which is passed
- // to the DLL in the ECB by HttpExtensionProc().
- // Hence the check for a non-zero HCONN
-
- if (hConn){
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- rc = GetEnvironmentVariable(lpszVariableName,lpBuffer,*lpdwSize) ;
-
- if (!rc) { // return of 0 indicates the variable was not found
- SetLastError(ERROR_NO_DATA);
- return FALSE;
- }
-
- if (rc > *lpdwSize) {
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
-
- *lpdwSize =rc + 1 ; // GetEnvironmentVariable does not count the NULL
-
- return TRUE;
-
- }
- //
- // Again, we don't have an HCONN, so we simply wrap ReadClient() to
- // ReadFile on stdin. The semantics of the two functions are the same
- //
- BOOL WINAPI ReadClient(HCONN hConn, LPVOID lpBuffer, LPDWORD lpdwSize) {
-
- return ReadFile(GetStdHandle(STD_INPUT_HANDLE),lpBuffer,(*lpdwSize),
- lpdwSize,NULL);
-
- }
- //
- // ditto for WriteClient()
- //
- BOOL WINAPI WriteClient(HCONN hConn, LPVOID lpBuffer, LPDWORD lpdwSize,
- DWORD dwReserved) {
-
- return WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),lpBuffer,*lpdwSize,
- lpdwSize,NULL);
-
- }
- //
- // This is a special callback function used by the DLL for certain extra
- // functionality. Look at the API help for details.
- //
- BOOL WINAPI ServerSupportFunction(HCONN hConn, DWORD dwHSERequest,
- LPVOID lpvBuffer, LPDWORD lpdwSize, LPDWORD lpdwDataType){
-
- char *lpszRespBuf;
- char * temp;
- DWORD dwBytes;
- BOOL bRet;
-
- switch(dwHSERequest) {
- case (HSE_REQ_SEND_RESPONSE_HEADER) :
- lpszRespBuf = xmalloc(*lpdwSize+ 80);//accomodate our header
- if (!lpszRespBuf)
- return FALSE;
- wsprintf(lpszRespBuf,"%s %s %s %s\r\n%s",HTTP_VER,
-
- /* Default response is 200 Ok */
-
- lpvBuffer?lpvBuffer:"200 Ok",
-
- /* Create a string for the time. */
- temp=MakeDateStr(),
-
- SERVER_VERSION,
-
- /* If this exists, it is a pointer to a data buffer to
- be sent. */
- lpdwDataType?(char *)lpdwDataType:NULL);
-
- xfree(temp);
-
- dwBytes = strlen(lpszRespBuf);
- bRet = WriteClient(0,lpszRespBuf,&dwBytes,0);
- xfree(lpszRespBuf);
-
- break;
- //
- // A real server would do cleanup here
- case (HSE_REQ_DONE_WITH_SESSION):
- ExitProcess(0);
- break;
-
- //
- // This sends a redirect (temporary) to the client.
- // The header construction is similar to RESPONSE_HEADER above.
- //
- case (HSE_REQ_SEND_URL_REDIRECT_RESP):
- lpszRespBuf = xmalloc(*lpdwSize +80) ;
- if (!lpszRespBuf)
- return FALSE;
- wsprintf(lpszRespBuf,"%s %s %s\r\n",
- HTTP_VER,
- "302 Moved Temporarily",
- (lpdwSize > 0)?lpvBuffer:0);
- xfree(temp);
- dwBytes = strlen(lpszRespBuf);
- bRet = WriteClient(0,lpszRespBuf,&dwBytes,0);
- xfree(lpszRespBuf);
- break;
- default:
- return FALSE;
- break;
- }
- return bRet;
-
- }
- //
- // Makes a string of the date and time from GetSystemTime().
- // This is in UTC, as required by the HTTP spec.`
- //
- char * MakeDateStr(void){
- SYSTEMTIME systime;
- char *szDate= xmalloc(64);
-
- char * DaysofWeek[] = {"Sun","Mon","Tue","Wed","Thurs","Fri","Sat"};
- char * Months[] = {"NULL","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug",
- "Sep","Oct","Nov","Dec"};
-
- GetSystemTime(&systime);
-
- wsprintf(szDate,"%s, %d %s %d %d:%d.%d",DaysofWeek[systime.wDayOfWeek],
- systime.wDay,
- Months[systime.wMonth],
- systime.wYear,
- systime.wHour,systime.wMinute,
- systime.wSecond );
-
- return szDate;
- }
- //
- // Fill the ECB up
- //
- BOOL WINAPI FillExtensionControlBlock(EXTENSION_CONTROL_BLOCK *ECB) {
-
- char * temp;
- ECB->cbSize = sizeof(EXTENSION_CONTROL_BLOCK);
- ECB->dwVersion = MAKELONG(HSE_VERSION_MINOR,HSE_VERSION_MAJOR);
- ECB->ConnID = 0;
- //
- // Pointers to the functions the DLL will call.
- //
- ECB->GetServerVariable = GetServerVariable;
- ECB->ReadClient = ReadClient;
- ECB->WriteClient = WriteClient;
- ECB->ServerSupportFunction = ServerSupportFunction;
-
- //
- // Fill in the standard CGI environment variables
- //
- ECB->lpszMethod = GetEnv("REQUEST_METHOD");
- ECB->lpszQueryString = GetEnv("QUERY_STRING");
- ECB->lpszPathInfo = GetEnv("PATH_INFO");
- ECB->lpszPathTranslated = GetEnv("PATH_TRANSLATED");
- ECB->cbTotalBytes=( (temp=GetEnv("CONTENT_LENGTH")) ? (atoi(temp)): 0);
- ECB->cbAvailable = 0;
- ECB->lpbData = "";
- ECB->lpszContentType = GetEnv("CONTENT_TYPE");
- return TRUE;
-
- }
-
- //
- // Works like _getenv(), but uses win32 functions instead.
- //
- char * GetEnv(LPSTR lpszEnvVar) {
-
- char *var,dummy;
- DWORD dwLen;
-
- if (!lpszEnvVar)
- return "";
-
- dwLen =GetEnvironmentVariable(lpszEnvVar,&dummy,1);
-
- if (dwLen == 0)
- return "";
-
- var = xmalloc(dwLen);
- if (!var)
- return "";
- (void)GetEnvironmentVariable(lpszEnvVar,var,dwLen);
-
- return var;
- }
-