[MSPORTS] Check and show which parallel port is in use.
[reactos.git] / dll / win32 / msports / parallel.c
1 /*
2 * PROJECT: Ports installer library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll\win32\msports\parallel.c
5 * PURPOSE: Parallel Port property functions
6 * COPYRIGHT: Copyright 2013 Eric Kohl
7 */
8
9 #include "precomp.h"
10
11
12 typedef struct _PORT_DATA
13 {
14 HDEVINFO DeviceInfoSet;
15 PSP_DEVINFO_DATA DeviceInfoData;
16
17 WCHAR szPortName[16];
18 DWORD dwPortNumber;
19 DWORD dwFilterResourceMethod;
20 DWORD dwLegacy;
21
22 } PORT_DATA, *PPORT_DATA;
23
24
25 static
26 VOID
27 GetUsedPorts(
28 PDWORD pPortMap)
29 {
30 WCHAR szDeviceName[64];
31 WCHAR szDosDeviceName[64];
32 DWORD dwIndex, dwType, dwPortNumber;
33 DWORD dwDeviceNameSize, dwDosDeviceNameSize;
34 PWSTR ptr;
35 HKEY hKey;
36 DWORD dwError;
37
38 *pPortMap = 0;
39
40 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
41 L"Hardware\\DeviceMap\\PARALLEL PORTS",
42 0,
43 KEY_READ,
44 &hKey);
45 if (dwError == ERROR_SUCCESS)
46 {
47 for (dwIndex = 0; ; dwIndex++)
48 {
49 dwDeviceNameSize = ARRAYSIZE(szDeviceName);
50 dwDosDeviceNameSize = sizeof(szDosDeviceName);
51 dwError = RegEnumValueW(hKey,
52 dwIndex,
53 szDeviceName,
54 &dwDeviceNameSize,
55 NULL,
56 &dwType,
57 (LPBYTE)szDosDeviceName,
58 &dwDosDeviceNameSize);
59 if (dwError != ERROR_SUCCESS)
60 break;
61
62 if (dwType == REG_SZ)
63 {
64 TRACE("%S --> %S\n", szDeviceName, szDosDeviceName);
65 if (_wcsnicmp(szDosDeviceName, L"\\DosDevices\\LPT", wcslen(L"\\DosDevices\\LPT")) == 0)
66 {
67 ptr = szDosDeviceName + wcslen(L"\\DosDevices\\LPT");
68 if (wcschr(ptr, L'.') == NULL)
69 {
70 TRACE("Device number %S\n", ptr);
71 dwPortNumber = wcstoul(ptr, NULL, 10);
72 if (dwPortNumber != 0)
73 {
74 *pPortMap |=(1 << dwPortNumber);
75 }
76 }
77 }
78 }
79 }
80
81 RegCloseKey(hKey);
82 }
83
84 TRACE("Done\n");
85 }
86
87
88 static
89 VOID
90 ReadPortSettings(
91 PPORT_DATA pPortData)
92 {
93 DWORD dwSize;
94 HKEY hKey;
95 DWORD dwError;
96
97 TRACE("ReadPortSettings(%p)\n", pPortData);
98
99 pPortData->dwFilterResourceMethod = 1; /* Never use an interrupt */
100 pPortData->dwLegacy = 0; /* Disabled */
101 pPortData->dwPortNumber = 0; /* Unknown */
102
103 hKey = SetupDiOpenDevRegKey(pPortData->DeviceInfoSet,
104 pPortData->DeviceInfoData,
105 DICS_FLAG_GLOBAL,
106 0,
107 DIREG_DEV,
108 KEY_READ);
109 if (hKey != INVALID_HANDLE_VALUE)
110 {
111 dwSize = sizeof(pPortData->szPortName);
112 dwError = RegQueryValueExW(hKey,
113 L"PortName",
114 NULL,
115 NULL,
116 (PBYTE)pPortData->szPortName,
117 &dwSize);
118 if (dwError != ERROR_SUCCESS)
119 {
120 ERR("RegQueryValueExW failed (Error %lu)\n", dwError);
121 }
122
123 dwSize = sizeof(pPortData->dwFilterResourceMethod);
124 dwError = RegQueryValueExW(hKey,
125 L"FilterResourceMethod",
126 NULL,
127 NULL,
128 (PBYTE)&pPortData->dwFilterResourceMethod,
129 &dwSize);
130 if (dwError != ERROR_SUCCESS)
131 {
132 ERR("RegQueryValueExW failed (Error %lu)\n", dwError);
133 }
134
135 RegCloseKey(hKey);
136 }
137
138 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
139 L"SYSTEM\\CurrentControlSet\\Services\\Parport\\Parameters",
140 0,
141 KEY_READ,
142 &hKey);
143 if (dwError == ERROR_SUCCESS)
144 {
145 dwSize = sizeof(pPortData->dwLegacy);
146 dwError = RegQueryValueExW(hKey,
147 L"ParEnableLegacyZip",
148 NULL,
149 NULL,
150 (PBYTE)&pPortData->dwLegacy,
151 &dwSize);
152 if (dwError != ERROR_SUCCESS)
153 {
154 ERR("RegQueryValueExW failed (Error %lu)\n", dwError);
155 }
156
157 RegCloseKey(hKey);
158 }
159 }
160
161
162 static
163 VOID
164 WritePortSettings(
165 HWND hwnd,
166 PPORT_DATA pPortData)
167 {
168 DWORD dwDisposition;
169 DWORD dwFilterResourceMethod;
170 DWORD dwLegacy;
171 DWORD dwPortNumber;
172 HKEY hKey;
173 DWORD dwError;
174
175 TRACE("WritePortSettings(%p)\n", pPortData);
176
177 dwFilterResourceMethod = 1;
178 if (Button_GetCheck(GetDlgItem(hwnd, IDC_TRY_INTERRUPT)) == BST_CHECKED)
179 dwFilterResourceMethod = 0;
180 else if (Button_GetCheck(GetDlgItem(hwnd, IDC_NEVER_INTERRUPT)) == BST_CHECKED)
181 dwFilterResourceMethod = 1;
182 else if (Button_GetCheck(GetDlgItem(hwnd, IDC_ANY_INTERRUPT)) == BST_CHECKED)
183 dwFilterResourceMethod = 2;
184
185 if (dwFilterResourceMethod != pPortData->dwFilterResourceMethod)
186 {
187 hKey = SetupDiOpenDevRegKey(pPortData->DeviceInfoSet,
188 pPortData->DeviceInfoData,
189 DICS_FLAG_GLOBAL,
190 0,
191 DIREG_DEV,
192 KEY_WRITE);
193 if (hKey != INVALID_HANDLE_VALUE)
194 {
195 dwError = RegSetValueExW(hKey,
196 L"FilterResourceMethod",
197 0,
198 REG_DWORD,
199 (PBYTE)&dwFilterResourceMethod,
200 sizeof(dwFilterResourceMethod));
201 if (dwError != ERROR_SUCCESS)
202 {
203 ERR("RegSetValueExW failed (Error %lu)\n", dwError);
204 }
205
206 RegCloseKey(hKey);
207 pPortData->dwFilterResourceMethod = dwFilterResourceMethod;
208 }
209 }
210
211 dwLegacy = 0;
212 if (Button_GetCheck(GetDlgItem(hwnd, IDC_PARALLEL_LEGACY)) == BST_CHECKED)
213 dwLegacy = 1;
214
215 if (dwLegacy != pPortData->dwLegacy)
216 {
217 dwError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
218 L"SYSTEM\\CurrentControlSet\\Services\\Parport\\Parameters",
219 0,
220 NULL,
221 REG_OPTION_NON_VOLATILE,
222 KEY_WRITE,
223 NULL,
224 &hKey,
225 &dwDisposition);
226 if (dwError == ERROR_SUCCESS)
227 {
228 dwError = RegSetValueExW(hKey,
229 L"ParEnableLegacyZip",
230 0,
231 REG_DWORD,
232 (LPBYTE)&dwLegacy,
233 sizeof(dwLegacy));
234 RegCloseKey(hKey);
235
236 if (dwError == ERROR_SUCCESS)
237 {
238 FIXME("Notify the driver!\n");
239
240 pPortData->dwLegacy = dwLegacy;
241 }
242 }
243 }
244
245 dwPortNumber = ComboBox_GetCurSel(GetDlgItem(hwnd, IDC_PARALLEL_NAME));
246 if (dwPortNumber != LB_ERR)
247 {
248 dwPortNumber++;
249 if (dwPortNumber != pPortData->dwPortNumber)
250 {
251 FIXME("Port name changed! LPT%lu --> LPT%lu", pPortData->dwPortNumber, dwPortNumber);
252
253
254 // pPortData->dwPortNumber = dwPortNumber;
255 }
256 }
257 }
258
259
260 static
261 BOOL
262 OnInitDialog(HWND hwnd,
263 WPARAM wParam,
264 LPARAM lParam)
265 {
266 WCHAR szBuffer[256];
267 WCHAR szPortInUse[64];
268 PPORT_DATA pPortData;
269 HWND hwndControl;
270 DWORD dwPortMap;
271 UINT i;
272
273 TRACE("OnInitDialog()\n");
274
275 pPortData = (PPORT_DATA)((LPPROPSHEETPAGEW)lParam)->lParam;
276 if (pPortData == NULL)
277 {
278 ERR("pPortData is NULL\n");
279 return FALSE;
280 }
281
282 SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)pPortData);
283
284 /* Read and parse the port settings */
285 ReadPortSettings(pPortData);
286
287 /* Set the 'Filter Resource Method' radiobuttons */
288 hwndControl = GetDlgItem(hwnd,
289 IDC_TRY_INTERRUPT + pPortData->dwFilterResourceMethod);
290 if (hwndControl)
291 Button_SetCheck(hwndControl, BST_CHECKED);
292
293 /* Disable the 'Enable legacy PNP detection' checkbox */
294 hwndControl = GetDlgItem(hwnd, IDC_PARALLEL_LEGACY);
295 if (hwndControl)
296 {
297 Button_SetCheck(GetDlgItem(hwnd, IDC_PARALLEL_LEGACY),
298 pPortData->dwLegacy ? BST_CHECKED : BST_UNCHECKED);
299 }
300
301 LoadStringW(hInstance, IDS_PORT_IN_USE, szPortInUse, ARRAYSIZE(szPortInUse));
302
303 /* Fill the 'LPT Port Number' combobox */
304 hwndControl = GetDlgItem(hwnd, IDC_PARALLEL_NAME);
305 if (hwndControl)
306 {
307 GetUsedPorts(&dwPortMap);
308
309 for (i = 1; i < 4; i++)
310 {
311 swprintf(szBuffer, L"LPT%lu", i);
312
313 if ((dwPortMap & (1 << i)) && (pPortData->dwPortNumber != i))
314 wcscat(szBuffer, szPortInUse);
315
316 ComboBox_AddString(hwndControl, szBuffer);
317
318 if (_wcsicmp(pPortData->szPortName, szBuffer) == 0)
319 pPortData->dwPortNumber = i;
320 }
321
322 if (pPortData->dwPortNumber != 0)
323 {
324 ComboBox_SetCurSel(hwndControl, pPortData->dwPortNumber - 1);
325 }
326 }
327
328 return TRUE;
329 }
330
331
332 static
333 VOID
334 OnNotify(
335 HWND hwnd,
336 WPARAM wParam,
337 LPARAM lParam)
338 {
339 PPORT_DATA pPortData;
340
341 TRACE("OnNotify()\n");
342
343 pPortData = (PPORT_DATA)GetWindowLongPtr(hwnd, DWLP_USER);
344 if (pPortData == NULL)
345 {
346 ERR("pPortData is NULL\n");
347 return;
348 }
349
350 if (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY)
351 {
352 TRACE("PSN_APPLY!\n");
353 WritePortSettings(hwnd, pPortData);
354 }
355 }
356
357
358 static
359 VOID
360 OnDestroy(
361 HWND hwnd)
362 {
363 PPORT_DATA pPortData;
364
365 TRACE("OnDestroy()\n");
366
367 pPortData = (PPORT_DATA)GetWindowLongPtr(hwnd, DWLP_USER);
368 if (pPortData == NULL)
369 {
370 ERR("pPortData is NULL\n");
371 return;
372 }
373
374 HeapFree(GetProcessHeap(), 0, pPortData);
375 SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)NULL);
376 }
377
378
379 static
380 INT_PTR
381 CALLBACK
382 ParallelSettingsDlgProc(HWND hwnd,
383 UINT uMsg,
384 WPARAM wParam,
385 LPARAM lParam)
386 {
387 TRACE("ParallelSettingsDlgProc()\n");
388
389 switch (uMsg)
390 {
391 case WM_INITDIALOG:
392 return OnInitDialog(hwnd, wParam, lParam);
393
394 case WM_NOTIFY:
395 OnNotify(hwnd, wParam, lParam);
396 break;
397
398 case WM_DESTROY:
399 OnDestroy(hwnd);
400 break;
401 }
402
403 return FALSE;
404 }
405
406
407 BOOL
408 WINAPI
409 ParallelPortPropPageProvider(PSP_PROPSHEETPAGE_REQUEST lpPropSheetPageRequest,
410 LPFNADDPROPSHEETPAGE lpfnAddPropSheetPageProc,
411 LPARAM lParam)
412 {
413 PROPSHEETPAGEW PropSheetPage;
414 HPROPSHEETPAGE hPropSheetPage;
415 PPORT_DATA pPortData;
416
417 TRACE("ParallelPortPropPageProvider(%p %p %lx)\n",
418 lpPropSheetPageRequest, lpfnAddPropSheetPageProc, lParam);
419
420 pPortData = HeapAlloc(GetProcessHeap(),
421 HEAP_ZERO_MEMORY,
422 sizeof(PORT_DATA));
423 if (pPortData == NULL)
424 {
425 ERR("Port data allocation failed!\n");
426 return FALSE;
427 }
428
429 pPortData->DeviceInfoSet = lpPropSheetPageRequest->DeviceInfoSet;
430 pPortData->DeviceInfoData = lpPropSheetPageRequest->DeviceInfoData;
431
432 if (lpPropSheetPageRequest->PageRequested == SPPSR_ENUM_ADV_DEVICE_PROPERTIES)
433 {
434 TRACE("SPPSR_ENUM_ADV_DEVICE_PROPERTIES\n");
435
436 PropSheetPage.dwSize = sizeof(PROPSHEETPAGEW);
437 PropSheetPage.dwFlags = 0;
438 PropSheetPage.hInstance = hInstance;
439 PropSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_PARALLELSETTINGS);
440 PropSheetPage.pfnDlgProc = ParallelSettingsDlgProc;
441 PropSheetPage.lParam = (LPARAM)pPortData;
442 PropSheetPage.pfnCallback = NULL;
443
444 hPropSheetPage = CreatePropertySheetPageW(&PropSheetPage);
445 if (hPropSheetPage == NULL)
446 {
447 ERR("CreatePropertySheetPageW() failed!\n");
448 return FALSE;
449 }
450
451 if (!(*lpfnAddPropSheetPageProc)(hPropSheetPage, lParam))
452 {
453 ERR("lpfnAddPropSheetPageProc() failed!\n");
454 DestroyPropertySheetPage(hPropSheetPage);
455 return FALSE;
456 }
457 }
458
459 TRACE("Done!\n");
460
461 return TRUE;
462 }
463
464 /* EOF */