[MSPORTS]
[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 } COMDB, *PCOMDB;
22
23
24 LONG
25 WINAPI
26 ComDBClaimNextFreePort(IN HCOMDB hComDB,
27 OUT LPDWORD ComNumber)
28 {
29 PCOMDB pComDB;
30 DWORD dwBitIndex;
31 DWORD dwByteIndex;
32 DWORD dwSize;
33 DWORD dwType;
34 PBYTE pBitmap = NULL;
35 BYTE cMask;
36 LONG lError;
37
38 TRACE("ComDBClaimNextFreePort(%p %p)\n", hComDB, ComNumber);
39
40 if (hComDB == INVALID_HANDLE_VALUE ||
41 hComDB == NULL ||
42 ComNumber == NULL)
43 return ERROR_INVALID_PARAMETER;
44
45 pComDB = (PCOMDB)hComDB;
46
47 /* Get the required bitmap size */
48 lError = RegQueryValueExW(pComDB->hKey,
49 L"ComDB",
50 NULL,
51 &dwType,
52 NULL,
53 &dwSize);
54 if (lError != ERROR_SUCCESS)
55 return lError;
56
57 /* Allocate the bitmap */
58 pBitmap = HeapAlloc(GetProcessHeap(),
59 HEAP_ZERO_MEMORY,
60 dwSize);
61 if (pBitmap == NULL)
62 {
63 ERR("Failed to allocate the bitmap!\n");
64 return lError;
65 }
66
67 /* Read the bitmap */
68 lError = RegQueryValueExW(pComDB->hKey,
69 L"ComDB",
70 NULL,
71 &dwType,
72 pBitmap,
73 &dwSize);
74 if (lError != ERROR_SUCCESS)
75 goto done;
76
77 lError = ERROR_INVALID_PARAMETER;
78 for (dwBitIndex = 0; dwBitIndex < (dwSize * BITS_PER_BYTE); dwBitIndex++)
79 {
80 /* Calculate the byte index and a mask for the affected bit */
81 dwByteIndex = dwBitIndex / BITS_PER_BYTE;
82 cMask = 1 << (dwBitIndex % BITS_PER_BYTE);
83
84 if ((pBitmap[dwByteIndex] & cMask) == 0)
85 {
86 pBitmap[dwByteIndex] |= cMask;
87 *ComNumber = dwBitIndex + 1;
88 lError = ERROR_SUCCESS;
89 break;
90 }
91 }
92
93 /* Save the bitmap if it was modified */
94 if (lError == ERROR_SUCCESS)
95 {
96 lError = RegSetValueExW(pComDB->hKey,
97 L"ComDB",
98 0,
99 REG_BINARY,
100 pBitmap,
101 dwSize);
102 }
103
104 done:;
105 if (pBitmap != NULL)
106 HeapFree(GetProcessHeap(), 0, pBitmap);
107
108 return lError;
109 }
110
111
112 LONG
113 WINAPI
114 ComDBClaimPort(IN HCOMDB hComDB,
115 IN DWORD ComNumber,
116 IN BOOL ForceClaim,
117 OUT PBOOL Forced)
118 {
119 PCOMDB pComDB;
120 DWORD dwBitIndex;
121 DWORD dwByteIndex;
122 DWORD dwType;
123 DWORD dwSize;
124 PBYTE pBitmap = NULL;
125 BYTE cMask;
126 LONG lError;
127
128 TRACE("ComDBClaimPort(%p %lu)\n", hComDB, ComNumber);
129
130 if (hComDB == INVALID_HANDLE_VALUE ||
131 hComDB == NULL ||
132 ComNumber == 0 ||
133 ComNumber > COMDB_MAX_PORTS_ARBITRATED)
134 return ERROR_INVALID_PARAMETER;
135
136 pComDB = (PCOMDB)hComDB;
137
138 /* Get the required bitmap size */
139 lError = RegQueryValueExW(pComDB->hKey,
140 L"ComDB",
141 NULL,
142 &dwType,
143 NULL,
144 &dwSize);
145 if (lError != ERROR_SUCCESS)
146 return lError;
147
148 /* Allocate the bitmap */
149 pBitmap = HeapAlloc(GetProcessHeap(),
150 HEAP_ZERO_MEMORY,
151 dwSize);
152 if (pBitmap == NULL)
153 {
154 ERR("Failed to allocate the bitmap!\n");
155 return lError;
156 }
157
158 /* Read the bitmap */
159 lError = RegQueryValueExW(pComDB->hKey,
160 L"ComDB",
161 NULL,
162 &dwType,
163 pBitmap,
164 &dwSize);
165 if (lError != ERROR_SUCCESS)
166 goto done;
167
168 /* Get the bit index */
169 dwBitIndex = ComNumber - 1;
170
171 /* Check if the bit to set fits into the bitmap */
172 if (dwBitIndex >= (dwSize * BITS_PER_BYTE))
173 {
174 FIXME("Resize the bitmap\n");
175
176 lError = ERROR_INVALID_PARAMETER;
177 goto done;
178 }
179
180 /* Calculate the byte index and a mask for the affected bit */
181 dwByteIndex = dwBitIndex / BITS_PER_BYTE;
182 cMask = 1 << (dwBitIndex % BITS_PER_BYTE);
183
184 lError = ERROR_SHARING_VIOLATION;
185
186 /* Check if the bit is not set */
187 if ((pBitmap[dwByteIndex] & cMask) == 0)
188 {
189 /* Set the bit */
190 pBitmap[dwByteIndex] |= cMask;
191 lError = ERROR_SUCCESS;
192 }
193
194 /* Save the bitmap if it was modified */
195 if (lError == ERROR_SUCCESS)
196 {
197 lError = RegSetValueExW(pComDB->hKey,
198 L"ComDB",
199 0,
200 REG_BINARY,
201 pBitmap,
202 dwSize);
203 }
204
205 done:
206 if (pBitmap != NULL)
207 HeapFree(GetProcessHeap(), 0, pBitmap);
208
209 return lError;
210 }
211
212
213 LONG
214 WINAPI
215 ComDBClose(IN HCOMDB hComDB)
216 {
217 PCOMDB pComDB;
218
219 TRACE("ComDBClose(%p)\n", hComDB);
220
221 if (hComDB == HCOMDB_INVALID_HANDLE_VALUE || hComDB == NULL)
222 return ERROR_INVALID_PARAMETER;
223
224 pComDB = (PCOMDB)hComDB;
225
226 /* Close the registry key */
227 if (pComDB->hKey != NULL)
228 RegCloseKey(pComDB->hKey);
229
230 /* Release the database */
231 HeapFree(GetProcessHeap(), 0, pComDB);
232
233 return ERROR_SUCCESS;
234 }
235
236
237 LONG
238 WINAPI
239 ComDBGetCurrentPortUsage(IN HCOMDB hComDB,
240 OUT PBYTE Buffer,
241 IN DWORD BufferSize,
242 IN DWORD ReportType,
243 OUT LPDWORD MaxPortsReported)
244 {
245 FIXME("ComDBGetCurrentPortUsage(%p)\n", hComDB);
246 return ERROR_CALL_NOT_IMPLEMENTED;
247 }
248
249
250 LONG
251 WINAPI
252 ComDBOpen(OUT HCOMDB *phComDB)
253 {
254 PCOMDB pComDB;
255 DWORD dwDisposition;
256 DWORD dwType;
257 DWORD dwSize;
258 PBYTE pBitmap;
259 LONG lError;
260
261 TRACE("ComDBOpen(%p)\n", phComDB);
262
263 /* Allocate a new database */
264 pComDB = HeapAlloc(GetProcessHeap(),
265 HEAP_ZERO_MEMORY,
266 sizeof(COMDB));
267 if (pComDB == NULL)
268 {
269 ERR("Failed to allocate the database!\n");
270 return ERROR_ACCESS_DENIED;
271 }
272
273 /* Create or open the database key */
274 lError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
275 L"System\\CurrentControlSet\\Control\\COM Name Arbiter",
276 0,
277 NULL,
278 0,
279 KEY_ALL_ACCESS,
280 NULL,
281 &pComDB->hKey,
282 &dwDisposition);
283 if (lError != ERROR_SUCCESS)
284 goto done;
285
286 /* Get the required bitmap size */
287 lError = RegQueryValueExW(pComDB->hKey,
288 L"ComDB",
289 NULL,
290 &dwType,
291 NULL,
292 &dwSize);
293 if (lError == ERROR_FILE_NOT_FOUND)
294 {
295 /* Allocate a new bitmap */
296 dwSize = COMDB_MIN_PORTS_ARBITRATED / BITS_PER_BYTE;
297 pBitmap = HeapAlloc(GetProcessHeap(),
298 HEAP_ZERO_MEMORY,
299 dwSize);
300 if (pBitmap == NULL)
301 {
302 ERR("Failed to allocate the bitmap!\n");
303 lError = ERROR_ACCESS_DENIED;
304 goto done;
305 }
306
307 /* Write the bitmap to the registry */
308 lError = RegSetValueExW(pComDB->hKey,
309 L"ComDB",
310 0,
311 REG_BINARY,
312 pBitmap,
313 dwSize);
314
315 HeapFree(GetProcessHeap(), 0, pBitmap);
316 }
317
318 done:;
319 if (lError != ERROR_SUCCESS)
320 {
321 /* Clean up in case of failure */
322 if (pComDB->hKey != NULL)
323 RegCloseKey(pComDB->hKey);
324
325 HeapFree(GetProcessHeap(), 0, pComDB);
326
327 *phComDB = HCOMDB_INVALID_HANDLE_VALUE;
328 }
329 else
330 {
331 /* Return the database handle */
332 *phComDB = (HCOMDB)pComDB;
333 }
334
335 TRACE("done (Error %lu)\n", lError);
336
337 return lError;
338 }
339
340
341 LONG
342 WINAPI
343 ComDBReleasePort(IN HCOMDB hComDB,
344 IN DWORD ComNumber)
345 {
346 PCOMDB pComDB;
347 DWORD dwByteIndex;
348 DWORD dwBitIndex;
349 DWORD dwType;
350 DWORD dwSize;
351 PBYTE pBitmap = NULL;
352 BYTE cMask;
353 LONG lError;
354
355 TRACE("ComDBReleasePort(%p %lu)\n", hComDB, ComNumber);
356
357 if (hComDB == INVALID_HANDLE_VALUE ||
358 ComNumber == 0 ||
359 ComNumber > COMDB_MAX_PORTS_ARBITRATED)
360 return ERROR_INVALID_PARAMETER;
361
362 pComDB = (PCOMDB)hComDB;
363
364 /* Get the required bitmap size */
365 lError = RegQueryValueExW(pComDB->hKey,
366 L"ComDB",
367 NULL,
368 &dwType,
369 NULL,
370 &dwSize);
371 if (lError != ERROR_SUCCESS)
372 return lError;
373
374 /* Allocate the bitmap */
375 pBitmap = HeapAlloc(GetProcessHeap(),
376 HEAP_ZERO_MEMORY,
377 dwSize);
378 if (pBitmap == NULL)
379 {
380 ERR("Failed to allocate the bitmap!\n");
381 return lError;
382 }
383
384 /* Read the bitmap */
385 lError = RegQueryValueExW(pComDB->hKey,
386 L"ComDB",
387 NULL,
388 &dwType,
389 pBitmap,
390 &dwSize);
391 if (lError != ERROR_SUCCESS)
392 goto done;
393
394 /* Get the bit index */
395 dwBitIndex = ComNumber - 1;
396
397 /* Check if the bit to set fits into the bitmap */
398 if (dwBitIndex >= (dwSize * BITS_PER_BYTE))
399 {
400 lError = ERROR_INVALID_PARAMETER;
401 goto done;
402 }
403
404 /* Calculate the byte index and a mask for the affected bit */
405 dwByteIndex = dwBitIndex / BITS_PER_BYTE;
406 cMask = 1 << (dwBitIndex % BITS_PER_BYTE);
407
408 /* Release the port */
409 pBitmap[dwByteIndex] &= ~cMask;
410
411 lError = RegSetValueExW(pComDB->hKey,
412 L"ComDB",
413 0,
414 REG_BINARY,
415 pBitmap,
416 dwSize);
417
418 done:;
419 if (pBitmap != NULL)
420 HeapFree(GetProcessHeap(), 0, pBitmap);
421
422 return lError;
423 }
424
425
426 LONG
427 WINAPI
428 ComDBResizeDatabase(IN HCOMDB hComDB,
429 IN DWORD NewSize)
430 {
431 FIXME("ComDBResizeDatabase(%p %lu)\n", hComDB, NewSize);
432 return ERROR_CALL_NOT_IMPLEMENTED;
433 }
434
435 /* EOF */