windows-nt/Source/XPSP1/NT/base/fs/sis/groveler/share.cpp
2020-09-26 16:20:57 +08:00

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