262 lines
5.4 KiB
C
262 lines
5.4 KiB
C
/* Copyright (c) 1995-2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
openf.c
|
|
|
|
Abstract:
|
|
|
|
This module implements a simple open file handle cache
|
|
*/
|
|
|
|
#include "openf.h"
|
|
|
|
/* 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);
|
|
|
|
VOID InitFileHandleCache(VOID)
|
|
{
|
|
InitializeCriticalSection(&g_csOpenFiles);
|
|
}
|
|
|
|
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);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
/*
|
|
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
|
|
*/
|
|
|
|
HANDLE FcOpenFile(IN EXTENSION_CONTROL_BLOCK *pecb, IN LPCSTR pszFile)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
if (NULL == pFileScan) {
|
|
|
|
/* File was not found. Create a new file handle */
|
|
|
|
CHAR rgchFileName[ MAX_PATH]; /* local copy */
|
|
LPCSTR pszInputPath = pszFile;
|
|
|
|
strncpy_s(rgchFileName, sizeof(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 */
|
|
|
|
strncpy_s(pFileScan->rgchFile, sizeof(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;
|
|
}
|
|
|
|
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: This is example code. Do not use for production, as there
|
|
is no freeing of the file when Ref hits 0
|
|
*/
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (NULL == pFileScan) {
|
|
|
|
/* file handle not found */
|
|
|
|
dwError = (ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
LeaveCriticalSection(&g_csOpenFiles);
|
|
|
|
return dwError;
|
|
}
|
|
|
|
/*
|
|
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 FcReadFromFile(IN HANDLE hFile, OUT CHAR *pchBuffer, IN DWORD dwBufferSize, OUT LPDWORD pcbRead, IN OUT LPOVERLAPPED pov)
|
|
{
|
|
BOOL fRet = TRUE;
|
|
|
|
*pcbRead = 0;
|
|
|
|
ResetEvent(pov->hEvent);
|
|
|
|
/* 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;
|
|
}
|