826 lines
19 KiB
C
826 lines
19 KiB
C
|
/*++
|
||
|
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doron J. Holan (doronh), 1-22-1998
|
||
|
--*/
|
||
|
|
||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||
|
#define WIN32_LEAN_AND_MEAN
|
||
|
#endif
|
||
|
|
||
|
#include <windows.h>
|
||
|
|
||
|
#include <msports.h>
|
||
|
#include <tchar.h>
|
||
|
|
||
|
#define GROWTH_VALUE 1024
|
||
|
|
||
|
#define BITS_INA_BYTE 8
|
||
|
|
||
|
typedef struct _DB_INFO {
|
||
|
|
||
|
HANDLE RegChangedEvent;
|
||
|
HANDLE AccessMutex;
|
||
|
|
||
|
HKEY DBKey;
|
||
|
|
||
|
PBYTE Ports;
|
||
|
ULONG PortsLength;
|
||
|
} DB_INFO, * PDB_INFO;
|
||
|
|
||
|
#define HandleToDBInfo(h) ((PDB_INFO) (h))
|
||
|
#define IsEventSignalled(hevent) (WaitForSingleObject(hevent, 0) == WAIT_OBJECT_0)
|
||
|
#define SanityCheckComNumber(num) { if (num > COMDB_MAX_PORTS_ARBITRATED) return ERROR_INVALID_PARAMETER; }
|
||
|
#define SanityCheckDBInfo(dbi) { if ((HANDLE) dbi == INVALID_HANDLE_VALUE) return ERROR_INVALID_PARAMETER; }
|
||
|
|
||
|
|
||
|
const TCHAR szMutexName[] = _T("ComPortNumberDatabaseMutexObject");
|
||
|
const TCHAR szComDBName[] = _T("ComDB");
|
||
|
const TCHAR szComDBMerge[] = _T("ComDB Merge");
|
||
|
const TCHAR szComDBPath[] = _T("System\\CurrentControlSet\\Control\\COM Name Arbiter");
|
||
|
const TCHAR szComDBPathOld[] = _T("System\\CurrentControlSet\\Services\\Serial");
|
||
|
|
||
|
#ifdef malloc
|
||
|
#undef malloc
|
||
|
#endif
|
||
|
#define malloc(size) LocalAlloc(LPTR, (size))
|
||
|
|
||
|
#ifdef free
|
||
|
#undef free
|
||
|
#endif
|
||
|
#define free LocalFree
|
||
|
|
||
|
VOID
|
||
|
DestroyDBInfo(
|
||
|
PDB_INFO DBInfo
|
||
|
)
|
||
|
{
|
||
|
if (DBInfo->AccessMutex &&
|
||
|
DBInfo->AccessMutex != INVALID_HANDLE_VALUE) {
|
||
|
CloseHandle(DBInfo->AccessMutex);
|
||
|
}
|
||
|
|
||
|
if (DBInfo->RegChangedEvent &&
|
||
|
DBInfo->RegChangedEvent != INVALID_HANDLE_VALUE) {
|
||
|
CloseHandle(DBInfo->RegChangedEvent);
|
||
|
}
|
||
|
|
||
|
if (DBInfo->DBKey &&
|
||
|
DBInfo->DBKey != (HKEY) INVALID_HANDLE_VALUE) {
|
||
|
RegCloseKey(DBInfo->DBKey);
|
||
|
}
|
||
|
|
||
|
if (DBInfo->Ports) {
|
||
|
free(DBInfo->Ports);
|
||
|
}
|
||
|
|
||
|
free(DBInfo);
|
||
|
}
|
||
|
|
||
|
LONG
|
||
|
CreationFailure (
|
||
|
PHCOMDB PHComDB,
|
||
|
PDB_INFO DBInfo
|
||
|
)
|
||
|
{
|
||
|
if (DBInfo->AccessMutex != 0)
|
||
|
ReleaseMutex(DBInfo->AccessMutex);
|
||
|
DestroyDBInfo(DBInfo);
|
||
|
*PHComDB = (HCOMDB) INVALID_HANDLE_VALUE;
|
||
|
return ERROR_ACCESS_DENIED;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
RegisterForNotification(
|
||
|
PDB_INFO DBInfo
|
||
|
)
|
||
|
{
|
||
|
ResetEvent(DBInfo->RegChangedEvent);
|
||
|
if (RegNotifyChangeKeyValue(DBInfo->DBKey,
|
||
|
FALSE,
|
||
|
REG_NOTIFY_CHANGE_LAST_SET,
|
||
|
DBInfo->RegChangedEvent,
|
||
|
TRUE) != ERROR_SUCCESS) {
|
||
|
//
|
||
|
// Can't get a notification of when the DB is changed so close the handle
|
||
|
// and we must update the DB at every access no matter what
|
||
|
//
|
||
|
CloseHandle(DBInfo->RegChangedEvent);
|
||
|
DBInfo->RegChangedEvent = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
ResizeDatabase(
|
||
|
PDB_INFO DBInfo,
|
||
|
ULONG NumberPorts
|
||
|
)
|
||
|
{
|
||
|
PBYTE newPorts = NULL;
|
||
|
ULONG newPortsLength;
|
||
|
|
||
|
if (DBInfo->Ports) {
|
||
|
newPortsLength = NumberPorts / BITS_INA_BYTE;
|
||
|
newPorts = (PBYTE) malloc(newPortsLength * sizeof(BYTE));
|
||
|
|
||
|
if (newPorts) {
|
||
|
memcpy(newPorts, DBInfo->Ports, DBInfo->PortsLength);
|
||
|
free(DBInfo->Ports);
|
||
|
DBInfo->Ports = newPorts;
|
||
|
DBInfo->PortsLength = newPortsLength;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
else {
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
//
|
||
|
// Just alloc and be done with it
|
||
|
//
|
||
|
DBInfo->PortsLength = NumberPorts / BITS_INA_BYTE;
|
||
|
DBInfo->Ports = (PBYTE) malloc(DBInfo->PortsLength * sizeof(BYTE));
|
||
|
|
||
|
return DBInfo->Ports ? TRUE : FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LONG
|
||
|
WINAPI
|
||
|
ComDBOpen (
|
||
|
PHCOMDB PHComDB
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Opens name data base, and returns a handle to be used in future calls.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
INVALID_HANDLE_VALUE if the call fails, otherwise a valid handle
|
||
|
|
||
|
If INVALID_HANDLE_VALUE, call GetLastError() to get details (??)
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PDB_INFO dbInfo = malloc(sizeof(DB_INFO));
|
||
|
DWORD type, size, disposition = 0x0;
|
||
|
BOOLEAN migrated = FALSE;
|
||
|
LONG res;
|
||
|
BYTE merge[COMDB_MIN_PORTS_ARBITRATED / BITS_INA_BYTE /* 32 */];
|
||
|
|
||
|
if (dbInfo == 0) {
|
||
|
*PHComDB = (HCOMDB) INVALID_HANDLE_VALUE;
|
||
|
return ERROR_ACCESS_DENIED;
|
||
|
}
|
||
|
|
||
|
dbInfo->AccessMutex = CreateMutex(NULL, FALSE, szMutexName);
|
||
|
|
||
|
if (dbInfo->AccessMutex == 0) {
|
||
|
return CreationFailure(PHComDB, dbInfo);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Enter the mutex so we can guarantee only one thread pounding on the reg
|
||
|
// key at once
|
||
|
//
|
||
|
WaitForSingleObject(dbInfo->AccessMutex, INFINITE);
|
||
|
|
||
|
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
|
||
|
szComDBPath,
|
||
|
0,
|
||
|
(TCHAR *) NULL,
|
||
|
REG_OPTION_NON_VOLATILE,
|
||
|
KEY_ALL_ACCESS | KEY_NOTIFY,
|
||
|
(LPSECURITY_ATTRIBUTES) NULL,
|
||
|
&dbInfo->DBKey,
|
||
|
&disposition) != ERROR_SUCCESS) {
|
||
|
//
|
||
|
// Try again w/out notification caps
|
||
|
//
|
||
|
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
|
||
|
szComDBPath,
|
||
|
0,
|
||
|
(TCHAR *) NULL,
|
||
|
REG_OPTION_NON_VOLATILE,
|
||
|
KEY_ALL_ACCESS,
|
||
|
(LPSECURITY_ATTRIBUTES) NULL,
|
||
|
&dbInfo->DBKey,
|
||
|
&disposition) != ERROR_SUCCESS) {
|
||
|
return CreationFailure(PHComDB, dbInfo);
|
||
|
}
|
||
|
|
||
|
dbInfo->RegChangedEvent = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
else {
|
||
|
dbInfo->RegChangedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||
|
|
||
|
if (dbInfo->RegChangedEvent == 0) {
|
||
|
dbInfo->RegChangedEvent = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (disposition == REG_CREATED_NEW_KEY) {
|
||
|
//
|
||
|
// Must migrate the previous values from the old com db path
|
||
|
//
|
||
|
HKEY hOldDB;
|
||
|
|
||
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||
|
szComDBPathOld,
|
||
|
0,
|
||
|
KEY_ALL_ACCESS,
|
||
|
&hOldDB) == ERROR_SUCCESS &&
|
||
|
RegQueryValueEx(hOldDB,
|
||
|
szComDBName,
|
||
|
0,
|
||
|
&type,
|
||
|
NULL,
|
||
|
&dbInfo->PortsLength) == ERROR_SUCCESS) {
|
||
|
|
||
|
//
|
||
|
// The old value is still there, get its contents, copy it to the
|
||
|
// new location and delete the old value
|
||
|
//
|
||
|
migrated = TRUE;
|
||
|
ResizeDatabase(dbInfo, dbInfo->PortsLength * BITS_INA_BYTE);
|
||
|
|
||
|
size = dbInfo->PortsLength;
|
||
|
|
||
|
res = RegQueryValueEx(hOldDB,
|
||
|
szComDBName,
|
||
|
0,
|
||
|
&type,
|
||
|
(PBYTE) dbInfo->Ports,
|
||
|
&size);
|
||
|
|
||
|
RegDeleteValue(hOldDB, szComDBName);
|
||
|
|
||
|
//
|
||
|
// The value does not exist, write it out
|
||
|
//
|
||
|
if (RegSetValueEx(dbInfo->DBKey,
|
||
|
szComDBName,
|
||
|
0,
|
||
|
REG_BINARY,
|
||
|
dbInfo->Ports,
|
||
|
dbInfo->PortsLength) != ERROR_SUCCESS) {
|
||
|
|
||
|
RegCloseKey(hOldDB);
|
||
|
return CreationFailure(PHComDB, dbInfo);
|
||
|
}
|
||
|
|
||
|
RegCloseKey(hOldDB);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If we haven't migrated values from the old path, then either create a
|
||
|
// new chunk or read in values previously written
|
||
|
//
|
||
|
if (!migrated) {
|
||
|
res = RegQueryValueEx(dbInfo->DBKey,
|
||
|
szComDBName,
|
||
|
0,
|
||
|
&type,
|
||
|
NULL,
|
||
|
&dbInfo->PortsLength);
|
||
|
|
||
|
if (res == ERROR_FILE_NOT_FOUND) {
|
||
|
ResizeDatabase(dbInfo, COMDB_MIN_PORTS_ARBITRATED);
|
||
|
|
||
|
//
|
||
|
// The value does not exist, write it out
|
||
|
//
|
||
|
res = RegSetValueEx(dbInfo->DBKey,
|
||
|
szComDBName,
|
||
|
0,
|
||
|
REG_BINARY,
|
||
|
dbInfo->Ports,
|
||
|
dbInfo->PortsLength);
|
||
|
|
||
|
if (res != ERROR_SUCCESS) {
|
||
|
return CreationFailure(PHComDB, dbInfo);
|
||
|
}
|
||
|
}
|
||
|
else if (res == ERROR_MORE_DATA || res != ERROR_SUCCESS || type != REG_BINARY) {
|
||
|
return CreationFailure(PHComDB, dbInfo);
|
||
|
}
|
||
|
else if (res == ERROR_SUCCESS) {
|
||
|
ResizeDatabase(dbInfo, dbInfo->PortsLength * BITS_INA_BYTE);
|
||
|
|
||
|
size = dbInfo->PortsLength;
|
||
|
res = RegQueryValueEx(dbInfo->DBKey,
|
||
|
szComDBName,
|
||
|
0,
|
||
|
&type,
|
||
|
(PBYTE) dbInfo->Ports,
|
||
|
&size);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
size = sizeof(merge);
|
||
|
if (RegQueryValueEx(dbInfo->DBKey,
|
||
|
szComDBMerge,
|
||
|
0,
|
||
|
&type,
|
||
|
(PBYTE) merge,
|
||
|
&size) == ERROR_SUCCESS &&
|
||
|
size <= dbInfo->PortsLength) {
|
||
|
|
||
|
int i;
|
||
|
|
||
|
for (i = 0 ; i < COMDB_MIN_PORTS_ARBITRATED / BITS_INA_BYTE; i++) {
|
||
|
dbInfo->Ports[i] |= merge[i];
|
||
|
}
|
||
|
|
||
|
RegDeleteValue(dbInfo->DBKey, szComDBMerge);
|
||
|
|
||
|
RegSetValueEx(dbInfo->DBKey,
|
||
|
szComDBName,
|
||
|
0,
|
||
|
REG_BINARY,
|
||
|
dbInfo->Ports,
|
||
|
dbInfo->PortsLength);
|
||
|
}
|
||
|
|
||
|
if (dbInfo->RegChangedEvent != INVALID_HANDLE_VALUE) {
|
||
|
RegisterForNotification(dbInfo);
|
||
|
}
|
||
|
|
||
|
ReleaseMutex(dbInfo->AccessMutex);
|
||
|
|
||
|
//
|
||
|
// All done! phew...
|
||
|
//
|
||
|
*PHComDB = (HCOMDB) dbInfo;
|
||
|
return ERROR_SUCCESS;
|
||
|
|
||
|
}
|
||
|
|
||
|
LONG
|
||
|
WINAPI
|
||
|
ComDBClose (
|
||
|
HCOMDB HComDB
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
frees a handle to the database returned from OpenComPortDataBase
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Handle returned from OpenComPortDataBase.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PDB_INFO dbInfo = HandleToDBInfo(HComDB);
|
||
|
|
||
|
SanityCheckDBInfo(dbInfo);
|
||
|
DestroyDBInfo(dbInfo);
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
EnterDB(
|
||
|
PDB_INFO DBInfo
|
||
|
)
|
||
|
{
|
||
|
BOOL eventSignalled = FALSE;
|
||
|
LONG res;
|
||
|
DWORD type, size;
|
||
|
|
||
|
WaitForSingleObject(DBInfo->AccessMutex, INFINITE);
|
||
|
|
||
|
if (DBInfo->RegChangedEvent == INVALID_HANDLE_VALUE ||
|
||
|
(eventSignalled = IsEventSignalled(DBInfo->RegChangedEvent))) {
|
||
|
|
||
|
size = 0;
|
||
|
res = RegQueryValueEx(DBInfo->DBKey,
|
||
|
szComDBName,
|
||
|
0,
|
||
|
&type,
|
||
|
0,
|
||
|
&size);
|
||
|
|
||
|
//
|
||
|
// Couldn't update the DB ... fail
|
||
|
//
|
||
|
if (res != ERROR_SUCCESS || type != REG_BINARY) {
|
||
|
ReleaseMutex(DBInfo->AccessMutex);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (size != DBInfo->PortsLength) {
|
||
|
ResizeDatabase(DBInfo, size * BITS_INA_BYTE);
|
||
|
}
|
||
|
|
||
|
RegQueryValueEx(DBInfo->DBKey,
|
||
|
szComDBName,
|
||
|
0,
|
||
|
&type,
|
||
|
DBInfo->Ports,
|
||
|
&size);
|
||
|
|
||
|
//
|
||
|
// Reregister the notification with the registry
|
||
|
//
|
||
|
if (eventSignalled) {
|
||
|
RegisterForNotification(DBInfo);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
LONG
|
||
|
LeaveDB(
|
||
|
PDB_INFO DBInfo,
|
||
|
BOOL CommitChanges
|
||
|
)
|
||
|
{
|
||
|
LONG retVal = ERROR_SUCCESS;
|
||
|
|
||
|
if (CommitChanges) {
|
||
|
if (RegSetValueEx(DBInfo->DBKey,
|
||
|
szComDBName,
|
||
|
0,
|
||
|
REG_BINARY,
|
||
|
DBInfo->Ports,
|
||
|
DBInfo->PortsLength) != ERROR_SUCCESS) {
|
||
|
retVal = ERROR_CANTWRITE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// The setting of the value in the reg signals the event...but we don't
|
||
|
// need to resync w/the reg off of this change b/c it is our own! Instead
|
||
|
// reset the event and rereg for the event
|
||
|
//
|
||
|
if (DBInfo->RegChangedEvent != INVALID_HANDLE_VALUE) {
|
||
|
RegisterForNotification(DBInfo);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ReleaseMutex(DBInfo->AccessMutex);
|
||
|
return retVal;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
GetByteAndMask(
|
||
|
PDB_INFO DBInfo,
|
||
|
DWORD ComNumber,
|
||
|
PBYTE *Byte,
|
||
|
PBYTE Mask
|
||
|
)
|
||
|
{
|
||
|
ComNumber--;
|
||
|
*Byte = DBInfo->Ports + (ComNumber / BITS_INA_BYTE);
|
||
|
*Mask = 1 << (ComNumber % BITS_INA_BYTE);
|
||
|
}
|
||
|
|
||
|
LONG
|
||
|
WINAPI
|
||
|
ComDBGetCurrentPortUsage (
|
||
|
HCOMDB HComDB,
|
||
|
PBYTE Buffer,
|
||
|
DWORD BufferSize,
|
||
|
ULONG ReportType,
|
||
|
LPDWORD MaxPortsReported
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Handle requests that require no synch w/DB first.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PDB_INFO dbInfo = HandleToDBInfo(HComDB);
|
||
|
PBYTE curSrc, curDest, endDest;
|
||
|
BYTE mask;
|
||
|
|
||
|
SanityCheckDBInfo(dbInfo);
|
||
|
|
||
|
if (!EnterDB(dbInfo)) {
|
||
|
return ERROR_NOT_CONNECTED;
|
||
|
}
|
||
|
|
||
|
if (Buffer == 0) {
|
||
|
if (!MaxPortsReported) {
|
||
|
LeaveDB(dbInfo, FALSE);
|
||
|
return ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
else {
|
||
|
*MaxPortsReported = dbInfo->PortsLength * BITS_INA_BYTE;
|
||
|
return LeaveDB(dbInfo, FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ReportType == CDB_REPORT_BITS) {
|
||
|
if (BufferSize > dbInfo->PortsLength) {
|
||
|
BufferSize = dbInfo->PortsLength;
|
||
|
}
|
||
|
memcpy(Buffer, dbInfo->Ports, BufferSize);
|
||
|
if (MaxPortsReported) {
|
||
|
*MaxPortsReported = BufferSize * BITS_INA_BYTE;
|
||
|
}
|
||
|
}
|
||
|
else if (ReportType == CDB_REPORT_BYTES) {
|
||
|
if (BufferSize > dbInfo->PortsLength * BITS_INA_BYTE) {
|
||
|
BufferSize = dbInfo->PortsLength * BITS_INA_BYTE;
|
||
|
}
|
||
|
|
||
|
curSrc = dbInfo->Ports;
|
||
|
endDest = Buffer + BufferSize;
|
||
|
curDest = Buffer;
|
||
|
|
||
|
for (mask = 1; curDest != endDest; curDest++) {
|
||
|
*curDest = (*curSrc & mask) ? 1 : 0;
|
||
|
if (mask & 0x80) {
|
||
|
mask = 0x1;
|
||
|
curSrc++;
|
||
|
}
|
||
|
else
|
||
|
mask <<= 1;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
LeaveDB(dbInfo, FALSE);
|
||
|
return ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
return LeaveDB(dbInfo, FALSE);
|
||
|
}
|
||
|
|
||
|
LONG
|
||
|
WINAPI
|
||
|
ComDBClaimNextFreePort (
|
||
|
HCOMDB HComDB,
|
||
|
LPDWORD ComNumber
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
returns the first free COMx value
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Handle returned from OpenComPortDataBase.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
|
||
|
returns ERROR_SUCCESS if successful. or other ERROR_ if not
|
||
|
|
||
|
if successful, then ComNumber will be that next free com value and claims it in the database
|
||
|
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PDB_INFO dbInfo = HandleToDBInfo(HComDB);
|
||
|
DWORD num;
|
||
|
BOOL commit = FALSE;
|
||
|
PBYTE curSrc, srcEnd;
|
||
|
BYTE mask;
|
||
|
LONG ret;
|
||
|
|
||
|
SanityCheckDBInfo(dbInfo);
|
||
|
|
||
|
if (!EnterDB(dbInfo)) {
|
||
|
return ERROR_NOT_CONNECTED;
|
||
|
}
|
||
|
|
||
|
curSrc = dbInfo->Ports;
|
||
|
srcEnd = curSrc + dbInfo->PortsLength;
|
||
|
|
||
|
for (num = 3, mask = 0x4; curSrc != srcEnd; num++) {
|
||
|
if (!(*curSrc & mask)) {
|
||
|
*ComNumber = num;
|
||
|
*curSrc |= mask;
|
||
|
commit = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
else if (mask & 0x80) {
|
||
|
mask = 0x1;
|
||
|
curSrc++;
|
||
|
}
|
||
|
else {
|
||
|
mask <<= 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (curSrc == srcEnd && !commit && num < COMDB_MAX_PORTS_ARBITRATED) {
|
||
|
// DB entirely full
|
||
|
ResizeDatabase(dbInfo, ((num / GROWTH_VALUE) + 1) * GROWTH_VALUE);
|
||
|
*ComNumber = num;
|
||
|
|
||
|
GetByteAndMask(dbInfo, num, &curSrc, &mask);
|
||
|
*curSrc |= mask;
|
||
|
commit = TRUE;
|
||
|
}
|
||
|
|
||
|
ret = LeaveDB(dbInfo, commit);
|
||
|
if (!commit) {
|
||
|
ret = ERROR_NO_LOG_SPACE;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
LONG
|
||
|
WINAPI
|
||
|
ComDBClaimPort (
|
||
|
HCOMDB HComDB,
|
||
|
DWORD ComNumber,
|
||
|
BOOL ForceClaim,
|
||
|
PBOOL Forced
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Attempts to claim a com name in the database
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DataBaseHandle - returned from OpenComPortDataBase.
|
||
|
|
||
|
ComNumber - The port value to be claimed
|
||
|
|
||
|
Force - If TRUE, will force the port to be claimed even if in use already
|
||
|
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
|
||
|
returns ERROR_SUCCESS if port name was not already claimed, or if it was claimed
|
||
|
and Force was TRUE.
|
||
|
|
||
|
ERROR_SHARING_VIOLATION if port name is use and Force is false
|
||
|
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PDB_INFO dbInfo = HandleToDBInfo(HComDB);
|
||
|
PBYTE curByte;
|
||
|
BYTE mask;
|
||
|
BOOL commit = TRUE;
|
||
|
LONG res;
|
||
|
ULONG newSize;
|
||
|
|
||
|
BOOL f;
|
||
|
if (!(Forced)) {
|
||
|
Forced = &f;
|
||
|
}
|
||
|
SanityCheckComNumber(ComNumber);
|
||
|
SanityCheckDBInfo(dbInfo);
|
||
|
|
||
|
if (!EnterDB(dbInfo)) {
|
||
|
return ERROR_NOT_CONNECTED;
|
||
|
}
|
||
|
|
||
|
if (ComNumber > dbInfo->PortsLength * BITS_INA_BYTE) {
|
||
|
ResizeDatabase(dbInfo, ((ComNumber / GROWTH_VALUE) + 1) * GROWTH_VALUE);
|
||
|
}
|
||
|
|
||
|
GetByteAndMask(dbInfo, ComNumber, &curByte, &mask);
|
||
|
|
||
|
if (*curByte & mask) {
|
||
|
commit = FALSE;
|
||
|
if (ForceClaim) {
|
||
|
if (Forced)
|
||
|
*Forced = TRUE;
|
||
|
}
|
||
|
else {
|
||
|
res = LeaveDB(dbInfo, commit);
|
||
|
if (res == ERROR_SUCCESS) {
|
||
|
return ERROR_SHARING_VIOLATION;
|
||
|
}
|
||
|
else {
|
||
|
return res;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (Forced)
|
||
|
*Forced = FALSE;
|
||
|
*curByte |= mask;
|
||
|
}
|
||
|
|
||
|
return LeaveDB(dbInfo, commit);
|
||
|
}
|
||
|
|
||
|
LONG
|
||
|
WINAPI
|
||
|
ComDBReleasePort (
|
||
|
HCOMDB HComDB,
|
||
|
DWORD ComNumber
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
un-claims the port in the database
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DatabaseHandle - returned from OpenComPortDataBase.
|
||
|
|
||
|
ComNumber - port to be unclaimed in database
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
|
||
|
returns ERROR_SUCCESS if successful. or other ERROR_ if not
|
||
|
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PDB_INFO dbInfo = HandleToDBInfo(HComDB);
|
||
|
PBYTE byte;
|
||
|
BYTE mask;
|
||
|
|
||
|
SanityCheckDBInfo(dbInfo);
|
||
|
|
||
|
if (!EnterDB(dbInfo)) {
|
||
|
return ERROR_NOT_CONNECTED;
|
||
|
}
|
||
|
|
||
|
if (ComNumber > dbInfo->PortsLength * BITS_INA_BYTE) {
|
||
|
LeaveDB(dbInfo, FALSE);
|
||
|
return ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
GetByteAndMask(dbInfo, ComNumber, &byte, &mask);
|
||
|
*byte &= ~mask;
|
||
|
|
||
|
return LeaveDB(dbInfo, TRUE);
|
||
|
}
|
||
|
|
||
|
LONG
|
||
|
WINAPI
|
||
|
ComDBResizeDatabase (
|
||
|
HCOMDB HComDB,
|
||
|
DWORD NewSize
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Resizes the database to the new size. To get the current size, call
|
||
|
ComDBGetCurrentPortUsage with a Buffer == NULL.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DatabaseHandle - returned from OpenComPortDataBase.
|
||
|
|
||
|
NewSize - must be a multiple of 1024, with a max of 4096
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
returns ERROR_SUCCESS if successful
|
||
|
ERROR_BAD_LENGTH if NewSize is not greater than the current size or
|
||
|
NewSize is greater than COMDB_MAX_PORTS_ARBITRATED
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PDB_INFO dbInfo = HandleToDBInfo(HComDB);
|
||
|
BOOL commit = FALSE;
|
||
|
|
||
|
SanityCheckDBInfo(dbInfo);
|
||
|
|
||
|
if (NewSize % GROWTH_VALUE) {
|
||
|
return ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
if (!EnterDB(dbInfo)) {
|
||
|
return ERROR_NOT_CONNECTED;
|
||
|
}
|
||
|
|
||
|
if (NewSize > COMDB_MAX_PORTS_ARBITRATED ||
|
||
|
dbInfo->PortsLength * BITS_INA_BYTE >= NewSize) {
|
||
|
LeaveDB(dbInfo, FALSE);
|
||
|
return ERROR_BAD_LENGTH;
|
||
|
}
|
||
|
|
||
|
ResizeDatabase(dbInfo, NewSize);
|
||
|
|
||
|
return LeaveDB(dbInfo, TRUE);
|
||
|
}
|
||
|
|