windows-nt/Source/XPSP1/NT/drivers/storage/drivearb/dll/filemap.c
2020-09-26 16:20:57 +08:00

198 lines
5.8 KiB
C

/*
* FILEMAP.C
*
*
* DRIVEARB.DLL - Shared Drive Aribiter for shared disks and libraries
* - inter-machine sharing client
* - inter-app sharing service
*
* Author: ErvinP
*
* (c) 2000 Microsoft Corporation
*
*/
#include <stdlib.h>
#include <wtypes.h>
#include <dlmhdr.h> // BUGBUG - get a common DLM header from Cluster team
#include <drivearb.h>
#include "internal.h"
/*
* InitDrivesFileMappingForProcess
*
* Either create or open the drives fileMapping for this process.
* Then map a process-local view to it.
*/
BOOL InitDrivesFileMappingForProcess()
{
BOOL result = FALSE;
/*
* See if the global drives fileMapping has already
* been created for some other process by trying to open it.
* If not, allocate it.
*/
g_allDrivesFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, DRIVES_FILEMAP_NAME);
if (!g_allDrivesFileMap){
g_allDrivesFileMap =
CreateFileMapping(
INVALID_HANDLE_VALUE, // map a portion of the paging file
NULL, // BUGBUG security
PAGE_READWRITE,
0,
DRIVES_FILEMAP_INITIAL_SIZE*sizeof(driveContext),
DRIVES_FILEMAP_NAME);
}
if (g_allDrivesFileMap){
g_allDrivesViewPtr = MapViewOfFile(
g_allDrivesFileMap,
FILE_MAP_ALL_ACCESS,
0, 0, 0);
if (g_allDrivesViewPtr){
g_numDrivesInFileMap = DRIVES_FILEMAP_INITIAL_SIZE;
result = TRUE;
}
else {
ASSERT(g_allDrivesViewPtr);
}
}
else {
ASSERT(g_allDrivesFileMap);
}
return result;
}
/*
* DestroyDrivesFileMappingForProcess
*
*/
VOID DestroyDrivesFileMappingForProcess()
{
if (g_allDrivesViewPtr){
UnmapViewOfFile(g_allDrivesViewPtr);
g_allDrivesViewPtr = NULL;
}
if (g_allDrivesFileMap){
CloseHandle(g_allDrivesFileMap);
g_allDrivesFileMap = NULL;
}
}
/*
* GrowDrivesFileMapping
*
* Must be called with globalMutex held.
* Should only be called in the service context, not by a client.
*/
BOOL GrowDrivesFileMapping(DWORD newNumDrives)
{
BOOL result = FALSE;
if (newNumDrives > g_numDrivesInFileMap){
HANDLE hNewFileMap;
driveContext *newAllDrivesViewPtr;
driveContext *drive;
DWORD driveIndex;
/*
* Lock down every drive.
* We have to do this since the common codepaths
* (e.g. drive AcquireDrive/ReleaseDrive)
* don't contend for the global mutex.
*/
for (driveIndex = 0; driveIndex < g_numDrivesInFileMap; driveIndex++){
drive = &g_allDrivesViewPtr[driveIndex];
WaitForSingleObject(drive->mutex, INFINITE);
}
/*
* Try to create the new, resized file map.
*/
hNewFileMap = CreateFileMapping(
INVALID_HANDLE_VALUE, // map a portion of the paging file
NULL, // BUGBUG security
PAGE_READWRITE,
0,
newNumDrives*sizeof(driveContext),
DRIVES_FILEMAP_NAME);
if (hNewFileMap){
newAllDrivesViewPtr = MapViewOfFile( hNewFileMap,
FILE_MAP_ALL_ACCESS,
0, 0, 0);
if (newAllDrivesViewPtr){
RtlZeroMemory(newAllDrivesViewPtr, newNumDrives*sizeof(driveContext));
/*
* Copy the existing drive contexts to the new filemap.
* The drive mutex and event handles remain valid as
* they're copied over.
*/
RtlCopyMemory( newAllDrivesViewPtr,
g_allDrivesViewPtr,
g_numDrivesInFileMap*sizeof(driveContext));
/*
* Mark each drive in the old fileMap as reallocated
* so sessions know to refresh their handles.
* (the old fileMap will stay in memory until each
* session closes its old handle)
*/
for (driveIndex = 0; driveIndex < g_numDrivesInFileMap; driveIndex++){
drive = &g_allDrivesViewPtr[driveIndex];
drive->isReallocated = TRUE;
}
result = TRUE;
}
else {
DBGMSG("GrowDrivesFileMapping: MapViewOfFile failed", 0);
CloseHandle(hNewFileMap);
hNewFileMap = NULL;
}
}
else {
DBGMSG("GrowDrivesFileMapping: CreateFileMapping failed", 0);
newAllDrivesViewPtr = NULL;
}
/*
* Unlock all drives
*/
for (driveIndex = g_numDrivesInFileMap; driveIndex > 0 ; driveIndex--){
drive = &g_allDrivesViewPtr[driveIndex-1];
ReleaseMutex(drive->mutex);
}
if (result){
/*
* Delete the old filemap.
* The filemap will actually continue to exist until
* all client session handles are removed.
*/
UnmapViewOfFile(g_allDrivesViewPtr);
CloseHandle(g_allDrivesFileMap);
/*
* Set globals to reflect new filemap
*/
g_allDrivesFileMap = hNewFileMap;
g_allDrivesViewPtr = newAllDrivesViewPtr;
g_numDrivesInFileMap = newNumDrives;
}
}
else {
ASSERT(newNumDrives > g_numDrivesInFileMap);
}
return result;
}