home *** CD-ROM | disk | FTP | other *** search
/ Tutto per Internet / Internet.iso / soft95 / Varie / server / cgiwrap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-03  |  8.7 KB  |  337 lines

  1. /*
  2.  * ======================================================================= *
  3.  * File: cgiwrap.c                                                         *
  4.  * Demonstrates an executable which can be used to load an ISAPI DLL like  *
  5.  * a CGI script.                                                           *
  6.  * ======================================================================= *
  7. */
  8. #define WIN32_LEAN_AND_MEAN
  9. #include <windows.h>
  10. #include <httpext.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13.  
  14. // These are things that go out in the Response Header
  15. //
  16. #define HTTP_VER     "HTTP/1.0"
  17. #define SERVER_VERSION "Http-Srv-Beta2/1.0"
  18.  
  19. //
  20. // Simple wrappers for the heap APIS
  21. //
  22. #define xmalloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s))
  23. #define xfree(s)   HeapFree(GetProcessHeap(),0,(s))
  24.  
  25. //
  26. // The mandatory exports from the ISAPI DLL
  27. //
  28. typedef BOOL (WINAPI *VersionProc)(HSE_VERSION_INFO *) ;
  29. typedef DWORD ( *HttpExtProc)(EXTENSION_CONTROL_BLOCK *);
  30.  
  31.  
  32. //
  33. // Prototypes of the functions this sample implements
  34. //
  35. BOOL WINAPI FillExtensionControlBlock(EXTENSION_CONTROL_BLOCK *) ;
  36. BOOL WINAPI GetServerVariable(HCONN, LPSTR, LPVOID, LPDWORD );
  37. BOOL WINAPI ReadClient(HCONN,LPVOID,LPDWORD);
  38. BOOL WINAPI WriteClient(HCONN,LPVOID,LPDWORD,DWORD);
  39. BOOL WINAPI ServerSupportFunction(HCONN,DWORD,LPVOID,LPDWORD,LPDWORD);
  40. char * MakeDateStr(VOID);
  41. char * GetEnv(char *);
  42.  
  43. /*
  44.  * ======================================================================= *
  45.  * In the startup of this program, we look at our executable name and      *
  46.  * replace the ".EXE" with ".DLL" to find the ISAPI DLL we need to load.   *
  47.  * This means that the executable need only be given the same "name" as    *
  48.  * the DLL to load. There is no recompilation required.                    *
  49.  * ======================================================================= *
  50. */
  51. int _CRTAPI1 main(int argc, char **argv) {
  52.  
  53.     HINSTANCE hDll;
  54.     VersionProc GetExtensionVersion;
  55.     HttpExtProc HttpExtensionProc;
  56.     HSE_VERSION_INFO version_info;
  57.     EXTENSION_CONTROL_BLOCK ECB;
  58.     DWORD rc;
  59.     char szModuleFileName[256],*c;
  60.  
  61.  
  62.     if (!GetModuleFileName(NULL,szModuleFileName,256)){
  63.         fprintf(stderr,"cannot get ModuleFileName %d\n",GetLastError());
  64.         return -1;
  65.     }
  66.     rc = strlen(szModuleFileName);
  67.     c = szModuleFileName + rc -4; // Go back to the last "."
  68.     c[1] = 'D';
  69.     c[2] = 'L';
  70.     c[3] = 'L';
  71.  
  72.     hDll = LoadLibrary(szModuleFileName); // Load our DLL
  73.  
  74.     if(!hDll) {
  75.         fprintf(stderr,"Error: Dll %s not found %d\n",
  76.                 argv[0],GetLastError());
  77.         return -1;
  78.     }
  79.  
  80.     //
  81.     // Find the exported functions
  82.  
  83.     GetExtensionVersion = (VersionProc)GetProcAddress(hDll,"GetExtensionVersion");
  84.     if (!GetExtensionVersion) {
  85.         fprintf(stderr,"Can't Get Extension Version %d\n",GetLastError());
  86.         return -1;
  87.     }
  88.     HttpExtensionProc = (HttpExtProc)GetProcAddress(hDll,"HttpExtensionProc");
  89.     if (!HttpExtensionProc) {
  90.         fprintf(stderr,"Can't Get Extension proc %d\n",GetLastError());
  91.         return -1;
  92.     }
  93.  
  94.     // This should really check if the version information matches what we
  95.     // expect.
  96.     //
  97.     __try {
  98.         if (!GetExtensionVersion(&version_info) ) {
  99.             fprintf(stderr,"Fatal: GetExtensionVersion failed\n");
  100.             return -1;
  101.         }
  102.     }
  103.     __except(1) {
  104.         return -1;
  105.     }
  106.  
  107.     //
  108.     // Fill the ECB with the necessary information
  109.     //
  110.     if(!FillExtensionControlBlock(&ECB) ) {
  111.         fprintf(stderr,"Fill Ext Block Failed\n");
  112.         return -1;
  113.     }
  114.  
  115.     // Call the DLL
  116.     //
  117.     __try {
  118.         rc = HttpExtensionProc(&ECB);
  119.     }
  120.     __except(1) {
  121.         return -1;
  122.     }
  123.  
  124.  
  125.     // We should really free memory (e.g., from GetEnv), but we'll be dead
  126.     // soon enough
  127.  
  128.  
  129.     if (rc == HSE_STATUS_PENDING) // We will exit in ServerSupportFunction
  130.         Sleep(INFINITE);
  131.  
  132.     return 0;
  133.         
  134. }
  135. //
  136. // GetServerVariable() is how the DLL calls the main program to figure out
  137. // the environment variables it needs. This is a required function.
  138. //
  139. BOOL WINAPI GetServerVariable(HCONN hConn, LPSTR lpszVariableName,
  140.                                 LPVOID lpBuffer, LPDWORD lpdwSize){
  141.  
  142.     DWORD rc;
  143. //
  144. // We don't really have an HCONN, so we assume a value of 0 (which is passed
  145. // to the DLL in the ECB by HttpExtensionProc().
  146. // Hence the check for a non-zero HCONN
  147.  
  148.     if (hConn){
  149.         SetLastError(ERROR_INVALID_PARAMETER);
  150.         return FALSE;
  151.     }
  152.         
  153.     rc = GetEnvironmentVariable(lpszVariableName,lpBuffer,*lpdwSize) ;
  154.  
  155.     if (!rc) { // return of 0 indicates the variable was not found
  156.         SetLastError(ERROR_NO_DATA);
  157.         return FALSE;
  158.     }
  159.  
  160.     if (rc > *lpdwSize) {
  161.         SetLastError(ERROR_INSUFFICIENT_BUFFER);
  162.         return FALSE;
  163.     }
  164.  
  165.     *lpdwSize =rc + 1 ; // GetEnvironmentVariable does not count the NULL
  166.  
  167.     return TRUE;
  168.  
  169. }
  170. //
  171. // Again, we don't have an HCONN, so we simply wrap ReadClient() to
  172. // ReadFile on stdin. The semantics of the two functions are the same
  173. //
  174. BOOL WINAPI ReadClient(HCONN hConn, LPVOID lpBuffer, LPDWORD lpdwSize) {
  175.  
  176.     return ReadFile(GetStdHandle(STD_INPUT_HANDLE),lpBuffer,(*lpdwSize),
  177.                   lpdwSize,NULL);
  178.  
  179. }
  180. //
  181. // ditto for WriteClient()
  182. //
  183. BOOL WINAPI WriteClient(HCONN hConn, LPVOID lpBuffer, LPDWORD lpdwSize,
  184.             DWORD dwReserved) {
  185.  
  186.     return WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),lpBuffer,*lpdwSize,
  187.                     lpdwSize,NULL);
  188.  
  189. }
  190. //
  191. // This is a special callback function used by the DLL for certain extra 
  192. // functionality. Look at the API help for details.
  193. //
  194. BOOL WINAPI ServerSupportFunction(HCONN hConn, DWORD dwHSERequest,
  195.                 LPVOID lpvBuffer, LPDWORD lpdwSize, LPDWORD lpdwDataType){
  196.  
  197.     char *lpszRespBuf;
  198.     char * temp;
  199.     DWORD dwBytes;
  200.     BOOL bRet;
  201.  
  202.     switch(dwHSERequest) {
  203.         case (HSE_REQ_SEND_RESPONSE_HEADER) :
  204.             lpszRespBuf = xmalloc(*lpdwSize+ 80);//accomodate our header
  205.             if (!lpszRespBuf)
  206.                 return FALSE;
  207.             wsprintf(lpszRespBuf,"%s %s %s %s\r\n%s",HTTP_VER,
  208.                 
  209.                 /* Default response is 200 Ok */
  210.  
  211.                 lpvBuffer?lpvBuffer:"200 Ok",
  212.                 
  213.                 /* Create a string for the time. */
  214.                 temp=MakeDateStr(),
  215.  
  216.                 SERVER_VERSION,
  217.                 
  218.                 /* If this exists, it is a pointer to a data buffer to
  219.                    be sent. */
  220.                 lpdwDataType?(char *)lpdwDataType:NULL);
  221.  
  222.             xfree(temp);
  223.  
  224.             dwBytes = strlen(lpszRespBuf);
  225.             bRet = WriteClient(0,lpszRespBuf,&dwBytes,0);
  226.             xfree(lpszRespBuf);
  227.  
  228.             break;
  229.             //
  230.             // A real server would do cleanup here
  231.         case (HSE_REQ_DONE_WITH_SESSION):
  232.             ExitProcess(0);
  233.             break;
  234.         
  235.         //
  236.         // This sends a redirect (temporary) to the client.
  237.         // The header construction is similar to RESPONSE_HEADER above.
  238.         //
  239.         case (HSE_REQ_SEND_URL_REDIRECT_RESP):
  240.             lpszRespBuf = xmalloc(*lpdwSize +80) ;
  241.             if (!lpszRespBuf)
  242.                 return FALSE;
  243.             wsprintf(lpszRespBuf,"%s %s %s\r\n",
  244.                     HTTP_VER,
  245.                     "302 Moved Temporarily",
  246.                     (lpdwSize > 0)?lpvBuffer:0);
  247.             xfree(temp);
  248.             dwBytes = strlen(lpszRespBuf);
  249.             bRet = WriteClient(0,lpszRespBuf,&dwBytes,0);
  250.             xfree(lpszRespBuf);
  251.             break;
  252.         default:
  253.             return FALSE;
  254.         break;
  255.     }
  256.     return bRet;
  257.     
  258. }
  259. //
  260. // Makes a string of the date and time from GetSystemTime().
  261. // This is in UTC, as required by the HTTP spec.`
  262. //
  263. char * MakeDateStr(void){
  264.     SYSTEMTIME systime;
  265.     char *szDate= xmalloc(64);
  266.  
  267.     char * DaysofWeek[] = {"Sun","Mon","Tue","Wed","Thurs","Fri","Sat"};
  268.     char * Months[] = {"NULL","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug",
  269.                         "Sep","Oct","Nov","Dec"};
  270.  
  271.     GetSystemTime(&systime);
  272.  
  273.     wsprintf(szDate,"%s, %d %s %d %d:%d.%d",DaysofWeek[systime.wDayOfWeek],
  274.                                       systime.wDay,
  275.                                       Months[systime.wMonth],
  276.                                       systime.wYear,
  277.                                       systime.wHour,systime.wMinute,
  278.                                       systime.wSecond );
  279.  
  280.     return szDate;
  281. }
  282. //
  283. // Fill the ECB up 
  284. //
  285. BOOL WINAPI FillExtensionControlBlock(EXTENSION_CONTROL_BLOCK *ECB) {
  286.  
  287.     char * temp;
  288.     ECB->cbSize = sizeof(EXTENSION_CONTROL_BLOCK);
  289.     ECB->dwVersion = MAKELONG(HSE_VERSION_MINOR,HSE_VERSION_MAJOR);
  290.     ECB->ConnID = 0;
  291.     //
  292.     // Pointers to the functions the DLL will call.
  293.     //
  294.     ECB->GetServerVariable = GetServerVariable;
  295.     ECB->ReadClient  = ReadClient;
  296.     ECB->WriteClient = WriteClient;
  297.     ECB->ServerSupportFunction = ServerSupportFunction;
  298.  
  299.     //
  300.     // Fill in the standard CGI environment variables
  301.     //
  302.     ECB->lpszMethod = GetEnv("REQUEST_METHOD");
  303.     ECB->lpszQueryString = GetEnv("QUERY_STRING");
  304.     ECB->lpszPathInfo = GetEnv("PATH_INFO");
  305.     ECB->lpszPathTranslated = GetEnv("PATH_TRANSLATED");
  306.     ECB->cbTotalBytes=( (temp=GetEnv("CONTENT_LENGTH")) ? (atoi(temp)): 0);
  307.     ECB->cbAvailable = 0;
  308.     ECB->lpbData = "";
  309.     ECB->lpszContentType = GetEnv("CONTENT_TYPE");
  310.     return TRUE;
  311.  
  312. }
  313.  
  314. //
  315. // Works like _getenv(), but uses win32 functions instead.
  316. //
  317. char * GetEnv(LPSTR lpszEnvVar) {
  318.     
  319.     char *var,dummy;
  320.     DWORD dwLen;
  321.  
  322.     if (!lpszEnvVar)
  323.         return "";
  324.     
  325.     dwLen =GetEnvironmentVariable(lpszEnvVar,&dummy,1);
  326.  
  327.     if (dwLen == 0)
  328.         return "";
  329.     
  330.     var = xmalloc(dwLen);
  331.     if (!var)
  332.         return "";
  333.     (void)GetEnvironmentVariable(lpszEnvVar,var,dwLen);
  334.  
  335.     return var;
  336. }
  337.