windows-nt/Source/XPSP1/NT/drivers/storage/drivearb/dll/drive.c

159 lines
3.8 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*
* DRIVE.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"
/*
* NewDriveContext
*
* Must be called with globalMutex held.
* Should only be called in the service context, not by a client.
*
*/
driveContext *NewDriveContext(LPSTR driveName)
{
driveContext *drive = NULL;
DWORD driveIndex;
/*
* Find an available drive context
*
* BUGBUG - make this more efficient; e.g. use a free list
*/
for (driveIndex = 0; driveIndex < g_numDrivesInFileMap; driveIndex++){
driveContext *d = &g_allDrivesViewPtr[driveIndex];
if (d->state == DRIVESTATE_NONE){
drive = d;
break;
}
}
if (drive){
char driveMutexName[sizeof(DRIVE_MUTEX_NAME_PREFIX)+8];
drive->sig = DRIVEARB_SIG;
wsprintf(driveMutexName, "%s%08x", DRIVE_MUTEX_NAME_PREFIX, driveIndex);
drive->mutex = CreateMutex(NULL, FALSE, (LPSTR)driveMutexName);
if (drive->mutex){
char driveEventName[sizeof(DRIVE_EVENT_NAME_PREFIX)+8];
wsprintf(driveEventName, "%s%08x", DRIVE_EVENT_NAME_PREFIX, driveIndex);
drive->event = CreateEvent(NULL, FALSE, FALSE, (LPSTR)driveEventName);
if (drive->event){
drive->state = DRIVESTATE_UNAVAILABLE_LOCALLY;
MyStrNCpy(drive->driveName, driveName, MAX_PATH);
// DBGMSG("NewDriveContext created drive:", driveIndex);
// DBGMSG(drive->driveName, 0);
}
else {
CloseHandle(drive->mutex);
drive = NULL;
}
}
else {
drive = NULL;
}
}
else {
/*
* No more free drive contexts in the current fileMap.
* So grow the fileMap and try again.
*/
BOOL ok = GrowDrivesFileMapping(g_numDrivesInFileMap*2);
if (ok){
drive = NewDriveContext(driveName);
}
}
return drive;
}
/*
* FreeDriveContext
*
* Must be called with globalMutex held.
* Should only be called in the service context, not by a client.
*
*/
VOID FreeDriveContext(driveContext *drive)
{
CloseHandle(drive->mutex);
CloseHandle(drive->event);
drive->state = DRIVESTATE_NONE;
}
/*
* GetDriveIndexByName
*
* Must be called with globalMutex held.
*
* Return drive index if it exists; else return -1.
*/
DWORD GetDriveIndexByName(LPSTR driveName)
{
HANDLE hDrivesFileMap;
DWORD driveIndex = -1;
/*
* Create a temporary read-only mapping of the entire drives array
* so we can look for the drive.
*/
hDrivesFileMap = OpenFileMapping(FILE_MAP_READ, FALSE, DRIVES_FILEMAP_NAME);
if (hDrivesFileMap){
driveContext *allDrivesViewPtr = MapViewOfFile(hDrivesFileMap, FILE_MAP_READ, 0, 0, 0);
if (allDrivesViewPtr){
DWORD i;
for (i = 0; i < g_numDrivesInFileMap; i++){
driveContext *d = &allDrivesViewPtr[i];
if ((d->state != DRIVESTATE_NONE) &&
MyCompareStringsI(d->driveName, driveName)){
driveIndex = i;
break;
}
}
UnmapViewOfFile(allDrivesViewPtr);
}
else {
ASSERT(allDrivesViewPtr);
}
CloseHandle(hDrivesFileMap);
}
else {
ASSERT(hDrivesFileMap);
}
ASSERT(driveIndex != -1);
return driveIndex;
}