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