422 lines
8.5 KiB
C++
422 lines
8.5 KiB
C++
/*++
|
|
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
share.cpp
|
|
|
|
Abstract:
|
|
|
|
SIS Groveler shared data class
|
|
|
|
Authors:
|
|
|
|
John Douceur, 1998
|
|
|
|
Environment:
|
|
|
|
User Mode
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include "all.hxx"
|
|
|
|
static const _TCHAR map_name[] = _T("Groveler Shared Memory");
|
|
static const _TCHAR mutex_name[] = _T("Groveler Shared Memory Mutex");
|
|
static const int mutex_timeout = 500;
|
|
|
|
#define ALIGN_INT64(x) \
|
|
(((x+sizeof(__int64)-1)/sizeof(__int64))*sizeof(__int64))
|
|
|
|
SharedData::SharedData(
|
|
int num_records,
|
|
_TCHAR **drive_names)
|
|
{
|
|
ASSERT(this != 0);
|
|
ASSERT(num_records <= max_shared_data_records);
|
|
map_ok = false;
|
|
mutex = 0;
|
|
map_handle = 0;
|
|
map_address = 0;
|
|
shared_num_records = 0;
|
|
shared_records = 0;
|
|
security_identifier = 0;
|
|
access_control_list = 0;
|
|
ZeroMemory(&security_attributes, sizeof(SECURITY_ATTRIBUTES));
|
|
ZeroMemory(&security_descriptor, sizeof(SECURITY_DESCRIPTOR));
|
|
|
|
//
|
|
// Initailize a Security descriptor so we can setup secure access
|
|
// to a shared file.
|
|
//
|
|
|
|
security_attributes.bInheritHandle = FALSE;
|
|
security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
security_attributes.lpSecurityDescriptor = (void *)&security_descriptor;
|
|
|
|
BOOL success = InitializeSecurityDescriptor(&security_descriptor,
|
|
SECURITY_DESCRIPTOR_REVISION);
|
|
if (!success)
|
|
{
|
|
DWORD err = GetLastError();
|
|
PRINT_DEBUG_MSG((
|
|
_T("GROVELER: InitializeSecurityDescriptor() failed with error %d\n"), err));
|
|
return;
|
|
}
|
|
|
|
SID_IDENTIFIER_AUTHORITY sid_authority = SECURITY_NT_AUTHORITY;
|
|
success = AllocateAndInitializeSid(
|
|
&sid_authority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
&security_identifier);
|
|
if (!success)
|
|
{
|
|
DWORD err = GetLastError();
|
|
PRINT_DEBUG_MSG((
|
|
_T("GROVELER: AllocateAndInitializeSid() failed with error %d\n"), err));
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Create ACL
|
|
//
|
|
|
|
DWORD acl_size = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
|
|
+ GetLengthSid(security_identifier);
|
|
access_control_list = (PACL)new BYTE[acl_size];
|
|
|
|
success = InitializeAcl(
|
|
access_control_list,
|
|
acl_size,
|
|
ACL_REVISION);
|
|
if (!success)
|
|
{
|
|
DWORD err = GetLastError();
|
|
PRINT_DEBUG_MSG((_T("GROVELER: InitializeAcl() failed with error %d\n"), err));
|
|
return;
|
|
}
|
|
|
|
success = AddAccessAllowedAce(
|
|
access_control_list,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
security_identifier);
|
|
if (!success)
|
|
{
|
|
DWORD err = GetLastError();
|
|
PRINT_DEBUG_MSG((_T("GROVELER: AddAccessAllowedAce() failed with error %d\n"),
|
|
err));
|
|
return;
|
|
}
|
|
|
|
success = SetSecurityDescriptorDacl(
|
|
&security_descriptor,
|
|
TRUE,
|
|
access_control_list,
|
|
FALSE);
|
|
if (!success)
|
|
{
|
|
DWORD err = GetLastError();
|
|
PRINT_DEBUG_MSG((_T("GROVELER: SetSecurityDescriptorDacl() failed with error %d\n"),
|
|
err));
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Create a named mutex
|
|
//
|
|
|
|
mutex = new NamedMutex(mutex_name, &security_attributes);
|
|
ASSERT(mutex != 0);
|
|
|
|
//
|
|
// Calcualte size of mapped file
|
|
//
|
|
|
|
int map_size = ALIGN_INT64(sizeof(int))
|
|
+ ALIGN_INT64(max_shared_data_records * sizeof(SharedDataRecord));
|
|
bool ok = mutex->acquire(mutex_timeout);
|
|
if (!ok)
|
|
{
|
|
PRINT_DEBUG_MSG((_T("GROVELER: Mutex::acquire() failed\n")));
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Create the mapped file. Note that it will be backed by system paging
|
|
// files.
|
|
//
|
|
|
|
map_handle = CreateFileMapping((HANDLE)-1, &security_attributes,
|
|
PAGE_READWRITE, 0, map_size, map_name);
|
|
DWORD map_error = GetLastError();
|
|
if (map_handle == 0)
|
|
{
|
|
PRINT_DEBUG_MSG((_T("GROVELER: CreateFileMapping() failed with error %d\n"),
|
|
map_error));
|
|
return;
|
|
}
|
|
ASSERT(map_error == NO_ERROR || map_error == ERROR_ALREADY_EXISTS);
|
|
|
|
//
|
|
// Map a view for this file
|
|
//
|
|
|
|
map_address =
|
|
MapViewOfFile(map_handle, FILE_MAP_ALL_ACCESS, 0, 0, map_size);
|
|
if (map_address == 0)
|
|
{
|
|
DWORD err = GetLastError();
|
|
PRINT_DEBUG_MSG((_T("GROVELER: MapViewOfFile() failed with error %d\n"), err));
|
|
return;
|
|
}
|
|
|
|
shared_num_records = (int *)map_address;
|
|
shared_records =
|
|
(SharedDataRecord *)ALIGN_INT64((DWORD_PTR)(shared_num_records + 1));
|
|
|
|
local_num_records = __max(num_records, 0);
|
|
ZeroMemory(local_records, max_shared_data_records * sizeof(SharedDataRecord));
|
|
|
|
ASSERT(local_num_records == 0 || drive_names != 0);
|
|
|
|
for (int index = 0; index < local_num_records; index++)
|
|
{
|
|
local_records[index].driveName = drive_names[index];
|
|
}
|
|
|
|
map_ok = true;
|
|
if (num_records >= 0 || map_error == NO_ERROR)
|
|
{
|
|
bool ok = send_values();
|
|
}
|
|
|
|
ok = mutex->release();
|
|
if (!ok)
|
|
{
|
|
PRINT_DEBUG_MSG((_T("GROVELER: Mutex::release() failed\n")));
|
|
}
|
|
}
|
|
|
|
SharedData::~SharedData()
|
|
{
|
|
ASSERT(this != 0);
|
|
ASSERT(mutex != 0);
|
|
delete mutex;
|
|
mutex = 0;
|
|
if (map_address != 0)
|
|
{
|
|
int ok = UnmapViewOfFile(map_address);
|
|
if (!ok)
|
|
{
|
|
DWORD err = GetLastError();
|
|
PRINT_DEBUG_MSG((_T("GROVELER: UnmapViewOfFile() failed with error %d\n"),
|
|
err));
|
|
}
|
|
map_address = 0;
|
|
}
|
|
if (map_handle != 0)
|
|
{
|
|
int ok = CloseHandle(map_handle);
|
|
if (!ok)
|
|
{
|
|
DWORD err = GetLastError();
|
|
PRINT_DEBUG_MSG((_T("GROVELER: CloseHandle() failed with error %d\n"), err));
|
|
}
|
|
map_handle = 0;
|
|
}
|
|
if (security_identifier != 0)
|
|
{
|
|
FreeSid(security_identifier);
|
|
security_identifier = 0;
|
|
}
|
|
if (access_control_list != 0)
|
|
{
|
|
delete[] access_control_list;
|
|
access_control_list = 0;
|
|
}
|
|
}
|
|
|
|
int
|
|
SharedData::count_of_records() const
|
|
{
|
|
ASSERT(this != 0);
|
|
return local_num_records;
|
|
}
|
|
|
|
//_TCHAR
|
|
//SharedData::drive_letter(
|
|
// int record_index) const
|
|
//{
|
|
// ASSERT(this != 0);
|
|
// ASSERT(record_index >= 0);
|
|
// ASSERT(record_index < max_shared_data_records);
|
|
// ASSERT(record_index < local_num_records);
|
|
// return local_records[record_index].drive_letter;
|
|
//}
|
|
|
|
__int64
|
|
SharedData::get_value(
|
|
int record_index,
|
|
SharedDataField field)
|
|
{
|
|
ASSERT(this != 0);
|
|
ASSERT(record_index >= 0);
|
|
ASSERT(record_index < max_shared_data_records);
|
|
ASSERT(record_index < local_num_records);
|
|
ASSERT(field >= 0);
|
|
ASSERT(field < num_shared_data_fields);
|
|
return local_records[record_index].fields[field];
|
|
}
|
|
|
|
void
|
|
SharedData::set_value(
|
|
int record_index,
|
|
SharedDataField field,
|
|
__int64 value)
|
|
{
|
|
ASSERT(this != 0);
|
|
ASSERT(record_index >= 0);
|
|
ASSERT(record_index < max_shared_data_records);
|
|
ASSERT(record_index < local_num_records);
|
|
ASSERT(field >= 0);
|
|
ASSERT(field < num_shared_data_fields);
|
|
local_records[record_index].fields[field] = value;
|
|
}
|
|
|
|
void
|
|
SharedData::increment_value(
|
|
int record_index,
|
|
SharedDataField field,
|
|
__int64 value)
|
|
{
|
|
ASSERT(this != 0);
|
|
ASSERT(record_index >= 0);
|
|
ASSERT(record_index < max_shared_data_records);
|
|
ASSERT(record_index < local_num_records);
|
|
ASSERT(field >= 0);
|
|
ASSERT(field < num_shared_data_fields);
|
|
local_records[record_index].fields[field] += value;
|
|
}
|
|
|
|
bool
|
|
SharedData::send_values()
|
|
{
|
|
ASSERT(this != 0);
|
|
if (map_ok)
|
|
{
|
|
bool ok = mutex->acquire(mutex_timeout);
|
|
if (ok)
|
|
{
|
|
ASSERT(shared_num_records != 0);
|
|
*shared_num_records = local_num_records;
|
|
ASSERT(shared_records != 0);
|
|
ASSERT(local_records != 0);
|
|
for (int index = 0; index < local_num_records; index++)
|
|
{
|
|
shared_records[index] = local_records[index];
|
|
}
|
|
ok = mutex->release();
|
|
if (!ok)
|
|
{
|
|
PRINT_DEBUG_MSG((_T("GROVELER: Mutex::release() failed\n")));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PRINT_DEBUG_MSG((_T("GROVELER: Mutex::acquire() failed\n")));
|
|
}
|
|
return ok;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool
|
|
SharedData::receive_values()
|
|
{
|
|
ASSERT(this != 0);
|
|
if (map_ok)
|
|
{
|
|
bool ok = mutex->acquire(mutex_timeout);
|
|
if (ok)
|
|
{
|
|
ASSERT(shared_num_records != 0);
|
|
local_num_records = *shared_num_records;
|
|
ASSERT(shared_records != 0);
|
|
ASSERT(local_records != 0);
|
|
for (int index = 0; index < local_num_records; index++)
|
|
{
|
|
local_records[index] = shared_records[index];
|
|
}
|
|
ok = mutex->release();
|
|
if (!ok)
|
|
{
|
|
PRINT_DEBUG_MSG((_T("GROVELER: Mutex::release() failed\n")));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PRINT_DEBUG_MSG((_T("GROVELER: Mutex::acquire() failed\n")));
|
|
}
|
|
return ok;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool
|
|
SharedData::extract_values(
|
|
int *num_records,
|
|
SharedDataRecord *records)
|
|
{
|
|
ASSERT(this != 0);
|
|
if (map_ok)
|
|
{
|
|
bool ok = mutex->acquire(mutex_timeout);
|
|
if (ok)
|
|
{
|
|
ASSERT(shared_num_records != 0);
|
|
ASSERT(num_records != 0);
|
|
*num_records = *shared_num_records;
|
|
ASSERT(shared_records != 0);
|
|
ASSERT(records != 0);
|
|
for (int index = 0; index < *num_records; index++)
|
|
{
|
|
records[index] = shared_records[index];
|
|
}
|
|
ok = mutex->release();
|
|
if (!ok)
|
|
{
|
|
PRINT_DEBUG_MSG((_T("GROVELER: Mutex::release() failed\n")));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PRINT_DEBUG_MSG((_T("GROVELER: Mutex::acquire() failed\n")));
|
|
}
|
|
return ok;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|