efd927408f430578b225df90f00bcc7576f54d52
[reactos.git] / reactos / dll / win32 / msports / comdb.c
1 /*
2 * PROJECT: Ports installer library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll\win32\msports\comdb.c
5 * PURPOSE: COM port database
6 * COPYRIGHT: Copyright 2011 Eric Kohl
7 */
8
9 #include <windows.h>
10 #include <msports.h>
11
12 #include <wine/debug.h>
13
14 WINE_DEFAULT_DEBUG_CHANNEL(msports);
15
16 #define BITS_PER_BYTE 8
17
18 typedef struct _COMDB
19 {
20 HKEY hKey;
21 DWORD dwSize;
22 PBYTE pBitmap;
23 } COMDB, *PCOMDB;
24
25
26 LONG
27 WINAPI
28 ComDBClaimPort(IN HCOMDB hComDB,
29 IN DWORD ComNumber,
30 IN BOOL ForceClaim,
31 OUT PBOOL Forced)
32 {
33 PCOMDB pComDB;
34 PBYTE pByte;
35 BYTE cMask;
36 DWORD dwBitIndex;
37 DWORD dwType;
38 DWORD dwSize;
39 LONG lError;
40
41 if (hComDB == INVALID_HANDLE_VALUE ||
42 hComDB == NULL ||
43 ComNumber == 0 ||
44 ComNumber > COMDB_MAX_PORTS_ARBITRATED)
45 return ERROR_INVALID_PARAMETER;
46
47 pComDB = (PCOMDB)hComDB;
48
49 /* Update the bitmap */
50 dwSize = pComDB->dwSize;
51 lError = RegQueryValueExW(pComDB->hKey,
52 L"ComDB",
53 NULL,
54 &dwType,
55 pComDB->pBitmap,
56 &dwSize);
57 if (lError != ERROR_SUCCESS)
58 return lError;
59
60 /* Get the bit index */
61 dwBitIndex = ComNumber - 1;
62
63 /* Check if the bit to set fits into the bitmap */
64 if (dwBitIndex >= (pComDB->dwSize * BITS_PER_BYTE))
65 {
66 /* FIXME: Resize the bitmap */
67 return ERROR_INVALID_PARAMETER;
68 }
69
70 /* Get a pointer to the affected byte and calculate a mask for the affected bit */
71 pByte = &(pComDB->pBitmap[dwBitIndex / BITS_PER_BYTE]);
72 cMask = 1 << (dwBitIndex % BITS_PER_BYTE);
73
74 /* Check if the bit is not set */
75 if ((*pByte & cMask) == 0)
76 {
77 /* Set the bit */
78 *pByte |= cMask;
79 lError = ERROR_SUCCESS;
80 }
81 else
82 {
83 /* The bit is already set */
84 lError = ERROR_SHARING_VIOLATION;
85 }
86
87 /* Save the bitmap if it was modified */
88 if (lError == ERROR_SUCCESS)
89 {
90 lError = RegSetValueExW(pComDB->hKey,
91 L"ComDB",
92 0,
93 REG_BINARY,
94 pComDB->pBitmap,
95 pComDB->dwSize);
96 }
97
98 return lError;
99 }
100
101
102 LONG
103 WINAPI
104 ComDBClose(IN HCOMDB hComDB)
105 {
106 PCOMDB pComDB;
107
108 if (hComDB == HCOMDB_INVALID_HANDLE_VALUE || hComDB == NULL)
109 return ERROR_INVALID_PARAMETER;
110
111 pComDB = (PCOMDB)hComDB;
112
113 /* Close the registry key */
114 if (pComDB->hKey != NULL)
115 RegCloseKey(pComDB->hKey);
116
117 /* Release the bitmap */
118 if (pComDB->pBitmap != NULL)
119 HeapFree(GetProcessHeap(), 0, pComDB->pBitmap);
120
121 /* Release the database */
122 HeapFree(GetProcessHeap(), 0, pComDB);
123
124 return ERROR_SUCCESS;
125 }
126
127
128 LONG
129 WINAPI
130 ComDBOpen(OUT HCOMDB *phComDB)
131 {
132 PCOMDB pComDB;
133 DWORD dwDisposition;
134 DWORD dwType;
135 LONG lError;
136
137 TRACE("ComDBOpen(%p)\n", phComDB);
138
139 /* Allocate a new database */
140 pComDB = HeapAlloc(GetProcessHeap(),
141 HEAP_ZERO_MEMORY,
142 sizeof(COMDB));
143 if (pComDB == NULL)
144 {
145 ERR("Failed to allocaete the database!\n");
146 return ERROR_ACCESS_DENIED;
147 }
148
149 /* Create or open the database key */
150 lError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
151 L"System\\CurrentControlSet\\Control\\COM Name Arbiter",
152 0,
153 NULL,
154 0,
155 KEY_ALL_ACCESS,
156 NULL,
157 &pComDB->hKey,
158 &dwDisposition);
159 if (lError != ERROR_SUCCESS)
160 goto done;
161
162 /* Get the required bitmap size */
163 lError = RegQueryValueExW(pComDB->hKey,
164 L"ComDB",
165 NULL,
166 &dwType,
167 NULL,
168 &pComDB->dwSize);
169 if (lError == ERROR_FILE_NOT_FOUND)
170 {
171 /* Allocate a new bitmap */
172 pComDB->dwSize = COMDB_MIN_PORTS_ARBITRATED / BITS_PER_BYTE;
173 pComDB->pBitmap = HeapAlloc(GetProcessHeap(),
174 HEAP_ZERO_MEMORY,
175 pComDB->dwSize);
176 if (pComDB->pBitmap == NULL)
177 {
178 ERR("Failed to allocaete the bitmap!\n");
179 lError = ERROR_ACCESS_DENIED;
180 goto done;
181 }
182
183 /* Read the bitmap from the registry */
184 lError = RegSetValueExW(pComDB->hKey,
185 L"ComDB",
186 0,
187 REG_BINARY,
188 pComDB->pBitmap,
189 pComDB->dwSize);
190 }
191
192 done:;
193 if (lError != ERROR_SUCCESS)
194 {
195 /* Clean up in case of failure */
196 if (pComDB->hKey != NULL)
197 RegCloseKey(pComDB->hKey);
198
199 if (pComDB->pBitmap != NULL)
200 HeapFree(GetProcessHeap(), 0, pComDB->pBitmap);
201
202 HeapFree(GetProcessHeap(), 0, pComDB);
203
204 *phComDB = HCOMDB_INVALID_HANDLE_VALUE;
205 }
206 else
207 {
208 /* Return the database handle */
209 *phComDB = (HCOMDB)pComDB;
210 }
211
212 TRACE("done (Error %lu)\n", lError);
213
214 return lError;
215 }
216
217 /* EOF */