[MSPORTS]
authorEric Kohl <eric.kohl@reactos.org>
Mon, 23 May 2011 17:54:16 +0000 (17:54 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Mon, 23 May 2011 17:54:16 +0000 (17:54 +0000)
- Add msports.h header file.
- Add the initial version of the com port database and use it to track the used com ports.

svn path=/trunk/; revision=51866

reactos/dll/win32/msports/CMakeLists.txt
reactos/dll/win32/msports/classinst.c
reactos/dll/win32/msports/comdb.c [new file with mode: 0644]
reactos/dll/win32/msports/msports.rbuild
reactos/dll/win32/msports/msports.spec
reactos/include/ddk/msports.h [new file with mode: 0644]

index 0d00273..8dfbd65 100644 (file)
@@ -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
index 8860639..4502d5f 100644 (file)
@@ -10,6 +10,7 @@
 #include <windows.h>
 #include <cmtypes.h>
 #include <stdio.h>
+#include <msports.h>
 #include <setupapi.h>
 #include <wine/debug.h>
 
@@ -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 (file)
index 0000000..1555611
--- /dev/null
@@ -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 <windows.h>
+#include <msports.h>
+
+#include <wine/debug.h>
+
+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
index 6c19b29..cd4a3de 100644 (file)
@@ -6,6 +6,7 @@
        <library>advapi32</library>
        <library>setupapi</library>
        <file>classinst.c</file>
+       <file>comdb.c</file>
        <file>msports.c</file>
        <file>msports.rc</file>
 </module>
index f2155b2..f5672c8 100644 (file)
@@ -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 (file)
index 0000000..fdaf2de
--- /dev/null
@@ -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_ */