mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
666 lines
17 KiB
C
666 lines
17 KiB
C
/*
|
|
* PROJECT: Ports installer library
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: dll\win32\msports\comdb.c
|
|
* PURPOSE: COM port database
|
|
* COPYRIGHT: Copyright 2011 Eric Kohl
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#define BITS_PER_BYTE 8
|
|
#define BITMAP_SIZE_INCREMENT 0x400
|
|
#define BITMAP_SIZE_INVALID_BITS 0x3FF
|
|
|
|
typedef struct _COMDB
|
|
{
|
|
HANDLE hMutex;
|
|
HKEY hKey;
|
|
} COMDB, *PCOMDB;
|
|
|
|
|
|
LONG
|
|
WINAPI
|
|
ComDBClaimNextFreePort(IN HCOMDB hComDB,
|
|
OUT LPDWORD ComNumber)
|
|
{
|
|
PCOMDB pComDB;
|
|
DWORD dwBitIndex;
|
|
DWORD dwByteIndex;
|
|
DWORD dwSize;
|
|
DWORD dwType;
|
|
PBYTE pBitmap = NULL;
|
|
BYTE cMask;
|
|
LONG lError;
|
|
|
|
TRACE("ComDBClaimNextFreePort(%p %p)\n", hComDB, ComNumber);
|
|
|
|
if (hComDB == INVALID_HANDLE_VALUE ||
|
|
hComDB == NULL ||
|
|
ComNumber == NULL)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
pComDB = (PCOMDB)hComDB;
|
|
|
|
/* Wait for the mutex */
|
|
WaitForSingleObject(pComDB->hMutex, INFINITE);
|
|
|
|
/* Get the required bitmap size */
|
|
lError = RegQueryValueExW(pComDB->hKey,
|
|
L"ComDB",
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwSize);
|
|
if (lError != ERROR_SUCCESS)
|
|
{
|
|
ERR("Failed to query the bitmap size!\n");
|
|
goto done;
|
|
}
|
|
|
|
/* Allocate the bitmap */
|
|
pBitmap = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
dwSize);
|
|
if (pBitmap == NULL)
|
|
{
|
|
ERR("Failed to allocate the bitmap!\n");
|
|
lError = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto done;
|
|
}
|
|
|
|
/* Read the bitmap */
|
|
lError = RegQueryValueExW(pComDB->hKey,
|
|
L"ComDB",
|
|
NULL,
|
|
&dwType,
|
|
pBitmap,
|
|
&dwSize);
|
|
if (lError != ERROR_SUCCESS)
|
|
goto done;
|
|
|
|
lError = ERROR_INVALID_PARAMETER;
|
|
for (dwBitIndex = 0; dwBitIndex < (dwSize * BITS_PER_BYTE); dwBitIndex++)
|
|
{
|
|
/* Calculate the byte index and a mask for the affected bit */
|
|
dwByteIndex = dwBitIndex / BITS_PER_BYTE;
|
|
cMask = 1 << (dwBitIndex % BITS_PER_BYTE);
|
|
|
|
if ((pBitmap[dwByteIndex] & cMask) == 0)
|
|
{
|
|
pBitmap[dwByteIndex] |= cMask;
|
|
*ComNumber = dwBitIndex + 1;
|
|
lError = ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Save the bitmap if it was modified */
|
|
if (lError == ERROR_SUCCESS)
|
|
{
|
|
lError = RegSetValueExW(pComDB->hKey,
|
|
L"ComDB",
|
|
0,
|
|
REG_BINARY,
|
|
pBitmap,
|
|
dwSize);
|
|
}
|
|
|
|
done:;
|
|
/* Release the mutex */
|
|
ReleaseMutex(pComDB->hMutex);
|
|
|
|
/* Release the bitmap */
|
|
if (pBitmap != NULL)
|
|
HeapFree(GetProcessHeap(), 0, pBitmap);
|
|
|
|
return lError;
|
|
}
|
|
|
|
|
|
LONG
|
|
WINAPI
|
|
ComDBClaimPort(IN HCOMDB hComDB,
|
|
IN DWORD ComNumber,
|
|
IN BOOL ForceClaim,
|
|
OUT PBOOL Forced)
|
|
{
|
|
PCOMDB pComDB;
|
|
DWORD dwBitIndex;
|
|
DWORD dwByteIndex;
|
|
DWORD dwType;
|
|
DWORD dwSize;
|
|
PBYTE pBitmap = NULL;
|
|
BYTE cMask;
|
|
LONG lError;
|
|
|
|
TRACE("ComDBClaimPort(%p %lu)\n", hComDB, ComNumber);
|
|
|
|
if (hComDB == INVALID_HANDLE_VALUE ||
|
|
hComDB == NULL ||
|
|
ComNumber == 0 ||
|
|
ComNumber > COMDB_MAX_PORTS_ARBITRATED)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
pComDB = (PCOMDB)hComDB;
|
|
|
|
/* Wait for the mutex */
|
|
WaitForSingleObject(pComDB->hMutex, INFINITE);
|
|
|
|
/* Get the required bitmap size */
|
|
lError = RegQueryValueExW(pComDB->hKey,
|
|
L"ComDB",
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwSize);
|
|
if (lError != ERROR_SUCCESS)
|
|
{
|
|
ERR("Failed to query the bitmap size!\n");
|
|
goto done;
|
|
}
|
|
|
|
/* Allocate the bitmap */
|
|
pBitmap = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
dwSize);
|
|
if (pBitmap == NULL)
|
|
{
|
|
ERR("Failed to allocate the bitmap!\n");
|
|
lError = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto done;
|
|
}
|
|
|
|
/* Read the bitmap */
|
|
lError = RegQueryValueExW(pComDB->hKey,
|
|
L"ComDB",
|
|
NULL,
|
|
&dwType,
|
|
pBitmap,
|
|
&dwSize);
|
|
if (lError != ERROR_SUCCESS)
|
|
goto done;
|
|
|
|
/* Get the bit index */
|
|
dwBitIndex = ComNumber - 1;
|
|
|
|
/* Check if the bit to set fits into the bitmap */
|
|
if (dwBitIndex >= (dwSize * BITS_PER_BYTE))
|
|
{
|
|
FIXME("Resize the bitmap\n");
|
|
|
|
lError = ERROR_INVALID_PARAMETER;
|
|
goto done;
|
|
}
|
|
|
|
/* Calculate the byte index and a mask for the affected bit */
|
|
dwByteIndex = dwBitIndex / BITS_PER_BYTE;
|
|
cMask = 1 << (dwBitIndex % BITS_PER_BYTE);
|
|
|
|
lError = ERROR_SHARING_VIOLATION;
|
|
|
|
/* Check if the bit is not set */
|
|
if ((pBitmap[dwByteIndex] & cMask) == 0)
|
|
{
|
|
/* Set the bit */
|
|
pBitmap[dwByteIndex] |= cMask;
|
|
lError = ERROR_SUCCESS;
|
|
}
|
|
|
|
/* Save the bitmap if it was modified */
|
|
if (lError == ERROR_SUCCESS)
|
|
{
|
|
lError = RegSetValueExW(pComDB->hKey,
|
|
L"ComDB",
|
|
0,
|
|
REG_BINARY,
|
|
pBitmap,
|
|
dwSize);
|
|
}
|
|
|
|
done:
|
|
/* Release the mutex */
|
|
ReleaseMutex(pComDB->hMutex);
|
|
|
|
/* Release the bitmap */
|
|
if (pBitmap != NULL)
|
|
HeapFree(GetProcessHeap(), 0, pBitmap);
|
|
|
|
return lError;
|
|
}
|
|
|
|
|
|
LONG
|
|
WINAPI
|
|
ComDBClose(IN HCOMDB hComDB)
|
|
{
|
|
PCOMDB pComDB;
|
|
|
|
TRACE("ComDBClose(%p)\n", hComDB);
|
|
|
|
if (hComDB == HCOMDB_INVALID_HANDLE_VALUE ||
|
|
hComDB == NULL)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
pComDB = (PCOMDB)hComDB;
|
|
|
|
/* Close the registry key */
|
|
if (pComDB->hKey != NULL)
|
|
RegCloseKey(pComDB->hKey);
|
|
|
|
/* Close the mutex */
|
|
if (pComDB->hMutex != NULL)
|
|
CloseHandle(pComDB->hMutex);
|
|
|
|
/* Release the database */
|
|
HeapFree(GetProcessHeap(), 0, pComDB);
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
LONG
|
|
WINAPI
|
|
ComDBGetCurrentPortUsage(IN HCOMDB hComDB,
|
|
OUT PBYTE Buffer,
|
|
IN DWORD BufferSize,
|
|
IN DWORD ReportType,
|
|
OUT LPDWORD MaxPortsReported)
|
|
{
|
|
PCOMDB pComDB;
|
|
DWORD dwBitIndex;
|
|
DWORD dwByteIndex;
|
|
DWORD dwType;
|
|
DWORD dwSize;
|
|
PBYTE pBitmap = NULL;
|
|
BYTE cMask;
|
|
LONG lError = ERROR_SUCCESS;
|
|
|
|
TRACE("ComDBGetCurrentPortUsage(%p %p %lu %lu %p)\n",
|
|
hComDB, Buffer, BufferSize, ReportType, MaxPortsReported);
|
|
|
|
if (hComDB == INVALID_HANDLE_VALUE ||
|
|
hComDB == NULL ||
|
|
(Buffer == NULL && MaxPortsReported == NULL) ||
|
|
(ReportType != CDB_REPORT_BITS && ReportType != CDB_REPORT_BYTES))
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
pComDB = (PCOMDB)hComDB;
|
|
|
|
/* Wait for the mutex */
|
|
WaitForSingleObject(pComDB->hMutex, INFINITE);
|
|
|
|
/* Get the required bitmap size */
|
|
lError = RegQueryValueExW(pComDB->hKey,
|
|
L"ComDB",
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwSize);
|
|
if (lError != ERROR_SUCCESS)
|
|
{
|
|
ERR("Failed to query the bitmap size!\n");
|
|
goto done;
|
|
}
|
|
|
|
/* Allocate the bitmap */
|
|
pBitmap = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
dwSize);
|
|
if (pBitmap == NULL)
|
|
{
|
|
ERR("Failed to allocate the bitmap!\n");
|
|
lError = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto done;
|
|
}
|
|
|
|
/* Read the bitmap */
|
|
lError = RegQueryValueExW(pComDB->hKey,
|
|
L"ComDB",
|
|
NULL,
|
|
&dwType,
|
|
pBitmap,
|
|
&dwSize);
|
|
if (lError != ERROR_SUCCESS)
|
|
goto done;
|
|
|
|
if (Buffer == NULL)
|
|
{
|
|
*MaxPortsReported = dwSize * BITS_PER_BYTE;
|
|
}
|
|
else
|
|
{
|
|
if (ReportType == CDB_REPORT_BITS)
|
|
{
|
|
/* Clear the buffer */
|
|
memset(Buffer, 0, BufferSize);
|
|
|
|
memcpy(Buffer,
|
|
pBitmap,
|
|
min(dwSize, BufferSize));
|
|
|
|
if (MaxPortsReported != NULL)
|
|
*MaxPortsReported = min(dwSize, BufferSize) * BITS_PER_BYTE;
|
|
}
|
|
else if (ReportType == CDB_REPORT_BYTES)
|
|
{
|
|
/* Clear the buffer */
|
|
memset(Buffer, 0, BufferSize);
|
|
|
|
for (dwBitIndex = 0; dwBitIndex < min(dwSize * BITS_PER_BYTE, BufferSize); dwBitIndex++)
|
|
{
|
|
/* Calculate the byte index and a mask for the affected bit */
|
|
dwByteIndex = dwBitIndex / BITS_PER_BYTE;
|
|
cMask = 1 << (dwBitIndex % BITS_PER_BYTE);
|
|
|
|
if ((pBitmap[dwByteIndex] & cMask) != 0)
|
|
Buffer[dwBitIndex] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
done:;
|
|
/* Release the mutex */
|
|
ReleaseMutex(pComDB->hMutex);
|
|
|
|
/* Release the bitmap */
|
|
HeapFree(GetProcessHeap(), 0, pBitmap);
|
|
|
|
return lError;
|
|
}
|
|
|
|
|
|
LONG
|
|
WINAPI
|
|
ComDBOpen(OUT HCOMDB *phComDB)
|
|
{
|
|
PCOMDB pComDB;
|
|
DWORD dwDisposition;
|
|
DWORD dwType;
|
|
DWORD dwSize;
|
|
PBYTE pBitmap;
|
|
LONG lError;
|
|
|
|
TRACE("ComDBOpen(%p)\n", phComDB);
|
|
|
|
/* Allocate a new database */
|
|
pComDB = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(COMDB));
|
|
if (pComDB == NULL)
|
|
{
|
|
ERR("Failed to allocate the database!\n");
|
|
*phComDB = HCOMDB_INVALID_HANDLE_VALUE;
|
|
return ERROR_ACCESS_DENIED;
|
|
}
|
|
|
|
/* Create a mutex to protect the database */
|
|
pComDB->hMutex = CreateMutexW(NULL,
|
|
FALSE,
|
|
L"ComDBMutex");
|
|
if (pComDB->hMutex == NULL)
|
|
{
|
|
ERR("Failed to create the mutex!\n");
|
|
HeapFree(GetProcessHeap(), 0, pComDB);
|
|
*phComDB = HCOMDB_INVALID_HANDLE_VALUE;
|
|
return ERROR_ACCESS_DENIED;
|
|
}
|
|
|
|
/* Wait for the mutex */
|
|
WaitForSingleObject(pComDB->hMutex, INFINITE);
|
|
|
|
/* Create or open the database key */
|
|
lError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
|
|
L"System\\CurrentControlSet\\Control\\COM Name Arbiter",
|
|
0,
|
|
NULL,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&pComDB->hKey,
|
|
&dwDisposition);
|
|
if (lError != ERROR_SUCCESS)
|
|
goto done;
|
|
|
|
/* Get the required bitmap size */
|
|
lError = RegQueryValueExW(pComDB->hKey,
|
|
L"ComDB",
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwSize);
|
|
if (lError == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
/* Allocate a new bitmap */
|
|
dwSize = COMDB_MIN_PORTS_ARBITRATED / BITS_PER_BYTE;
|
|
pBitmap = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
dwSize);
|
|
if (pBitmap == NULL)
|
|
{
|
|
ERR("Failed to allocate the bitmap!\n");
|
|
lError = ERROR_ACCESS_DENIED;
|
|
goto done;
|
|
}
|
|
|
|
/* Write the bitmap to the registry */
|
|
lError = RegSetValueExW(pComDB->hKey,
|
|
L"ComDB",
|
|
0,
|
|
REG_BINARY,
|
|
pBitmap,
|
|
dwSize);
|
|
|
|
HeapFree(GetProcessHeap(), 0, pBitmap);
|
|
}
|
|
|
|
done:;
|
|
/* Release the mutex */
|
|
ReleaseMutex(pComDB->hMutex);
|
|
|
|
if (lError != ERROR_SUCCESS)
|
|
{
|
|
/* Clean up in case of failure */
|
|
if (pComDB->hKey != NULL)
|
|
RegCloseKey(pComDB->hKey);
|
|
|
|
if (pComDB->hMutex != NULL)
|
|
CloseHandle(pComDB->hMutex);
|
|
|
|
HeapFree(GetProcessHeap(), 0, pComDB);
|
|
|
|
*phComDB = HCOMDB_INVALID_HANDLE_VALUE;
|
|
}
|
|
else
|
|
{
|
|
/* Return the database handle */
|
|
*phComDB = (HCOMDB)pComDB;
|
|
}
|
|
|
|
TRACE("done (Error %lu)\n", lError);
|
|
|
|
return lError;
|
|
}
|
|
|
|
|
|
LONG
|
|
WINAPI
|
|
ComDBReleasePort(IN HCOMDB hComDB,
|
|
IN DWORD ComNumber)
|
|
{
|
|
PCOMDB pComDB;
|
|
DWORD dwByteIndex;
|
|
DWORD dwBitIndex;
|
|
DWORD dwType;
|
|
DWORD dwSize;
|
|
PBYTE pBitmap = NULL;
|
|
BYTE cMask;
|
|
LONG lError;
|
|
|
|
TRACE("ComDBReleasePort(%p %lu)\n", hComDB, ComNumber);
|
|
|
|
if (hComDB == INVALID_HANDLE_VALUE ||
|
|
ComNumber == 0 ||
|
|
ComNumber > COMDB_MAX_PORTS_ARBITRATED)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
pComDB = (PCOMDB)hComDB;
|
|
|
|
/* Wait for the mutex */
|
|
WaitForSingleObject(pComDB->hMutex, INFINITE);
|
|
|
|
/* Get the required bitmap size */
|
|
lError = RegQueryValueExW(pComDB->hKey,
|
|
L"ComDB",
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwSize);
|
|
if (lError != ERROR_SUCCESS)
|
|
{
|
|
ERR("Failed to query the bitmap size!\n");
|
|
goto done;
|
|
}
|
|
|
|
/* Allocate the bitmap */
|
|
pBitmap = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
dwSize);
|
|
if (pBitmap == NULL)
|
|
{
|
|
ERR("Failed to allocate the bitmap!\n");
|
|
lError = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto done;
|
|
}
|
|
|
|
/* Read the bitmap */
|
|
lError = RegQueryValueExW(pComDB->hKey,
|
|
L"ComDB",
|
|
NULL,
|
|
&dwType,
|
|
pBitmap,
|
|
&dwSize);
|
|
if (lError != ERROR_SUCCESS)
|
|
goto done;
|
|
|
|
/* Get the bit index */
|
|
dwBitIndex = ComNumber - 1;
|
|
|
|
/* Check if the bit to set fits into the bitmap */
|
|
if (dwBitIndex >= (dwSize * BITS_PER_BYTE))
|
|
{
|
|
lError = ERROR_INVALID_PARAMETER;
|
|
goto done;
|
|
}
|
|
|
|
/* Calculate the byte index and a mask for the affected bit */
|
|
dwByteIndex = dwBitIndex / BITS_PER_BYTE;
|
|
cMask = 1 << (dwBitIndex % BITS_PER_BYTE);
|
|
|
|
/* Release the port */
|
|
pBitmap[dwByteIndex] &= ~cMask;
|
|
|
|
lError = RegSetValueExW(pComDB->hKey,
|
|
L"ComDB",
|
|
0,
|
|
REG_BINARY,
|
|
pBitmap,
|
|
dwSize);
|
|
|
|
done:;
|
|
/* Release the mutex */
|
|
ReleaseMutex(pComDB->hMutex);
|
|
|
|
/* Release the bitmap */
|
|
if (pBitmap != NULL)
|
|
HeapFree(GetProcessHeap(), 0, pBitmap);
|
|
|
|
return lError;
|
|
}
|
|
|
|
|
|
LONG
|
|
WINAPI
|
|
ComDBResizeDatabase(IN HCOMDB hComDB,
|
|
IN DWORD NewSize)
|
|
{
|
|
PCOMDB pComDB;
|
|
PBYTE pBitmap = NULL;
|
|
DWORD dwSize;
|
|
DWORD dwNewSize;
|
|
DWORD dwType;
|
|
LONG lError;
|
|
|
|
TRACE("ComDBResizeDatabase(%p %lu)\n", hComDB, NewSize);
|
|
|
|
if (hComDB == INVALID_HANDLE_VALUE ||
|
|
hComDB == NULL ||
|
|
(NewSize & BITMAP_SIZE_INVALID_BITS))
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
pComDB = (PCOMDB)hComDB;
|
|
|
|
/* Wait for the mutex */
|
|
WaitForSingleObject(pComDB->hMutex, INFINITE);
|
|
|
|
/* Get the required bitmap size */
|
|
lError = RegQueryValueExW(pComDB->hKey,
|
|
L"ComDB",
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwSize);
|
|
if (lError != ERROR_SUCCESS)
|
|
goto done;
|
|
|
|
/* Check the size limits */
|
|
if (NewSize > COMDB_MAX_PORTS_ARBITRATED ||
|
|
NewSize <= dwSize * BITS_PER_BYTE)
|
|
{
|
|
lError = ERROR_BAD_LENGTH;
|
|
goto done;
|
|
}
|
|
|
|
/* Calculate the new bitmap size */
|
|
dwNewSize = NewSize / BITS_PER_BYTE;
|
|
|
|
/* Allocate the new bitmap */
|
|
pBitmap = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
dwSize);
|
|
if (pBitmap == NULL)
|
|
{
|
|
ERR("Failed to allocate the bitmap!\n");
|
|
lError = ERROR_ACCESS_DENIED;
|
|
goto done;
|
|
}
|
|
|
|
/* Read the current bitmap */
|
|
lError = RegQueryValueExW(pComDB->hKey,
|
|
L"ComDB",
|
|
NULL,
|
|
&dwType,
|
|
pBitmap,
|
|
&dwSize);
|
|
if (lError != ERROR_SUCCESS)
|
|
goto done;
|
|
|
|
/* Write the new bitmap */
|
|
lError = RegSetValueExW(pComDB->hKey,
|
|
L"ComDB",
|
|
0,
|
|
REG_BINARY,
|
|
pBitmap,
|
|
dwNewSize);
|
|
|
|
done:;
|
|
/* Release the mutex */
|
|
ReleaseMutex(pComDB->hMutex);
|
|
|
|
if (pBitmap != NULL)
|
|
HeapFree(GetProcessHeap(), 0, pBitmap);
|
|
|
|
return lError;
|
|
}
|
|
|
|
/* EOF */
|