214 lines
6.6 KiB
C
214 lines
6.6 KiB
C
/*
|
|
* SESSION.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"
|
|
|
|
|
|
clientSessionContext *NewClientSession(LPSTR driveName)
|
|
{
|
|
clientSessionContext *session;
|
|
|
|
session = (clientSessionContext *)GlobalAlloc(
|
|
GMEM_FIXED|GMEM_ZEROINIT,
|
|
sizeof(clientSessionContext));
|
|
if (session){
|
|
BOOL success = FALSE;
|
|
|
|
session->sig = DRIVEARB_SIG;
|
|
|
|
|
|
WaitForSingleObject(g_hSharedGlobalMutex, INFINITE);
|
|
|
|
session->driveIndex = GetDriveIndexByName(driveName);
|
|
if (session->driveIndex != -1){
|
|
|
|
/*
|
|
* Map just this one drive context into this process' address space.
|
|
*/
|
|
session->hDrivesFileMap = OpenFileMapping(
|
|
FILE_MAP_ALL_ACCESS,
|
|
FALSE,
|
|
DRIVES_FILEMAP_NAME);
|
|
if (session->hDrivesFileMap){
|
|
|
|
session->driveViewPtr = MapViewOfFile(
|
|
session->hDrivesFileMap,
|
|
FILE_MAP_ALL_ACCESS,
|
|
0,
|
|
session->driveIndex*sizeof(driveContext),
|
|
sizeof(driveContext));
|
|
if (session->driveViewPtr){
|
|
|
|
/*
|
|
* Map the drive mutex into this process' address space
|
|
*/
|
|
char driveMutexName[sizeof(DRIVE_MUTEX_NAME_PREFIX)+8];
|
|
wsprintf(driveMutexName, "%s%08x", DRIVE_MUTEX_NAME_PREFIX, session->driveIndex);
|
|
session->sessionDriveMutex = OpenMutex(SYNCHRONIZE, FALSE, (LPSTR)driveMutexName);
|
|
if (session->sessionDriveMutex){
|
|
|
|
/*
|
|
* Map the drive event into this process' address space
|
|
*/
|
|
char driveEventName[sizeof(DRIVE_EVENT_NAME_PREFIX)+8];
|
|
wsprintf(driveEventName, "%s%08x", DRIVE_EVENT_NAME_PREFIX, session->driveIndex);
|
|
session->sessionDriveEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, (LPSTR)driveEventName);
|
|
if (session->sessionDriveEvent){
|
|
|
|
session->state = CLIENTSTATE_INACTIVE;
|
|
success = TRUE;
|
|
}
|
|
else {
|
|
ASSERT(session->sessionDriveEvent);
|
|
}
|
|
}
|
|
else {
|
|
ASSERT(session->sessionDriveMutex);
|
|
}
|
|
}
|
|
else {
|
|
ASSERT(session->driveViewPtr);
|
|
}
|
|
}
|
|
else {
|
|
ASSERT(session->hDrivesFileMap);
|
|
}
|
|
}
|
|
else {
|
|
ASSERT(session->driveIndex != -1);
|
|
}
|
|
|
|
ReleaseMutex(g_hSharedGlobalMutex);
|
|
|
|
if (!success){
|
|
FreeClientSession(session);
|
|
session = NULL;
|
|
}
|
|
}
|
|
else {
|
|
ASSERT(session);
|
|
}
|
|
|
|
ASSERT(session);
|
|
return session;
|
|
}
|
|
|
|
|
|
VOID FreeClientSession(clientSessionContext *session)
|
|
{
|
|
/*
|
|
* This function is also called for error cases in NewClientSession,
|
|
* so check each object before freeing it.
|
|
*/
|
|
|
|
if (session->driveViewPtr){
|
|
UnmapViewOfFile(session->driveViewPtr);
|
|
}
|
|
if (session->hDrivesFileMap){
|
|
CloseHandle(session->hDrivesFileMap);
|
|
}
|
|
if (session->sessionDriveMutex){
|
|
CloseHandle(session->sessionDriveMutex);
|
|
}
|
|
if (session->sessionDriveEvent){
|
|
CloseHandle(session->sessionDriveEvent);
|
|
}
|
|
|
|
GlobalFree(session);
|
|
}
|
|
|
|
|
|
BOOL LOCKDriveForSession(clientSessionContext *session)
|
|
{
|
|
BOOL result;
|
|
|
|
WaitForSingleObject(session->sessionDriveMutex, INFINITE);
|
|
|
|
if (session->driveViewPtr->isReallocated){
|
|
/*
|
|
* The drive filemap was reallocated.
|
|
* Refresh this sessions's filemap.
|
|
*/
|
|
|
|
UnmapViewOfFile(session->driveViewPtr);
|
|
CloseHandle(session->hDrivesFileMap);
|
|
|
|
session->hDrivesFileMap = OpenFileMapping(
|
|
FILE_MAP_ALL_ACCESS,
|
|
FALSE,
|
|
DRIVES_FILEMAP_NAME);
|
|
if (session->hDrivesFileMap){
|
|
session->driveViewPtr = MapViewOfFile(
|
|
session->hDrivesFileMap,
|
|
FILE_MAP_READ,
|
|
0,
|
|
session->driveIndex*sizeof(driveContext),
|
|
sizeof(driveContext));
|
|
if (session->driveViewPtr){
|
|
/*
|
|
* No need to set isReallocated = FALSE
|
|
* since driveViewPtr is now pointing to a fresh context.
|
|
*/
|
|
result = TRUE;
|
|
}
|
|
else {
|
|
ASSERT(session->driveViewPtr);
|
|
CloseHandle(session->hDrivesFileMap);
|
|
session->hDrivesFileMap = NULL;
|
|
result = FALSE;
|
|
}
|
|
}
|
|
else {
|
|
ASSERT(session->hDrivesFileMap);
|
|
session->driveViewPtr = NULL;
|
|
result = FALSE;
|
|
}
|
|
|
|
if (!result){
|
|
ReleaseMutex(session->sessionDriveMutex);
|
|
|
|
/*
|
|
* Call the client's invalidateHandleProc callback to let them
|
|
* know that the session is now invalid.
|
|
* Must call this with sessionDriveMutex released because
|
|
* the client will call CloseDriveSession inside this call.
|
|
* There is no race condition wrt not holding the mutex
|
|
* because we're still inside a client's call on this session
|
|
* (client must synchronize calls on a session).
|
|
*/
|
|
ASSERT(session->invalidateHandleProc);
|
|
session->invalidateHandleProc(session);
|
|
}
|
|
}
|
|
else {
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
VOID UNLOCKDriveForSession(clientSessionContext *session)
|
|
{
|
|
ReleaseMutex(session->sessionDriveMutex);
|
|
}
|
|
|
|
|