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