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