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
12 typedef struct _PORT_DATA
14 HDEVINFO DeviceInfoSet
;
15 PSP_DEVINFO_DATA DeviceInfoData
;
19 DWORD dwFilterResourceMethod
;
22 } PORT_DATA
, *PPORT_DATA
;
30 WCHAR szDeviceName
[64];
31 WCHAR szDosDeviceName
[64];
32 DWORD dwIndex
, dwType
, dwPortNumber
;
33 DWORD dwDeviceNameSize
, dwDosDeviceNameSize
;
40 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
41 L
"Hardware\\DeviceMap\\PARALLEL PORTS",
45 if (dwError
== ERROR_SUCCESS
)
47 for (dwIndex
= 0; ; dwIndex
++)
49 dwDeviceNameSize
= ARRAYSIZE(szDeviceName
);
50 dwDosDeviceNameSize
= sizeof(szDosDeviceName
);
51 dwError
= RegEnumValueW(hKey
,
57 (LPBYTE
)szDosDeviceName
,
58 &dwDosDeviceNameSize
);
59 if (dwError
!= ERROR_SUCCESS
)
64 TRACE("%S --> %S\n", szDeviceName
, szDosDeviceName
);
65 if (_wcsnicmp(szDosDeviceName
, L
"\\DosDevices\\LPT", wcslen(L
"\\DosDevices\\LPT")) == 0)
67 ptr
= szDosDeviceName
+ wcslen(L
"\\DosDevices\\LPT");
68 if (wcschr(ptr
, L
'.') == NULL
)
70 TRACE("Device number %S\n", ptr
);
71 dwPortNumber
= wcstoul(ptr
, NULL
, 10);
72 if (dwPortNumber
!= 0)
74 *pPortMap
|=(1 << dwPortNumber
);
97 TRACE("ReadPortSettings(%p)\n", pPortData
);
99 pPortData
->dwFilterResourceMethod
= 1; /* Never use an interrupt */
100 pPortData
->dwLegacy
= 0; /* Disabled */
101 pPortData
->dwPortNumber
= 0; /* Unknown */
103 hKey
= SetupDiOpenDevRegKey(pPortData
->DeviceInfoSet
,
104 pPortData
->DeviceInfoData
,
109 if (hKey
!= INVALID_HANDLE_VALUE
)
111 dwSize
= sizeof(pPortData
->szPortName
);
112 dwError
= RegQueryValueExW(hKey
,
116 (PBYTE
)pPortData
->szPortName
,
118 if (dwError
!= ERROR_SUCCESS
)
120 ERR("RegQueryValueExW failed (Error %lu)\n", dwError
);
123 dwSize
= sizeof(pPortData
->dwFilterResourceMethod
);
124 dwError
= RegQueryValueExW(hKey
,
125 L
"FilterResourceMethod",
128 (PBYTE
)&pPortData
->dwFilterResourceMethod
,
130 if (dwError
!= ERROR_SUCCESS
)
132 ERR("RegQueryValueExW failed (Error %lu)\n", dwError
);
138 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
139 L
"SYSTEM\\CurrentControlSet\\Services\\Parport\\Parameters",
143 if (dwError
== ERROR_SUCCESS
)
145 dwSize
= sizeof(pPortData
->dwLegacy
);
146 dwError
= RegQueryValueExW(hKey
,
147 L
"ParEnableLegacyZip",
150 (PBYTE
)&pPortData
->dwLegacy
,
152 if (dwError
!= ERROR_SUCCESS
)
154 ERR("RegQueryValueExW failed (Error %lu)\n", dwError
);
165 _In_ PPORT_DATA pPortData
,
166 _In_ DWORD dwNewPortNumber
)
168 WCHAR szDeviceDescription
[256];
169 WCHAR szFriendlyName
[256];
170 WCHAR szNewPortName
[16];
171 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
174 /* We are done if old and new port number are the same */
175 if (pPortData
->dwPortNumber
== dwNewPortNumber
)
176 return ERROR_SUCCESS
;
178 /* Build the new port name */
179 swprintf(szNewPortName
, L
"LPT%lu", dwNewPortNumber
);
181 /* Open the devices hardware key */
182 hDeviceKey
= SetupDiOpenDevRegKey(pPortData
->DeviceInfoSet
,
183 pPortData
->DeviceInfoData
,
187 KEY_READ
| KEY_WRITE
);
188 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
190 return GetLastError();
193 /* Set the new 'PortName' value */
194 dwError
= RegSetValueExW(hDeviceKey
,
198 (LPBYTE
)szNewPortName
,
199 (wcslen(szNewPortName
) + 1) * sizeof(WCHAR
));
200 if (dwError
!= ERROR_SUCCESS
)
203 /* Save the new port name and number */
204 wcscpy(pPortData
->szPortName
, szNewPortName
);
205 pPortData
->dwPortNumber
= dwNewPortNumber
;
207 /* Get the device description... */
208 if (SetupDiGetDeviceRegistryProperty(pPortData
->DeviceInfoSet
,
209 pPortData
->DeviceInfoData
,
212 (PBYTE
)szDeviceDescription
,
213 sizeof(szDeviceDescription
),
216 /* ... and use it to build a new friendly name */
217 swprintf(szFriendlyName
,
224 /* ... or build a generic friendly name */
225 swprintf(szFriendlyName
,
226 L
"Parallel Port (%s)",
230 /* Set the friendly name for the device */
231 SetupDiSetDeviceRegistryProperty(pPortData
->DeviceInfoSet
,
232 pPortData
->DeviceInfoData
,
234 (PBYTE
)szFriendlyName
,
235 (wcslen(szFriendlyName
) + 1) * sizeof(WCHAR
));
238 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
239 RegCloseKey(hDeviceKey
);
249 PPORT_DATA pPortData
)
252 DWORD dwFilterResourceMethod
;
259 TRACE("WritePortSettings(%p)\n", pPortData
);
261 dwFilterResourceMethod
= 1;
262 if (Button_GetCheck(GetDlgItem(hwnd
, IDC_TRY_INTERRUPT
)) == BST_CHECKED
)
263 dwFilterResourceMethod
= 0;
264 else if (Button_GetCheck(GetDlgItem(hwnd
, IDC_NEVER_INTERRUPT
)) == BST_CHECKED
)
265 dwFilterResourceMethod
= 1;
266 else if (Button_GetCheck(GetDlgItem(hwnd
, IDC_ANY_INTERRUPT
)) == BST_CHECKED
)
267 dwFilterResourceMethod
= 2;
269 if (dwFilterResourceMethod
!= pPortData
->dwFilterResourceMethod
)
271 hKey
= SetupDiOpenDevRegKey(pPortData
->DeviceInfoSet
,
272 pPortData
->DeviceInfoData
,
277 if (hKey
!= INVALID_HANDLE_VALUE
)
279 dwError
= RegSetValueExW(hKey
,
280 L
"FilterResourceMethod",
283 (PBYTE
)&dwFilterResourceMethod
,
284 sizeof(dwFilterResourceMethod
));
285 if (dwError
!= ERROR_SUCCESS
)
287 ERR("RegSetValueExW failed (Error %lu)\n", dwError
);
291 pPortData
->dwFilterResourceMethod
= dwFilterResourceMethod
;
296 if (Button_GetCheck(GetDlgItem(hwnd
, IDC_PARALLEL_LEGACY
)) == BST_CHECKED
)
299 if (dwLegacy
!= pPortData
->dwLegacy
)
301 dwError
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
302 L
"SYSTEM\\CurrentControlSet\\Services\\Parport\\Parameters",
305 REG_OPTION_NON_VOLATILE
,
310 if (dwError
== ERROR_SUCCESS
)
312 dwError
= RegSetValueExW(hKey
,
313 L
"ParEnableLegacyZip",
320 if (dwError
== ERROR_SUCCESS
)
322 FIXME("Notify the driver!\n");
324 pPortData
->dwLegacy
= dwLegacy
;
329 dwPortNumber
= ComboBox_GetCurSel(GetDlgItem(hwnd
, IDC_PARALLEL_NAME
));
330 if (dwPortNumber
!= LB_ERR
)
333 if (dwPortNumber
!= pPortData
->dwPortNumber
)
335 GetUsedPorts(&dwPortMap
);
337 if (dwPortMap
& 1 << dwPortNumber
)
339 ERR("Port LPT%lu is already in use!\n", dwPortNumber
);
343 ChangePortNumber(pPortData
,
352 OnInitDialog(HWND hwnd
,
357 WCHAR szPortInUse
[64];
358 PPORT_DATA pPortData
;
363 TRACE("OnInitDialog()\n");
365 pPortData
= (PPORT_DATA
)((LPPROPSHEETPAGEW
)lParam
)->lParam
;
366 if (pPortData
== NULL
)
368 ERR("pPortData is NULL\n");
372 SetWindowLongPtr(hwnd
, DWLP_USER
, (LONG_PTR
)pPortData
);
374 /* Read and parse the port settings */
375 ReadPortSettings(pPortData
);
377 /* Set the 'Filter Resource Method' radiobuttons */
378 hwndControl
= GetDlgItem(hwnd
,
379 IDC_TRY_INTERRUPT
+ pPortData
->dwFilterResourceMethod
);
381 Button_SetCheck(hwndControl
, BST_CHECKED
);
383 /* Disable the 'Enable legacy PNP detection' checkbox */
384 hwndControl
= GetDlgItem(hwnd
, IDC_PARALLEL_LEGACY
);
387 Button_SetCheck(GetDlgItem(hwnd
, IDC_PARALLEL_LEGACY
),
388 pPortData
->dwLegacy
? BST_CHECKED
: BST_UNCHECKED
);
391 LoadStringW(hInstance
, IDS_PORT_IN_USE
, szPortInUse
, ARRAYSIZE(szPortInUse
));
393 /* Fill the 'LPT Port Number' combobox */
394 hwndControl
= GetDlgItem(hwnd
, IDC_PARALLEL_NAME
);
397 GetUsedPorts(&dwPortMap
);
399 for (i
= 1; i
< 4; i
++)
401 swprintf(szBuffer
, L
"LPT%lu", i
);
403 if ((dwPortMap
& (1 << i
)) && (pPortData
->dwPortNumber
!= i
))
404 wcscat(szBuffer
, szPortInUse
);
406 ComboBox_AddString(hwndControl
, szBuffer
);
408 if (_wcsicmp(pPortData
->szPortName
, szBuffer
) == 0)
409 pPortData
->dwPortNumber
= i
;
412 if (pPortData
->dwPortNumber
!= 0)
414 ComboBox_SetCurSel(hwndControl
, pPortData
->dwPortNumber
- 1);
429 PPORT_DATA pPortData
;
431 TRACE("OnNotify()\n");
433 pPortData
= (PPORT_DATA
)GetWindowLongPtr(hwnd
, DWLP_USER
);
434 if (pPortData
== NULL
)
436 ERR("pPortData is NULL\n");
440 if (((LPNMHDR
)lParam
)->code
== (UINT
)PSN_APPLY
)
442 TRACE("PSN_APPLY!\n");
443 WritePortSettings(hwnd
, pPortData
);
453 PPORT_DATA pPortData
;
455 TRACE("OnDestroy()\n");
457 pPortData
= (PPORT_DATA
)GetWindowLongPtr(hwnd
, DWLP_USER
);
458 if (pPortData
== NULL
)
460 ERR("pPortData is NULL\n");
464 HeapFree(GetProcessHeap(), 0, pPortData
);
465 SetWindowLongPtr(hwnd
, DWLP_USER
, (LONG_PTR
)NULL
);
472 ParallelSettingsDlgProc(HWND hwnd
,
477 TRACE("ParallelSettingsDlgProc()\n");
482 return OnInitDialog(hwnd
, wParam
, lParam
);
485 OnNotify(hwnd
, wParam
, lParam
);
499 ParallelPortPropPageProvider(PSP_PROPSHEETPAGE_REQUEST lpPropSheetPageRequest
,
500 LPFNADDPROPSHEETPAGE lpfnAddPropSheetPageProc
,
503 PROPSHEETPAGEW PropSheetPage
;
504 HPROPSHEETPAGE hPropSheetPage
;
505 PPORT_DATA pPortData
;
507 TRACE("ParallelPortPropPageProvider(%p %p %lx)\n",
508 lpPropSheetPageRequest
, lpfnAddPropSheetPageProc
, lParam
);
510 pPortData
= HeapAlloc(GetProcessHeap(),
513 if (pPortData
== NULL
)
515 ERR("Port data allocation failed!\n");
519 pPortData
->DeviceInfoSet
= lpPropSheetPageRequest
->DeviceInfoSet
;
520 pPortData
->DeviceInfoData
= lpPropSheetPageRequest
->DeviceInfoData
;
522 if (lpPropSheetPageRequest
->PageRequested
== SPPSR_ENUM_ADV_DEVICE_PROPERTIES
)
524 TRACE("SPPSR_ENUM_ADV_DEVICE_PROPERTIES\n");
526 PropSheetPage
.dwSize
= sizeof(PROPSHEETPAGEW
);
527 PropSheetPage
.dwFlags
= 0;
528 PropSheetPage
.hInstance
= hInstance
;
529 PropSheetPage
.pszTemplate
= MAKEINTRESOURCE(IDD_PARALLELSETTINGS
);
530 PropSheetPage
.pfnDlgProc
= ParallelSettingsDlgProc
;
531 PropSheetPage
.lParam
= (LPARAM
)pPortData
;
532 PropSheetPage
.pfnCallback
= NULL
;
534 hPropSheetPage
= CreatePropertySheetPageW(&PropSheetPage
);
535 if (hPropSheetPage
== NULL
)
537 ERR("CreatePropertySheetPageW() failed!\n");
541 if (!(*lpfnAddPropSheetPageProc
)(hPropSheetPage
, lParam
))
543 ERR("lpfnAddPropSheetPageProc() failed!\n");
544 DestroyPropertySheetPage(hPropSheetPage
);