diff --git a/reactos/dll/win32/msports/CMakeLists.txt b/reactos/dll/win32/msports/CMakeLists.txt index 0d002739877..8dfbd65f268 100644 --- a/reactos/dll/win32/msports/CMakeLists.txt +++ b/reactos/dll/win32/msports/CMakeLists.txt @@ -5,6 +5,7 @@ spec2def(msports.dll msports.spec) list(APPEND SOURCE classinst.c + comdb.c msports.c msports.rc ${CMAKE_CURRENT_BINARY_DIR}/msports_stubs.c diff --git a/reactos/dll/win32/msports/classinst.c b/reactos/dll/win32/msports/classinst.c index 8860639c384..4502d5f2ca8 100644 --- a/reactos/dll/win32/msports/classinst.c +++ b/reactos/dll/win32/msports/classinst.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -244,21 +245,33 @@ InstallSerialPort(IN HDEVINFO DeviceInfoSet, WCHAR szFriendlyName[256]; WCHAR szPortName[5]; DWORD dwPortNumber; + HCOMDB hComDB = HCOMDB_INVALID_HANDLE_VALUE; TRACE("InstallSerialPort(%p, %p)\n", DeviceInfoSet, DeviceInfoData); + /* Open the com port database */ + ComDBOpen(&hComDB); + dwPortNumber = GetSerialPortNumber(DeviceInfoSet, DeviceInfoData); if (dwPortNumber != 0) { swprintf(szPortName, L"COM%u", dwPortNumber); + + ComDBClaimPort(hComDB, + dwPortNumber, + FALSE, + NULL); } else { wcscpy(szPortName, L"COMx"); } + /* Close the com port database */ + if (hComDB != HCOMDB_INVALID_HANDLE_VALUE) + ComDBClose(hComDB); /* Install the device */ if (!SetupDiInstallDevice(DeviceInfoSet, diff --git a/reactos/dll/win32/msports/comdb.c b/reactos/dll/win32/msports/comdb.c new file mode 100644 index 00000000000..1555611e26b --- /dev/null +++ b/reactos/dll/win32/msports/comdb.c @@ -0,0 +1,217 @@ +/* + * 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 +#include + +#include + +WINE_DEFAULT_DEBUG_CHANNEL(msports); + +#define BITS_PER_BYTE 8 + +typedef struct _COMDB +{ + HKEY hKey; + DWORD dwSize; + PBYTE pBitmap; +} COMDB, *PCOMDB; + + +LONG +WINAPI +ComDBClaimPort(IN HCOMDB hComDB, + IN DWORD ComNumber, + IN BOOL ForceClaim, + OUT PBOOL Forced) +{ + PCOMDB pComDB; + PBYTE pByte; + BYTE cMask; + DWORD dwBitIndex; + DWORD dwType; + DWORD dwSize; + LONG lError; + + if (hComDB == INVALID_HANDLE_VALUE || + hComDB == NULL || + ComNumber == 0 || + ComNumber > COMDB_MAX_PORTS_ARBITRATED) + return ERROR_INVALID_PARAMETER; + + pComDB = (PCOMDB)hComDB; + + /* Update the bitmap */ + dwSize = pComDB->dwSize; + lError = RegQueryValueExW(pComDB->hKey, + L"ComDB", + NULL, + &dwType, + pComDB->pBitmap, + &dwSize); + if (lError != ERROR_SUCCESS) + return lError; + + /* Get the bit index */ + dwBitIndex = ComNumber - 1; + + /* Check if the bit to set fits into the bitmap */ + if (dwBitIndex >= (pComDB->dwSize * BITS_PER_BYTE)) + { + /* FIXME: Resize the bitmap */ + return ERROR_INVALID_PARAMETER; + } + + /* Get a pointer to the affected byte and calculate a mask for the affected bit */ + pByte = &(pComDB->pBitmap[dwBitIndex / BITS_PER_BYTE]); + cMask = 1 << (dwBitIndex % BITS_PER_BYTE); + + /* Check if the bit is not set */ + if ((*pByte & cMask) == 0) + { + /* Set the bit */ + *pByte |= cMask; + lError = ERROR_SUCCESS; + } + else + { + /* The bit is already set */ + lError = ERROR_SHARING_VIOLATION; + } + + /* Save the bitmap if it was modified */ + if (lError == ERROR_SUCCESS) + { + lError = RegSetValueExW(pComDB->hKey, + L"ComDB", + 0, + REG_BINARY, + pComDB->pData, + pComDB->dwSize); + } + + return lError; +} + + +LONG +WINAPI +ComDBClose(IN HCOMDB hComDB) +{ + PCOMDB pComDB; + + 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); + + /* Release the bitmap */ + if (pComDB->pBitmap != NULL) + HeapFree(GetProcessHeap(), 0, pComDB->pBitmap); + + /* Release the database */ + HeapFree(GetProcessHeap(), 0, pComDB); + + return ERROR_SUCCESS; +} + + +LONG +WINAPI +ComDBOpen(OUT HCOMDB *phComDB) +{ + PCOMDB pComDB; + DWORD dwDisposition; + DWORD dwType; + 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 allocaete the database!\n"); + return ERROR_ACCESS_DENIED; + } + + /* 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, + &pComDB->dwSize); + if (lError == ERROR_FILE_NOT_FOUND) + { + /* Allocate a new bitmap */ + pComDB->dwSize = COMDB_MIN_PORTS_ARBITRATED / BITS_PER_BYTE; + pComDB->pData = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + pComDB->dwSize); + if (pComDB->pData == NULL) + { + ERR("Failed to allocaete the bitmap!\n"); + lError = ERROR_ACCESS_DENIED; + goto done; + } + + /* Read the bitmap from the registry */ + lError = RegSetValueExW(pComDB->hKey, + L"ComDB", + 0, + REG_BINARY, + pComDB->pData, + pComDB->dwSize); + } + +done:; + if (lError != ERROR_SUCCESS) + { + /* Clean up in case of failure */ + if (pComDB->hKey != NULL) + RegCloseKey(pComDB->hKey); + + if (pComDB->pData != NULL) + HeapFree(GetProcessHeap(), 0, pComDB->pData); + + 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; +} + +/* EOF */ \ No newline at end of file diff --git a/reactos/dll/win32/msports/msports.rbuild b/reactos/dll/win32/msports/msports.rbuild index 6c19b29f2ed..cd4a3de1098 100644 --- a/reactos/dll/win32/msports/msports.rbuild +++ b/reactos/dll/win32/msports/msports.rbuild @@ -6,6 +6,7 @@ advapi32 setupapi classinst.c + comdb.c msports.c msports.rc diff --git a/reactos/dll/win32/msports/msports.spec b/reactos/dll/win32/msports/msports.spec index f2155b2fa94..f5672c8ba2b 100644 --- a/reactos/dll/win32/msports/msports.spec +++ b/reactos/dll/win32/msports/msports.spec @@ -1,8 +1,8 @@ @ stub ComDBClaimNextFreePort -@ stub ComDBClaimPort -@ stub ComDBClose +@ stdcall ComDBClaimPort(ptr long long ptr) +@ stdcall ComDBClose(ptr) @ stub ComDBGetCurrentPortUsage -@ stub ComDBOpen +@ stdcall ComDBOpen(ptr) @ stub ComDBReleasePort @ stub ComDBResizeDatabase @ stdcall LibMain(ptr long ptr) DllMain diff --git a/reactos/include/ddk/msports.h b/reactos/include/ddk/msports.h new file mode 100644 index 00000000000..fdaf2def9d9 --- /dev/null +++ b/reactos/include/ddk/msports.h @@ -0,0 +1,52 @@ +#ifndef _MSPORTS_ +#define _MSPORTS_ + +#ifdef __cplusplus +extern "C" { +#endif + +DECLARE_HANDLE(HCOMDB); +typedef HCOMDB *PHCOMDB; +#define HCOMDB_INVALID_HANDLE_VALUE ((HCOMDB)INVALID_HANDLE_VALUE) + +#define COMDB_MIN_PORTS_ARBITRATED 256 +#define COMDB_MAX_PORTS_ARBITRATED 4096 + +LONG +WINAPI +ComDBClaimPort(IN HCOMDB hComDB, + IN DWORD ComNumber, + IN BOOL ForceClaim, + OUT PBOOL Forced); + +LONG +WINAPI +ComDBClose(IN HCOMDB hComDB); + +LONG +WINAPI +ComDBGetCurrentPortUsage(IN HCOMDB hComDB, + OUT PBYTE Buffer, + IN DWORD BufferSize, + IN ULONG ReportType, + OUT LPDWORD MaxPortsReported); + +LONG +WINAPI +ComDBOpen(OUT HCOMDB *phComDB); + +LONG +WINAPI +ComDBReleasePort(IN HCOMDB hComDB, + IN DWORD ComNumber); + +LONG +WINAPI +ComDBResizeDatabase(IN HCOMDB hComDB, + IN DWORD NewSize); + +#ifdef __cplusplus +} +#endif + +#endif /* _MSPORTS_ */