From 9074f26b851aef3a53cb587d1fa3b0230a6da508 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Wed, 25 May 2011 10:52:12 +0000 Subject: [PATCH] [MSPORTS] - Implement ComDBClaimNextFreePort and ComDBReleasePort. - Add stubs for ComDBGetCurrentPortUsage and ComDBResizeDatabase. - Do not keep the port bitmap in a buffer between calls but use a read-modify-write strategy instead. - Replace pointer-based access to the port bitmap by index-based access. - Use ComDBClaimNextFreePort in the serial port installer. See issue #6272 for more details. svn path=/trunk/; revision=51901 --- reactos/dll/win32/msports/classinst.c | 7 +- reactos/dll/win32/msports/comdb.c | 296 +++++++++++++++++++++---- reactos/dll/win32/msports/msports.spec | 8 +- reactos/include/ddk/msports.h | 7 +- 4 files changed, 271 insertions(+), 47 deletions(-) diff --git a/reactos/dll/win32/msports/classinst.c b/reactos/dll/win32/msports/classinst.c index 4502d5f2ca8..1ac86bf99de 100644 --- a/reactos/dll/win32/msports/classinst.c +++ b/reactos/dll/win32/msports/classinst.c @@ -257,8 +257,6 @@ InstallSerialPort(IN HDEVINFO DeviceInfoSet, DeviceInfoData); if (dwPortNumber != 0) { - swprintf(szPortName, L"COM%u", dwPortNumber); - ComDBClaimPort(hComDB, dwPortNumber, FALSE, @@ -266,9 +264,12 @@ InstallSerialPort(IN HDEVINFO DeviceInfoSet, } else { - wcscpy(szPortName, L"COMx"); + ComDBClaimNextFreePort(hComDB, + &dwPortNumber); } + swprintf(szPortName, L"COM%u", dwPortNumber); + /* Close the com port database */ if (hComDB != HCOMDB_INVALID_HANDLE_VALUE) ComDBClose(hComDB); diff --git a/reactos/dll/win32/msports/comdb.c b/reactos/dll/win32/msports/comdb.c index efd927408f4..ccb703cf70d 100644 --- a/reactos/dll/win32/msports/comdb.c +++ b/reactos/dll/win32/msports/comdb.c @@ -18,11 +18,97 @@ WINE_DEFAULT_DEBUG_CHANNEL(msports); typedef struct _COMDB { HKEY hKey; - DWORD dwSize; - PBYTE pBitmap; } 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; + + /* Get the required bitmap size */ + lError = RegQueryValueExW(pComDB->hKey, + L"ComDB", + NULL, + &dwType, + NULL, + &dwSize); + if (lError != ERROR_SUCCESS) + return lError; + + /* Allocate the bitmap */ + pBitmap = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + dwSize); + if (pBitmap == NULL) + { + ERR("Failed to allocate the bitmap!\n"); + return lError; + } + + /* 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:; + if (pBitmap != NULL) + HeapFree(GetProcessHeap(), 0, pBitmap); + + return lError; +} + + LONG WINAPI ComDBClaimPort(IN HCOMDB hComDB, @@ -31,13 +117,16 @@ ComDBClaimPort(IN HCOMDB hComDB, OUT PBOOL Forced) { PCOMDB pComDB; - PBYTE pByte; - BYTE cMask; 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 || @@ -46,43 +135,61 @@ ComDBClaimPort(IN HCOMDB hComDB, pComDB = (PCOMDB)hComDB; - /* Update the bitmap */ - dwSize = pComDB->dwSize; + /* Get the required bitmap size */ lError = RegQueryValueExW(pComDB->hKey, L"ComDB", NULL, &dwType, - pComDB->pBitmap, + NULL, &dwSize); if (lError != ERROR_SUCCESS) return lError; + /* Allocate the bitmap */ + pBitmap = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + dwSize); + if (pBitmap == NULL) + { + ERR("Failed to allocate the bitmap!\n"); + return lError; + } + + /* 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 >= (pComDB->dwSize * BITS_PER_BYTE)) + if (dwBitIndex >= (dwSize * BITS_PER_BYTE)) { - /* FIXME: Resize the bitmap */ - return ERROR_INVALID_PARAMETER; + FIXME("Resize the bitmap\n"); + + lError = ERROR_INVALID_PARAMETER; + goto done; } - /* Get a pointer to the affected byte and calculate a mask for the affected bit */ - pByte = &(pComDB->pBitmap[dwBitIndex / BITS_PER_BYTE]); + /* 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 ((*pByte & cMask) == 0) + if ((pBitmap[dwByteIndex] & cMask) == 0) { /* Set the bit */ - *pByte |= cMask; + pBitmap[dwByteIndex] |= 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) @@ -91,10 +198,14 @@ ComDBClaimPort(IN HCOMDB hComDB, L"ComDB", 0, REG_BINARY, - pComDB->pBitmap, - pComDB->dwSize); + pBitmap, + dwSize); } +done: + if (pBitmap != NULL) + HeapFree(GetProcessHeap(), 0, pBitmap); + return lError; } @@ -105,6 +216,8 @@ ComDBClose(IN HCOMDB hComDB) { PCOMDB pComDB; + TRACE("ComDBClose(%p)\n", hComDB); + if (hComDB == HCOMDB_INVALID_HANDLE_VALUE || hComDB == NULL) return ERROR_INVALID_PARAMETER; @@ -114,10 +227,6 @@ ComDBClose(IN HCOMDB hComDB) 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); @@ -125,6 +234,19 @@ ComDBClose(IN HCOMDB hComDB) } +LONG +WINAPI +ComDBGetCurrentPortUsage(IN HCOMDB hComDB, + OUT PBYTE Buffer, + IN DWORD BufferSize, + IN DWORD ReportType, + OUT LPDWORD MaxPortsReported) +{ + FIXME("ComDBGetCurrentPortUsage(%p)\n", hComDB); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + LONG WINAPI ComDBOpen(OUT HCOMDB *phComDB) @@ -132,6 +254,8 @@ ComDBOpen(OUT HCOMDB *phComDB) PCOMDB pComDB; DWORD dwDisposition; DWORD dwType; + DWORD dwSize; + PBYTE pBitmap; LONG lError; TRACE("ComDBOpen(%p)\n", phComDB); @@ -142,7 +266,7 @@ ComDBOpen(OUT HCOMDB *phComDB) sizeof(COMDB)); if (pComDB == NULL) { - ERR("Failed to allocaete the database!\n"); + ERR("Failed to allocate the database!\n"); return ERROR_ACCESS_DENIED; } @@ -165,28 +289,30 @@ ComDBOpen(OUT HCOMDB *phComDB) NULL, &dwType, NULL, - &pComDB->dwSize); + &dwSize); if (lError == ERROR_FILE_NOT_FOUND) { /* Allocate a new bitmap */ - pComDB->dwSize = COMDB_MIN_PORTS_ARBITRATED / BITS_PER_BYTE; - pComDB->pBitmap = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - pComDB->dwSize); - if (pComDB->pBitmap == NULL) + dwSize = COMDB_MIN_PORTS_ARBITRATED / BITS_PER_BYTE; + pBitmap = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + dwSize); + if (pBitmap == NULL) { - ERR("Failed to allocaete the bitmap!\n"); + ERR("Failed to allocate the bitmap!\n"); lError = ERROR_ACCESS_DENIED; goto done; } - /* Read the bitmap from the registry */ + /* Write the bitmap to the registry */ lError = RegSetValueExW(pComDB->hKey, L"ComDB", 0, REG_BINARY, - pComDB->pBitmap, - pComDB->dwSize); + pBitmap, + dwSize); + + HeapFree(GetProcessHeap(), 0, pBitmap); } done:; @@ -196,9 +322,6 @@ done:; if (pComDB->hKey != NULL) RegCloseKey(pComDB->hKey); - if (pComDB->pBitmap != NULL) - HeapFree(GetProcessHeap(), 0, pComDB->pBitmap); - HeapFree(GetProcessHeap(), 0, pComDB); *phComDB = HCOMDB_INVALID_HANDLE_VALUE; @@ -214,4 +337,99 @@ done:; 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; + + /* Get the required bitmap size */ + lError = RegQueryValueExW(pComDB->hKey, + L"ComDB", + NULL, + &dwType, + NULL, + &dwSize); + if (lError != ERROR_SUCCESS) + return lError; + + /* Allocate the bitmap */ + pBitmap = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + dwSize); + if (pBitmap == NULL) + { + ERR("Failed to allocate the bitmap!\n"); + return lError; + } + + /* 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:; + if (pBitmap != NULL) + HeapFree(GetProcessHeap(), 0, pBitmap); + + return lError; +} + + +LONG +WINAPI +ComDBResizeDatabase(IN HCOMDB hComDB, + IN DWORD NewSize) +{ + FIXME("ComDBResizeDatabase(%p %lu)\n", hComDB, NewSize); + return ERROR_CALL_NOT_IMPLEMENTED; +} + /* EOF */ diff --git a/reactos/dll/win32/msports/msports.spec b/reactos/dll/win32/msports/msports.spec index f5672c8ba2b..84fb9571c1f 100644 --- a/reactos/dll/win32/msports/msports.spec +++ b/reactos/dll/win32/msports/msports.spec @@ -1,10 +1,10 @@ -@ stub ComDBClaimNextFreePort +@ stdcall ComDBClaimNextFreePort(ptr ptr) @ stdcall ComDBClaimPort(ptr long long ptr) @ stdcall ComDBClose(ptr) -@ stub ComDBGetCurrentPortUsage +@ stdcall ComDBGetCurrentPortUsage(ptr ptr long long ptr) @ stdcall ComDBOpen(ptr) -@ stub ComDBReleasePort -@ stub ComDBResizeDatabase +@ stdcall ComDBReleasePort(ptr long) +@ stdcall ComDBResizeDatabase(ptr long) @ stdcall LibMain(ptr long ptr) DllMain @ stub ParallelPortPropPageProvider @ stdcall PortsClassInstaller(long ptr ptr) diff --git a/reactos/include/ddk/msports.h b/reactos/include/ddk/msports.h index fdaf2def9d9..33c801551a9 100644 --- a/reactos/include/ddk/msports.h +++ b/reactos/include/ddk/msports.h @@ -12,6 +12,11 @@ typedef HCOMDB *PHCOMDB; #define COMDB_MIN_PORTS_ARBITRATED 256 #define COMDB_MAX_PORTS_ARBITRATED 4096 +LONG +WINAPI +ComDBClaimNextFreePort(IN HCOMDB hComDB, + OUT LPDWORD ComNumber); + LONG WINAPI ComDBClaimPort(IN HCOMDB hComDB, @@ -28,7 +33,7 @@ WINAPI ComDBGetCurrentPortUsage(IN HCOMDB hComDB, OUT PBYTE Buffer, IN DWORD BufferSize, - IN ULONG ReportType, + IN DWORD ReportType, OUT LPDWORD MaxPortsReported); LONG -- 2.17.1