451 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			451 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						||
 | 
						||
   Copyright    (c)    1995-1996    Microsoft Corporation
 | 
						||
 | 
						||
   Module  Name :
 | 
						||
 | 
						||
      openf.c
 | 
						||
 | 
						||
   Abstract:
 | 
						||
 | 
						||
      This module implements a simple open file handle cache
 | 
						||
 | 
						||
   Author:
 | 
						||
 | 
						||
       Murali R. Krishnan    ( MuraliK )     30-Apr-1996 
 | 
						||
 | 
						||
   Environment:
 | 
						||
    
 | 
						||
       User Mode - Win32
 | 
						||
 | 
						||
   Project:
 | 
						||
 | 
						||
       Internet Server DLL
 | 
						||
 | 
						||
   Functions Exported:
 | 
						||
 | 
						||
 | 
						||
 | 
						||
   Note:
 | 
						||
      THIS IS NOT ROBUST for REAL WORLD.
 | 
						||
      I wrote this for testing the ISAPI Async IO processing.
 | 
						||
 | 
						||
--*/
 | 
						||
 | 
						||
 | 
						||
/************************************************************
 | 
						||
 *     Include Headers
 | 
						||
 ************************************************************/
 | 
						||
 | 
						||
# include "openf.h"
 | 
						||
 | 
						||
#define DEFAULT_TRACE_FLAGS     (DEBUG_ERROR)
 | 
						||
 | 
						||
#include "dbgutil.h"
 | 
						||
 | 
						||
#include <initguid.h>
 | 
						||
DEFINE_GUID(IisFtransGuid, 
 | 
						||
0x784d8935, 0xaa8c, 0x11d2, 0x92, 0x5e, 0x00, 0xc0, 0x4f, 0x72, 0xd9, 0x0e);
 | 
						||
 | 
						||
 | 
						||
/************************************************************
 | 
						||
 *     Type definitions and Globals
 | 
						||
 ************************************************************/
 | 
						||
 | 
						||
#ifdef _NO_TRACING_
 | 
						||
DECLARE_DEBUG_VARIABLE();
 | 
						||
#endif
 | 
						||
DECLARE_DEBUG_PRINTS_OBJECT();
 | 
						||
DECLARE_PLATFORM_TYPE();
 | 
						||
 | 
						||
//
 | 
						||
// internal data structure for maintaining the list of open file handles.
 | 
						||
//
 | 
						||
 | 
						||
typedef struct _OPEN_FILE {
 | 
						||
    
 | 
						||
    HANDLE  hFile;
 | 
						||
    struct _OPEN_FILE * pNext;
 | 
						||
    LONG    nHits;
 | 
						||
    LONG    nRefs;
 | 
						||
    CHAR    rgchFile[MAX_PATH+1];
 | 
						||
 | 
						||
} OPEN_FILE, * LPOPEN_FILE;
 | 
						||
 | 
						||
 | 
						||
LPOPEN_FILE g_pOpenFiles = NULL;
 | 
						||
CRITICAL_SECTION g_csOpenFiles;
 | 
						||
 | 
						||
//
 | 
						||
// Set up global variables containing the flags for CreateFile
 | 
						||
//  The flags can be masked for Windows 95 system
 | 
						||
//
 | 
						||
 | 
						||
DWORD  g_dwCreateFileShareMode = 
 | 
						||
         (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE);
 | 
						||
 | 
						||
DWORD  g_dwCreateFileFlags = 
 | 
						||
         (FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_OVERLAPPED);
 | 
						||
 | 
						||
/************************************************************
 | 
						||
 *    Functions 
 | 
						||
 ************************************************************/
 | 
						||
 | 
						||
 | 
						||
DWORD
 | 
						||
InitFileHandleCache(VOID)
 | 
						||
/*++
 | 
						||
 | 
						||
  This function initializes the file handle cache.
 | 
						||
  It should be called at the initialization time.
 | 
						||
 | 
						||
  Arguments:
 | 
						||
    None
 | 
						||
  
 | 
						||
  Returns:
 | 
						||
    Win32 error code. NO_ERROR indicates that the call succeeded.
 | 
						||
--*/
 | 
						||
{
 | 
						||
    
 | 
						||
#ifdef _NO_TRACING_
 | 
						||
    CREATE_DEBUG_PRINT_OBJECT( "TEST_ISAPI-openf");
 | 
						||
#else
 | 
						||
    CREATE_DEBUG_PRINT_OBJECT( "TEST_ISAPI-openf", IisFtransGuid);
 | 
						||
#endif
 | 
						||
    if ( !VALID_DEBUG_PRINT_OBJECT()) {
 | 
						||
        
 | 
						||
        return ( GetLastError());
 | 
						||
    }
 | 
						||
 | 
						||
    INITIALIZE_CRITICAL_SECTION( &g_csOpenFiles);
 | 
						||
 | 
						||
#ifdef _NO_TRACING_
 | 
						||
    SET_DEBUG_FLAGS(DEBUG_ERROR);
 | 
						||
#endif
 | 
						||
    INITIALIZE_PLATFORM_TYPE();
 | 
						||
    DBG_ASSERT( IISIsValidPlatform());
 | 
						||
 | 
						||
    if ( TsIsWindows95()) {
 | 
						||
 | 
						||
        //
 | 
						||
        // Reset the flags appropriately so that Windows 95 will be happy
 | 
						||
        //
 | 
						||
 | 
						||
        g_dwCreateFileShareMode = (FILE_SHARE_READ | FILE_SHARE_WRITE);
 | 
						||
        g_dwCreateFileFlags     = (FILE_FLAG_SEQUENTIAL_SCAN);
 | 
						||
    }
 | 
						||
 | 
						||
    return (NO_ERROR);
 | 
						||
 | 
						||
} // InitFileHandleCache()
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
DWORD
 | 
						||
CleanupFileHandleCache(VOID)
 | 
						||
{
 | 
						||
    LPOPEN_FILE  pFileScan;
 | 
						||
 | 
						||
    while ( g_pOpenFiles != NULL) {
 | 
						||
 | 
						||
        pFileScan = g_pOpenFiles;
 | 
						||
        g_pOpenFiles = g_pOpenFiles->pNext;
 | 
						||
 | 
						||
        if ( pFileScan->hFile != INVALID_HANDLE_VALUE) {
 | 
						||
 | 
						||
            CloseHandle( pFileScan->hFile);
 | 
						||
        }
 | 
						||
 | 
						||
        LocalFree( pFileScan);
 | 
						||
    }
 | 
						||
 | 
						||
    DeleteCriticalSection( &g_csOpenFiles);
 | 
						||
 | 
						||
    DELETE_DEBUG_PRINT_OBJECT();
 | 
						||
 | 
						||
    return (NO_ERROR);
 | 
						||
} // CleanupFileHandleCache()
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
HANDLE
 | 
						||
FcOpenFile(IN EXTENSION_CONTROL_BLOCK * pecb, IN LPCSTR pszFile)
 | 
						||
/*++
 | 
						||
 | 
						||
 FcOpenFile()
 | 
						||
 
 | 
						||
 Description:
 | 
						||
   This function opens the file specified in the 'pszFile'. 
 | 
						||
   If the file name starts with a '/' we use the ECB to map 
 | 
						||
   the given path into a physical file path.
 | 
						||
 | 
						||
 Arguments:
 | 
						||
  pecb - pointer to the ECB block
 | 
						||
  pszFile - pointer to file name
 | 
						||
 | 
						||
 Returns:
 | 
						||
   valid File handle on success
 | 
						||
--*/
 | 
						||
{
 | 
						||
    LPOPEN_FILE  pFileScan;
 | 
						||
    HANDLE hFile = INVALID_HANDLE_VALUE;
 | 
						||
 | 
						||
    EnterCriticalSection( &g_csOpenFiles);
 | 
						||
 | 
						||
    for ( pFileScan =  g_pOpenFiles; 
 | 
						||
         NULL != pFileScan; 
 | 
						||
         pFileScan = pFileScan->pNext) {
 | 
						||
 | 
						||
        if ( 0 == lstrcmpi( pFileScan->rgchFile, pszFile)) {
 | 
						||
 | 
						||
            //
 | 
						||
            //  there is a file match. 
 | 
						||
            //
 | 
						||
 | 
						||
            break;
 | 
						||
        }
 | 
						||
 | 
						||
    } // for
 | 
						||
 | 
						||
 | 
						||
    if ( NULL == pFileScan) {
 | 
						||
 | 
						||
        //
 | 
						||
        // File was not found. Create a new file handle
 | 
						||
        //
 | 
						||
 | 
						||
        CHAR   rgchFileName[ MAX_PATH]; // local copy
 | 
						||
        LPCSTR pszInputPath = pszFile;
 | 
						||
        
 | 
						||
        lstrcpyn( rgchFileName, pszFile, MAX_PATH);
 | 
						||
        if ( *pszFile == '/') { 
 | 
						||
 | 
						||
            DWORD cbSize = sizeof(rgchFileName);
 | 
						||
            BOOL  fRet;
 | 
						||
 | 
						||
            // reset the file pointer, so subsequent use will fail
 | 
						||
            pszFile = NULL;
 | 
						||
 | 
						||
            //
 | 
						||
            // Using the ECB map the Virtual path to the Physical path
 | 
						||
            //
 | 
						||
 | 
						||
            fRet = pecb->ServerSupportFunction( pecb->ConnID,
 | 
						||
                                                HSE_REQ_MAP_URL_TO_PATH,
 | 
						||
                                                rgchFileName,
 | 
						||
                                                &cbSize, NULL);
 | 
						||
            
 | 
						||
            if (fRet) {
 | 
						||
                // we got the mapping. Use it.
 | 
						||
                pszFile = rgchFileName;
 | 
						||
            }
 | 
						||
        }   
 | 
						||
 | 
						||
        if ( NULL != pszFile) {
 | 
						||
            pFileScan = LocalAlloc( LPTR, sizeof( *pFileScan));
 | 
						||
 | 
						||
            if ( NULL != pFileScan) {
 | 
						||
                
 | 
						||
                SECURITY_ATTRIBUTES sa;
 | 
						||
                
 | 
						||
                sa.nLength              = sizeof(sa);
 | 
						||
                sa.lpSecurityDescriptor = NULL;
 | 
						||
                sa.bInheritHandle       = FALSE;
 | 
						||
                
 | 
						||
                pFileScan->hFile = 
 | 
						||
                    CreateFile( pszFile,
 | 
						||
                                GENERIC_READ,
 | 
						||
                                g_dwCreateFileShareMode,
 | 
						||
                                &sa,
 | 
						||
                                OPEN_EXISTING,
 | 
						||
                                g_dwCreateFileFlags,
 | 
						||
                                NULL );
 | 
						||
                
 | 
						||
                if ( INVALID_HANDLE_VALUE == pFileScan->hFile) {
 | 
						||
                    
 | 
						||
                    LocalFree( pFileScan);
 | 
						||
                    pFileScan = NULL;
 | 
						||
                } else {
 | 
						||
                    
 | 
						||
                    // insert this into the list at the top
 | 
						||
                    lstrcpyn( pFileScan->rgchFile, pszInputPath, MAX_PATH);
 | 
						||
                    pFileScan->pNext = g_pOpenFiles;
 | 
						||
                    g_pOpenFiles = pFileScan;
 | 
						||
                    pFileScan->nRefs = 1;
 | 
						||
                    pFileScan->nHits = 0;
 | 
						||
                }
 | 
						||
            }
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
    if ( NULL != pFileScan) {
 | 
						||
 | 
						||
        hFile = pFileScan->hFile;
 | 
						||
        pFileScan->nHits++;
 | 
						||
        pFileScan->nRefs++;
 | 
						||
    }
 | 
						||
 | 
						||
    LeaveCriticalSection( &g_csOpenFiles);
 | 
						||
 | 
						||
    return (hFile);
 | 
						||
 | 
						||
} // FcOpenFile()
 | 
						||
 | 
						||
 | 
						||
 | 
						||
DWORD
 | 
						||
FcCloseFile(IN HANDLE hFile)
 | 
						||
{
 | 
						||
    LPOPEN_FILE  pFileScan;
 | 
						||
    DWORD dwError = NO_ERROR;
 | 
						||
 | 
						||
    EnterCriticalSection( &g_csOpenFiles);
 | 
						||
 | 
						||
    //
 | 
						||
    // Look for the handle and decrement the ref count.
 | 
						||
    // 
 | 
						||
    for ( pFileScan =  g_pOpenFiles; 
 | 
						||
         NULL != pFileScan; 
 | 
						||
         pFileScan = pFileScan->pNext) {
 | 
						||
 | 
						||
        if ( hFile == pFileScan->hFile) {
 | 
						||
 | 
						||
            //
 | 
						||
            //  there is a file match. 
 | 
						||
            //
 | 
						||
 | 
						||
            pFileScan->nRefs--;
 | 
						||
 | 
						||
            //
 | 
						||
            // NOTE: There is no freeing of the file when Ref hits '0' :(
 | 
						||
            //
 | 
						||
 | 
						||
            break;
 | 
						||
        }
 | 
						||
 | 
						||
    } // for
 | 
						||
 | 
						||
 | 
						||
    if ( NULL == pFileScan) {
 | 
						||
        //
 | 
						||
        // file handle not found
 | 
						||
        //
 | 
						||
        dwError = ( ERROR_INVALID_HANDLE);
 | 
						||
    }
 | 
						||
 | 
						||
    LeaveCriticalSection( &g_csOpenFiles);
 | 
						||
 | 
						||
 | 
						||
    return ( dwError);
 | 
						||
 | 
						||
} // FcCloseFile()
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
BOOL
 | 
						||
FcReadFromFile(
 | 
						||
               IN  HANDLE hFile,
 | 
						||
               OUT CHAR * pchBuffer,
 | 
						||
               IN  DWORD  dwBufferSize,
 | 
						||
               OUT LPDWORD  pcbRead,
 | 
						||
               IN OUT LPOVERLAPPED  pov
 | 
						||
               )
 | 
						||
/*++
 | 
						||
  Description:
 | 
						||
    Reads contents of file [hFile] from the specified offset in the overlapped 
 | 
						||
    structure. The contents are read into the buffer supplied.
 | 
						||
 | 
						||
  Arguments:
 | 
						||
    hFile        - handle for the File from which to read data
 | 
						||
    pchBuffer    - pointer to the buffer into which the data is to be read
 | 
						||
    dwBufferSize - DWORD containing the max size of the buffer supplied
 | 
						||
    pcbRead      - number of bytes read from the file
 | 
						||
    pov          - pointer to an overlapped structure that contains the 
 | 
						||
                     offset from where to read the contents. The
 | 
						||
                     overlapped structure also is used for Overlapped
 | 
						||
                     IO in NT.
 | 
						||
 | 
						||
  Notes:
 | 
						||
   This function automatically handles both Windows 95 and NT
 | 
						||
   
 | 
						||
 | 
						||
  Returns:
 | 
						||
    TRUE on success and FALSE if there is a failure.
 | 
						||
    Use GetLastError() to get the last error code on failure.
 | 
						||
--*/
 | 
						||
{
 | 
						||
    BOOL fRet = TRUE;
 | 
						||
 | 
						||
    DBG_ASSERT( hFile != INVALID_HANDLE_VALUE);
 | 
						||
    DBG_ASSERT( NULL != pchBuffer);
 | 
						||
    DBG_ASSERT( NULL != pov);
 | 
						||
    DBG_ASSERT( NULL != pcbRead);
 | 
						||
    DBG_ASSERT( 0 < dwBufferSize);
 | 
						||
 | 
						||
    *pcbRead = 0;
 | 
						||
    
 | 
						||
    if ( TsIsWindows95()) {
 | 
						||
        //
 | 
						||
        // Windows95 does not support Overlapped IO.
 | 
						||
        //  So we shall thunk it out and use Synchronous IO
 | 
						||
        //
 | 
						||
 | 
						||
	DWORD dwError =   SetFilePointer( hFile, 
 | 
						||
                                pov->Offset,
 | 
						||
                                 NULL,
 | 
						||
                                FILE_BEGIN);
 | 
						||
 | 
						||
	// Apparently SetFilePointer() returns -1 for failure.
 | 
						||
	fRet = (dwError != 0xFFFFFFFF); 
 | 
						||
 | 
						||
        if ( fRet) { 
 | 
						||
            fRet = ReadFile( hFile,
 | 
						||
                             pchBuffer,
 | 
						||
                             dwBufferSize,
 | 
						||
                             pcbRead,
 | 
						||
                             NULL
 | 
						||
                            );
 | 
						||
	    if ( fRet && (*pcbRead == 0)) {
 | 
						||
                 // we are at end of file
 | 
						||
                 fRet = FALSE;
 | 
						||
                 SetLastError( ERROR_HANDLE_EOF);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
    } else {
 | 
						||
            
 | 
						||
            ResetEvent( pov->hEvent);
 | 
						||
 | 
						||
            fRet = TRUE;
 | 
						||
 | 
						||
            // read data from file
 | 
						||
            if (!ReadFile(hFile,
 | 
						||
                          pchBuffer,
 | 
						||
                          dwBufferSize,
 | 
						||
                          pcbRead,
 | 
						||
                          pov
 | 
						||
                          )) {
 | 
						||
                
 | 
						||
                DWORD err = GetLastError();
 | 
						||
                
 | 
						||
                if ( (err != ERROR_IO_PENDING) ||
 | 
						||
                     !GetOverlappedResult( hFile, pov,
 | 
						||
                                           pcbRead, TRUE)) {
 | 
						||
                    
 | 
						||
                    fRet = FALSE;
 | 
						||
                }
 | 
						||
            }
 | 
						||
    }
 | 
						||
 | 
						||
    if ( fRet) {
 | 
						||
        pov->Offset += *pcbRead;
 | 
						||
    }
 | 
						||
 | 
						||
    return ( fRet);
 | 
						||
} // FcReadFromFile()
 | 
						||
 | 
						||
/************************ End of File ***********************/
 |