2025-11-28 00:35:46 +09:00

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;
}