[CMAKE]
[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 HANDLE hMutex;
21 HKEY hKey;
22 } COMDB, *PCOMDB;
23
24
25 LONG
26 WINAPI
27 ComDBClaimNextFreePort(IN HCOMDB hComDB,
28 OUT LPDWORD ComNumber)
29 {
30 PCOMDB pComDB;
31 DWORD dwBitIndex;
32 DWORD dwByteIndex;
33 DWORD dwSize;
34 DWORD dwType;
35 PBYTE pBitmap = NULL;
36 BYTE cMask;
37 LONG lError;
38
39 TRACE("ComDBClaimNextFreePort(%p %p)\n", hComDB, ComNumber);
40
41 if (hComDB == INVALID_HANDLE_VALUE ||
42 hComDB == NULL ||
43 ComNumber == NULL)
44 return ERROR_INVALID_PARAMETER;
45
46 pComDB = (PCOMDB)hComDB;
47
48 /* Wait for the mutex */
49 WaitForSingleObject(pComDB->hMutex, INFINITE);
50
51 /* Get the required bitmap size */
52 lError = RegQueryValueExW(pComDB->hKey,
53 L"ComDB",
54 NULL,
55 &dwType,
56 NULL,
57 &dwSize);
58 if (lError != ERROR_SUCCESS)
59 {
60 ERR("Failed to query the bitmap size!\n");
61 goto done;
62 }
63
64 /* Allocate the bitmap */
65 pBitmap = HeapAlloc(GetProcessHeap(),
66 HEAP_ZERO_MEMORY,
67 dwSize);
68 if (pBitmap == NULL)
69 {
70 ERR("Failed to allocate the bitmap!\n");
71 lError = ERROR_NOT_ENOUGH_MEMORY;
72 goto done;
73 }
74
75 /* Read the bitmap */
76 lError = RegQueryValueExW(pComDB->hKey,
77 L"ComDB",
78 NULL,
79 &dwType,
80 pBitmap,
81 &dwSize);
82 if (lError != ERROR_SUCCESS)
83 goto done;
84
85 lError = ERROR_INVALID_PARAMETER;
86 for (dwBitIndex = 0; dwBitIndex < (dwSize * BITS_PER_BYTE); dwBitIndex++)
87 {
88 /* Calculate the byte index and a mask for the affected bit */
89 dwByteIndex = dwBitIndex / BITS_PER_BYTE;
90 cMask = 1 << (dwBitIndex % BITS_PER_BYTE);
91
92 if ((pBitmap[dwByteIndex] & cMask) == 0)
93 {
94 pBitmap[dwByteIndex] |= cMask;
95 *ComNumber = dwBitIndex + 1;
96 lError = ERROR_SUCCESS;
97 break;
98 }
99 }
100
101 /* Save the bitmap if it was modified */
102 if (lError == ERROR_SUCCESS)
103 {
104 lError = RegSetValueExW(pComDB->hKey,
105 L"ComDB",
106 0,
107 REG_BINARY,
108 pBitmap,
109 dwSize);
110 }
111
112 done:;
113 /* Release the mutex */
114 ReleaseMutex(pComDB->hMutex);
115
116 /* Release the bitmap */
117 if (pBitmap != NULL)
118 HeapFree(GetProcessHeap(), 0, pBitmap);
119
120 return lError;
121 }
122
123
124 LONG
125 WINAPI
126 ComDBClaimPort(IN HCOMDB hComDB,
127 IN DWORD ComNumber,
128 IN BOOL ForceClaim,
129 OUT PBOOL Forced)
130 {
131 PCOMDB pComDB;
132 DWORD dwBitIndex;
133 DWORD dwByteIndex;
134 DWORD dwType;
135 DWORD dwSize;
136 PBYTE pBitmap = NULL;
137 BYTE cMask;
138 LONG lError;
139
140 TRACE("ComDBClaimPort(%p %lu)\n", hComDB, ComNumber);
141
142 if (hComDB == INVALID_HANDLE_VALUE ||
143 hComDB == NULL ||
144 ComNumber == 0 ||
145 ComNumber > COMDB_MAX_PORTS_ARBITRATED)
146 return ERROR_INVALID_PARAMETER;
147
148 pComDB = (PCOMDB)hComDB;
149
150 /* Wait for the mutex */
151 WaitForSingleObject(pComDB->hMutex, INFINITE);
152
153 /* Get the required bitmap size */
154 lError = RegQueryValueExW(pComDB->hKey,
155 L"ComDB",
156 NULL,
157 &dwType,
158 NULL,
159 &dwSize);
160 if (lError != ERROR_SUCCESS)
161 {
162 ERR("Failed to query the bitmap size!\n");
163 goto done;
164 }
165
166 /* Allocate the bitmap */
167 pBitmap = HeapAlloc(GetProcessHeap(),
168 HEAP_ZERO_MEMORY,
169 dwSize);
170 if (pBitmap == NULL)
171 {
172 ERR("Failed to allocate the bitmap!\n");
173 lError = ERROR_NOT_ENOUGH_MEMORY;
174 goto done;
175 }
176
177 /* Read the bitmap */
178 lError = RegQueryValueExW(pComDB->hKey,
179 L"ComDB",
180 NULL,
181 &dwType,
182 pBitmap,
183 &dwSize);
184 if (lError != ERROR_SUCCESS)
185 goto done;
186
187 /* Get the bit index */
188 dwBitIndex = ComNumber - 1;
189
190 /* Check if the bit to set fits into the bitmap */
191 if (dwBitIndex >= (dwSize * BITS_PER_BYTE))
192 {
193 FIXME("Resize the bitmap\n");
194
195 lError = ERROR_INVALID_PARAMETER;
196 goto done;
197 }
198
199 /* Calculate the byte index and a mask for the affected bit */
200 dwByteIndex = dwBitIndex / BITS_PER_BYTE;
201 cMask = 1 << (dwBitIndex % BITS_PER_BYTE);
202
203 lError = ERROR_SHARING_VIOLATION;
204
205 /* Check if the bit is not set */
206 if ((pBitmap[dwByteIndex] & cMask) == 0)
207 {
208 /* Set the bit */
209 pBitmap[dwByteIndex] |= cMask;
210 lError = ERROR_SUCCESS;
211 }
212
213 /* Save the bitmap if it was modified */
214 if (lError == ERROR_SUCCESS)
215 {
216 lError = RegSetValueExW(pComDB->hKey,
217 L"ComDB",
218 0,
219 REG_BINARY,
220 pBitmap,
221 dwSize);
222 }
223
224 done:
225 /* Release the mutex */
226 ReleaseMutex(pComDB->hMutex);
227
228 /* Release the bitmap */
229 if (pBitmap != NULL)
230 HeapFree(GetProcessHeap(), 0, pBitmap);
231
232 return lError;
233 }
234
235
236 LONG
237 WINAPI
238 ComDBClose(IN HCOMDB hComDB)
239 {
240 PCOMDB pComDB;
241
242 TRACE("ComDBClose(%p)\n", hComDB);
243
244 if (hComDB == HCOMDB_INVALID_HANDLE_VALUE ||
245 hComDB == NULL)
246 return ERROR_INVALID_PARAMETER;
247
248 pComDB = (PCOMDB)hComDB;
249
250 /* Close the registry key */
251 if (pComDB->hKey != NULL)
252 RegCloseKey(pComDB->hKey);
253
254 /* Close the mutex */
255 if (pComDB->hMutex != NULL)
256 CloseHandle(pComDB->hMutex);
257
258 /* Release the database */
259 HeapFree(GetProcessHeap(), 0, pComDB);
260
261 return ERROR_SUCCESS;
262 }
263
264
265 LONG
266 WINAPI
267 ComDBGetCurrentPortUsage(IN HCOMDB hComDB,
268 OUT PBYTE Buffer,
269 IN DWORD BufferSize,
270 IN DWORD ReportType,
271 OUT LPDWORD MaxPortsReported)
272 {
273 PCOMDB pComDB;
274 DWORD dwBitIndex;
275 DWORD dwByteIndex;
276 DWORD dwType;
277 DWORD dwSize;
278 PBYTE pBitmap = NULL;
279 BYTE cMask;
280 LONG lError = ERROR_SUCCESS;
281
282 if (hComDB == INVALID_HANDLE_VALUE ||
283 hComDB == NULL ||
284 (Buffer == NULL && MaxPortsReported == NULL) ||
285 (ReportType != CDB_REPORT_BITS && ReportType != CDB_REPORT_BYTES))
286 return ERROR_INVALID_PARAMETER;
287
288 pComDB = (PCOMDB)hComDB;
289
290 /* Wait for the mutex */
291 WaitForSingleObject(pComDB->hMutex, INFINITE);
292
293 /* Get the required bitmap size */
294 lError = RegQueryValueExW(pComDB->hKey,
295 L"ComDB",
296 NULL,
297 &dwType,
298 NULL,
299 &dwSize);
300 if (lError != ERROR_SUCCESS)
301 {
302 ERR("Failed to query the bitmap size!\n");
303 goto done;
304 }
305
306 /* Allocate the bitmap */
307 pBitmap = HeapAlloc(GetProcessHeap(),
308 HEAP_ZERO_MEMORY,
309 dwSize);
310 if (pBitmap == NULL)
311 {
312 ERR("Failed to allocate the bitmap!\n");
313 lError = ERROR_NOT_ENOUGH_MEMORY;
314 goto done;
315 }
316
317 /* Read the bitmap */
318 lError = RegQueryValueExW(pComDB->hKey,
319 L"ComDB",
320 NULL,
321 &dwType,
322 pBitmap,
323 &dwSize);
324 if (lError != ERROR_SUCCESS)
325 goto done;
326
327 if (Buffer == NULL)
328 {
329 *MaxPortsReported = dwSize * BITS_PER_BYTE;
330 }
331 else
332 {
333 if (ReportType == CDB_REPORT_BITS)
334 {
335 /* Clear the buffer */
336 memset(Buffer, 0, BufferSize);
337
338 memcpy(Buffer,
339 pBitmap,
340 min(dwSize, BufferSize));
341
342 if (MaxPortsReported != NULL)
343 *MaxPortsReported = min(dwSize, BufferSize) * BITS_PER_BYTE;
344 }
345 else if (ReportType == CDB_REPORT_BYTES)
346 {
347 /* Clear the buffer */
348 memset(Buffer, 0, BufferSize);
349
350 for (dwBitIndex = 0; dwBitIndex < min(dwSize * BITS_PER_BYTE, BufferSize); dwBitIndex++)
351 {
352 /* Calculate the byte index and a mask for the affected bit */
353 dwByteIndex = dwBitIndex / BITS_PER_BYTE;
354 cMask = 1 << (dwBitIndex % BITS_PER_BYTE);
355
356 if ((pBitmap[dwByteIndex] & cMask) != 0)
357 Buffer[dwBitIndex] = 1;
358 }
359 }
360 }
361
362 done:;
363 /* Release the mutex */
364 ReleaseMutex(pComDB->hMutex);
365
366 /* Release the bitmap */
367 HeapFree(GetProcessHeap(), 0, pBitmap);
368
369 return lError;
370 }
371
372
373 LONG
374 WINAPI
375 ComDBOpen(OUT HCOMDB *phComDB)
376 {
377 PCOMDB pComDB;
378 DWORD dwDisposition;
379 DWORD dwType;
380 DWORD dwSize;
381 PBYTE pBitmap;
382 LONG lError;
383
384 TRACE("ComDBOpen(%p)\n", phComDB);
385
386 /* Allocate a new database */
387 pComDB = HeapAlloc(GetProcessHeap(),
388 HEAP_ZERO_MEMORY,
389 sizeof(COMDB));
390 if (pComDB == NULL)
391 {
392 ERR("Failed to allocate the database!\n");
393 *phComDB = HCOMDB_INVALID_HANDLE_VALUE;
394 return ERROR_ACCESS_DENIED;
395 }
396
397 /* Create a mutex to protect the database */
398 pComDB->hMutex = CreateMutexW(NULL,
399 FALSE,
400 L"ComDBMutex");
401 if (pComDB->hMutex == NULL)
402 {
403 ERR("Failed to create the mutex!\n");
404 HeapFree(GetProcessHeap(), 0, pComDB);
405 *phComDB = HCOMDB_INVALID_HANDLE_VALUE;
406 return ERROR_ACCESS_DENIED;
407 }
408
409 /* Wait for the mutex */
410 WaitForSingleObject(pComDB->hMutex, INFINITE);
411
412 /* Create or open the database key */
413 lError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
414 L"System\\CurrentControlSet\\Control\\COM Name Arbiter",
415 0,
416 NULL,
417 0,
418 KEY_ALL_ACCESS,
419 NULL,
420 &pComDB->hKey,
421 &dwDisposition);
422 if (lError != ERROR_SUCCESS)
423 goto done;
424
425 /* Get the required bitmap size */
426 lError = RegQueryValueExW(pComDB->hKey,
427 L"ComDB",
428 NULL,
429 &dwType,
430 NULL,
431 &dwSize);
432 if (lError == ERROR_FILE_NOT_FOUND)
433 {
434 /* Allocate a new bitmap */
435 dwSize = COMDB_MIN_PORTS_ARBITRATED / BITS_PER_BYTE;
436 pBitmap = HeapAlloc(GetProcessHeap(),
437 HEAP_ZERO_MEMORY,
438 dwSize);
439 if (pBitmap == NULL)
440 {
441 ERR("Failed to allocate the bitmap!\n");
442 lError = ERROR_ACCESS_DENIED;
443 goto done;
444 }
445
446 /* Write the bitmap to the registry */
447 lError = RegSetValueExW(pComDB->hKey,
448 L"ComDB",
449 0,
450 REG_BINARY,
451 pBitmap,
452 dwSize);
453
454 HeapFree(GetProcessHeap(), 0, pBitmap);
455 }
456
457 done:;
458 /* Release the mutex */
459 ReleaseMutex(pComDB->hMutex);
460
461 if (lError != ERROR_SUCCESS)
462 {
463 /* Clean up in case of failure */
464 if (pComDB->hKey != NULL)
465 RegCloseKey(pComDB->hKey);
466
467 if (pComDB->hMutex != NULL)
468 CloseHandle(pComDB->hMutex);
469
470 HeapFree(GetProcessHeap(), 0, pComDB);
471
472 *phComDB = HCOMDB_INVALID_HANDLE_VALUE;
473 }
474 else
475 {
476 /* Return the database handle */
477 *phComDB = (HCOMDB)pComDB;
478 }
479
480 TRACE("done (Error %lu)\n", lError);
481
482 return lError;
483 }
484
485
486 LONG
487 WINAPI
488 ComDBReleasePort(IN HCOMDB hComDB,
489 IN DWORD ComNumber)
490 {
491 PCOMDB pComDB;
492 DWORD dwByteIndex;
493 DWORD dwBitIndex;
494 DWORD dwType;
495 DWORD dwSize;
496 PBYTE pBitmap = NULL;
497 BYTE cMask;
498 LONG lError;
499
500 TRACE("ComDBReleasePort(%p %lu)\n", hComDB, ComNumber);
501
502 if (hComDB == INVALID_HANDLE_VALUE ||
503 ComNumber == 0 ||
504 ComNumber > COMDB_MAX_PORTS_ARBITRATED)
505 return ERROR_INVALID_PARAMETER;
506
507 pComDB = (PCOMDB)hComDB;
508
509 /* Wait for the mutex */
510 WaitForSingleObject(pComDB->hMutex, INFINITE);
511
512 /* Get the required bitmap size */
513 lError = RegQueryValueExW(pComDB->hKey,
514 L"ComDB",
515 NULL,
516 &dwType,
517 NULL,
518 &dwSize);
519 if (lError != ERROR_SUCCESS)
520 {
521 ERR("Failed to query the bitmap size!\n");
522 goto done;
523 }
524
525 /* Allocate the bitmap */
526 pBitmap = HeapAlloc(GetProcessHeap(),
527 HEAP_ZERO_MEMORY,
528 dwSize);
529 if (pBitmap == NULL)
530 {
531 ERR("Failed to allocate the bitmap!\n");
532 lError = ERROR_NOT_ENOUGH_MEMORY;
533 goto done;
534 }
535
536 /* Read the bitmap */
537 lError = RegQueryValueExW(pComDB->hKey,
538 L"ComDB",
539 NULL,
540 &dwType,
541 pBitmap,
542 &dwSize);
543 if (lError != ERROR_SUCCESS)
544 goto done;
545
546 /* Get the bit index */
547 dwBitIndex = ComNumber - 1;
548
549 /* Check if the bit to set fits into the bitmap */
550 if (dwBitIndex >= (dwSize * BITS_PER_BYTE))
551 {
552 lError = ERROR_INVALID_PARAMETER;
553 goto done;
554 }
555
556 /* Calculate the byte index and a mask for the affected bit */
557 dwByteIndex = dwBitIndex / BITS_PER_BYTE;
558 cMask = 1 << (dwBitIndex % BITS_PER_BYTE);
559
560 /* Release the port */
561 pBitmap[dwByteIndex] &= ~cMask;
562
563 lError = RegSetValueExW(pComDB->hKey,
564 L"ComDB",
565 0,
566 REG_BINARY,
567 pBitmap,
568 dwSize);
569
570 done:;
571 /* Release the mutex */
572 ReleaseMutex(pComDB->hMutex);
573
574 /* Release the bitmap */
575 if (pBitmap != NULL)
576 HeapFree(GetProcessHeap(), 0, pBitmap);
577
578 return lError;
579 }
580
581
582 LONG
583 WINAPI
584 ComDBResizeDatabase(IN HCOMDB hComDB,
585 IN DWORD NewSize)
586 {
587 FIXME("ComDBResizeDatabase(%p %lu)\n", hComDB, NewSize);
588 return ERROR_CALL_NOT_IMPLEMENTED;
589 }
590
591 /* EOF */