home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / software / pelne / optionp / iis4_07.cab / fwrite.c < prev    next >
Text File  |  1997-10-25  |  7KB  |  342 lines

  1. /*++
  2.  
  3. Copyright (c) 1995-1997  Microsoft Corporation
  4.  
  5. Module Name:
  6.  
  7.     fwrite.c
  8.  
  9. Abstract:
  10.  
  11.     This module demonstrates a simple file transfer using ISAPI application
  12.       using the WriteClient() callback.
  13.  
  14. Revision History:
  15. --*/
  16.  
  17. # define WIN32_LEAN_AND_MEAN
  18. # include <windows.h>
  19. # include <stdio.h>
  20. # include "httpext.h"
  21. # include "openf.h"
  22.  
  23. DWORD
  24. SendHeaderToClient( IN EXTENSION_CONTROL_BLOCK  * pecb, IN LPCSTR pszErrorMsg);
  25.  
  26.  
  27. DWORD
  28. SendFileToClient( IN EXTENSION_CONTROL_BLOCK  * pecb, IN LPCSTR pszFile);
  29.  
  30. DWORD
  31. SendFileOver( IN EXTENSION_CONTROL_BLOCK  * pecb, IN HANDLE hFile);
  32.  
  33.  
  34.  
  35.  
  36. BOOL WINAPI
  37. DllMain(
  38.      IN HINSTANCE hinstDll,
  39.      IN DWORD     fdwReason,
  40.      IN LPVOID    lpvContext OPTIONAL)
  41. /*++
  42.  
  43.  Routine Description:
  44.  
  45.    This function DllLibMain() is the main initialization function for
  46.     this DLL. It initializes local variables and prepares it to be invoked
  47.     subsequently.
  48.  
  49.  Arguments:
  50.  
  51.    hinstDll          Instance Handle of the DLL
  52.    fdwReason         Reason why NT called this DLL
  53.    lpvReserved       Reserved parameter for future use.
  54.  
  55.  Return Value:
  56.  
  57.     Returns TRUE is successful; otherwise FALSE is returned.
  58.  
  59. --*/
  60. {
  61.   BOOL    fReturn = TRUE;
  62.  
  63.   switch (fdwReason ) {
  64.  
  65.     case DLL_PROCESS_ATTACH:
  66.       {
  67.           OutputDebugString( " Initializing the global data in fwrite.dll\n");
  68.  
  69.           //
  70.           // Initialize various data and modules.
  71.           //
  72.           fReturn = (InitFileHandleCache() == NO_ERROR);
  73.  
  74.           break;
  75.       } /* case DLL_PROCESS_ATTACH */
  76.  
  77.     case DLL_PROCESS_DETACH:
  78.       {
  79.  
  80.           //
  81.           // Only cleanup when we are called because of a FreeLibrary().
  82.           //  i.e., when lpvContext == NULL
  83.           // If we are called because of a process termination,
  84.           //  dont free anything. System will free resources and memory for us.
  85.           //
  86.  
  87.           CleanupFileHandleCache();
  88.  
  89.           break;
  90.       } /* case DLL_PROCESS_DETACH */
  91.  
  92.     default:
  93.       break;
  94.   }   /* switch */
  95.  
  96.   return ( fReturn);
  97. }  /* DllLibMain() */
  98.  
  99.  
  100.  
  101.  
  102. DWORD WINAPI
  103. HttpExtensionProc(
  104.     IN EXTENSION_CONTROL_BLOCK * pecb
  105. )
  106. {
  107.     DWORD hseStatus;
  108.  
  109.  
  110.     if ( pecb->lpszQueryString == NULL) {
  111.  
  112.         hseStatus = SendHeaderToClient( pecb, "File Not Found");
  113.     } else {
  114.  
  115.         hseStatus = SendFileToClient( pecb, pecb->lpszQueryString);
  116.     }
  117.  
  118.     return ( hseStatus);
  119.  
  120. } // HttpExtensionProc()
  121.  
  122.  
  123.  
  124.  
  125.  
  126. BOOL WINAPI
  127. GetExtensionVersion(
  128.     HSE_VERSION_INFO * pver
  129.     )
  130. {
  131.     pver->dwExtensionVersion = MAKELONG( 1, 0 );
  132.     strcpy( pver->lpszExtensionDesc,
  133.            "File Transfer using WriteClient" );
  134.  
  135.     return TRUE;
  136. }
  137.  
  138.  
  139.  
  140. BOOL WINAPI
  141. TerminateExtension(
  142.                    /*IN */ DWORD dwFlags
  143.     )
  144. /*++
  145.   This function is called when IIS decides to stop and unload the 
  146.   ISAPI DLL. We can do any custom cleanup for the module inside this function
  147. --*/
  148. {
  149.     //
  150.     // Nothing specific do here for cleanup
  151.     // Cleanup is done in the dll process detach in DllLibMain()
  152.     //
  153.  
  154.     return ( TRUE);
  155. }
  156.  
  157.  
  158.  
  159.  
  160. DWORD
  161. SendHeaderToClient( IN EXTENSION_CONTROL_BLOCK  * pecb, IN LPCSTR pszErrorMsg)
  162. {
  163.     HSE_SEND_HEADER_EX_INFO    SendHeaderExInfo;
  164.     char szStatus[]     = "200 OK";
  165.     char szHeader[1024];
  166.  
  167.     //
  168.     //  Note the HTTP header block is terminated by a blank '\r\n' pair,
  169.     //  followed by the document body
  170.     //
  171.  
  172.     wsprintf( szHeader,
  173.               "Content-Type: text/html\r\n"
  174.               "\r\n"              // marks the end of header block
  175.               "<head><title>Simple File Transfer (Synchronous Write)"
  176.               "</title></head>\n"
  177.               "<body><h1>%s</h1>\n"
  178.               ,
  179.               pszErrorMsg );
  180.  
  181.  
  182.     //
  183.     //  Populate SendHeaderExInfo struct
  184.     //
  185.  
  186.     SendHeaderExInfo.pszStatus = szStatus;
  187.     SendHeaderExInfo.pszHeader = szHeader;
  188.     SendHeaderExInfo.cchStatus = lstrlen( szStatus);
  189.     SendHeaderExInfo.cchHeader = lstrlen( szHeader);
  190.     SendHeaderExInfo.fKeepConn = FALSE;
  191.  
  192.     //
  193.     //  Send header - use the EX Version to send the header blob
  194.     //
  195.  
  196.     if ( !pecb->ServerSupportFunction(
  197.                 pecb->ConnID
  198.                 , HSE_REQ_SEND_RESPONSE_HEADER_EX
  199.                 , &SendHeaderExInfo
  200.                 , NULL
  201.                 , NULL
  202.             ) ) {
  203.  
  204.         return HSE_STATUS_ERROR;
  205.     }
  206.  
  207.     return ( HSE_STATUS_SUCCESS);
  208. } // SendHeaderToClient()
  209.  
  210.  
  211.  
  212. DWORD
  213. SendFileToClient( IN EXTENSION_CONTROL_BLOCK  * pecb, IN LPCSTR pszFile)
  214. {
  215.     CHAR    pchBuffer[1024];
  216.     HANDLE  hFile;
  217.     DWORD   hseStatus = HSE_STATUS_SUCCESS;
  218.  
  219.     hFile = FcOpenFile( pecb, pszFile);
  220.  
  221.     if ( hFile == INVALID_HANDLE_VALUE) {
  222.  
  223.  
  224.         wsprintfA( pchBuffer,
  225.                   "OpenFailed: Error (%d) while opening the file %s.\n",
  226.                   GetLastError(), pszFile);
  227.  
  228.         hseStatus = SendHeaderToClient( pecb, pchBuffer);
  229.  
  230.     } else {
  231.  
  232.         wsprintfA( pchBuffer, " Transferred file contains...");
  233.  
  234.         hseStatus = SendHeaderToClient( pecb, pchBuffer);
  235.  
  236.         if ( hseStatus == HSE_STATUS_SUCCESS) {
  237.  
  238.             hseStatus = SendFileOver( pecb, hFile);
  239.  
  240.             if ( hseStatus != HSE_STATUS_PENDING) {
  241.  
  242.                 if ( hseStatus != HSE_STATUS_SUCCESS) {
  243.  
  244.                     //
  245.                     // Error in transmitting the file. Send error message.
  246.                     //
  247.  
  248.                     wsprintfA( pchBuffer,
  249.                               "Send Failed: Error (%d) for file %s.\n",
  250.                               GetLastError(), pszFile);
  251.  
  252.                     SendHeaderToClient( pecb, pchBuffer);
  253.                 }
  254.             }
  255.  
  256.             if ( hseStatus != HSE_STATUS_PENDING) {
  257.  
  258.                 //
  259.                 // assume that the data is transmitted.
  260.                 //
  261.  
  262.                 // close file handle
  263.                 FcCloseFile( hFile);
  264.             }
  265.         }
  266.     }
  267.  
  268.     return (hseStatus);
  269.  
  270. } // SendFileToClient()
  271.  
  272.  
  273.  
  274.  
  275. # define MAX_BUFFER_SIZE  (4096)
  276.  
  277. DWORD
  278. SendFileOver( IN EXTENSION_CONTROL_BLOCK  * pecb, IN HANDLE hFile)
  279. {
  280.     CHAR  pchBuffer[MAX_BUFFER_SIZE];
  281.     DWORD dwBytesInFile = GetFileSize(hFile, NULL);
  282.     DWORD nRead = 0;
  283.     DWORD hseStatus = HSE_STATUS_SUCCESS;
  284.     OVERLAPPED  ov;
  285.     DWORD err;
  286.  
  287.     //
  288.     // Send the whole file.
  289.     // Loop thru reading the file and transmitting it to client
  290.     //
  291.  
  292.  
  293.     memset(&ov, 0, sizeof(OVERLAPPED));
  294.  
  295.     ov.OffsetHigh = 0;
  296.     ov.Offset = 0;
  297.     ov.hEvent = CreateEvent(NULL, TRUE, FALSE, "OVERLAPPED::hEvent");
  298.  
  299.     if ( ov.hEvent == NULL) {
  300.  
  301.         return (HSE_STATUS_ERROR);
  302.     }
  303.  
  304.     do {
  305.  
  306.         nRead = 0;
  307.  
  308.         // read data from the file
  309.         if (!FcReadFromFile( hFile, pchBuffer, MAX_BUFFER_SIZE, &nRead,
  310.                            &ov)
  311.             ) {
  312.  
  313.             hseStatus = HSE_STATUS_ERROR;
  314.             break;
  315.         }
  316.  
  317.         // write data to client
  318.  
  319.         if ( !pecb->WriteClient( pecb->ConnID,
  320.                                  pchBuffer, &nRead,
  321.                                 0)
  322.             ) {
  323.  
  324.             hseStatus = HSE_STATUS_ERROR;
  325.             break;
  326.         }
  327.  
  328.     } while (TRUE);
  329.  
  330.  
  331.     if ( ov.hEvent != NULL) {
  332.  
  333.         err = GetLastError();
  334.         CloseHandle( ov.hEvent);
  335.         ov.hEvent = NULL;
  336.         SetLastError( err);
  337.     }
  338.  
  339.     return (hseStatus);
  340.  
  341. } // SendFileOver()
  342.