#include "precomp.h"
+
+typedef struct _PORT_DATA
+{
+ HDEVINFO DeviceInfoSet;
+ PSP_DEVINFO_DATA DeviceInfoData;
+
+ WCHAR szPortName[16];
+ DWORD dwPortNumber;
+ DWORD dwFilterResourceMethod;
+ DWORD dwLegacy;
+
+} PORT_DATA, *PPORT_DATA;
+
+
+static
+VOID
+GetUsedPorts(
+ PDWORD pPortMap)
+{
+ WCHAR szDeviceName[64];
+ WCHAR szDosDeviceName[64];
+ DWORD dwIndex, dwType, dwPortNumber;
+ DWORD dwDeviceNameSize, dwDosDeviceNameSize;
+ PWSTR ptr;
+ HKEY hKey;
+ DWORD dwError;
+
+ *pPortMap = 0;
+
+ dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"Hardware\\DeviceMap\\PARALLEL PORTS",
+ 0,
+ KEY_READ,
+ &hKey);
+ if (dwError == ERROR_SUCCESS)
+ {
+ for (dwIndex = 0; ; dwIndex++)
+ {
+ dwDeviceNameSize = ARRAYSIZE(szDeviceName);
+ dwDosDeviceNameSize = sizeof(szDosDeviceName);
+ dwError = RegEnumValueW(hKey,
+ dwIndex,
+ szDeviceName,
+ &dwDeviceNameSize,
+ NULL,
+ &dwType,
+ (LPBYTE)szDosDeviceName,
+ &dwDosDeviceNameSize);
+ if (dwError != ERROR_SUCCESS)
+ break;
+
+ if (dwType == REG_SZ)
+ {
+ TRACE("%S --> %S\n", szDeviceName, szDosDeviceName);
+ if (_wcsnicmp(szDosDeviceName, L"\\DosDevices\\LPT", wcslen(L"\\DosDevices\\LPT")) == 0)
+ {
+ ptr = szDosDeviceName + wcslen(L"\\DosDevices\\LPT");
+ if (wcschr(ptr, L'.') == NULL)
+ {
+ TRACE("Device number %S\n", ptr);
+ dwPortNumber = wcstoul(ptr, NULL, 10);
+ if (dwPortNumber != 0)
+ {
+ *pPortMap |=(1 << dwPortNumber);
+ }
+ }
+ }
+ }
+ }
+
+ RegCloseKey(hKey);
+ }
+
+ TRACE("Done\n");
+}
+
+
+static
+VOID
+ReadPortSettings(
+ PPORT_DATA pPortData)
+{
+ DWORD dwSize;
+ HKEY hKey;
+ DWORD dwError;
+
+ TRACE("ReadPortSettings(%p)\n", pPortData);
+
+ pPortData->dwFilterResourceMethod = 1; /* Never use an interrupt */
+ pPortData->dwLegacy = 0; /* Disabled */
+ pPortData->dwPortNumber = 0; /* Unknown */
+
+ hKey = SetupDiOpenDevRegKey(pPortData->DeviceInfoSet,
+ pPortData->DeviceInfoData,
+ DICS_FLAG_GLOBAL,
+ 0,
+ DIREG_DEV,
+ KEY_READ);
+ if (hKey != INVALID_HANDLE_VALUE)
+ {
+ dwSize = sizeof(pPortData->szPortName);
+ dwError = RegQueryValueExW(hKey,
+ L"PortName",
+ NULL,
+ NULL,
+ (PBYTE)pPortData->szPortName,
+ &dwSize);
+ if (dwError != ERROR_SUCCESS)
+ {
+ ERR("RegQueryValueExW failed (Error %lu)\n", dwError);
+ }
+
+ dwSize = sizeof(pPortData->dwFilterResourceMethod);
+ dwError = RegQueryValueExW(hKey,
+ L"FilterResourceMethod",
+ NULL,
+ NULL,
+ (PBYTE)&pPortData->dwFilterResourceMethod,
+ &dwSize);
+ if (dwError != ERROR_SUCCESS)
+ {
+ ERR("RegQueryValueExW failed (Error %lu)\n", dwError);
+ }
+
+ RegCloseKey(hKey);
+ }
+
+ dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"SYSTEM\\CurrentControlSet\\Services\\Parport\\Parameters",
+ 0,
+ KEY_READ,
+ &hKey);
+ if (dwError == ERROR_SUCCESS)
+ {
+ dwSize = sizeof(pPortData->dwLegacy);
+ dwError = RegQueryValueExW(hKey,
+ L"ParEnableLegacyZip",
+ NULL,
+ NULL,
+ (PBYTE)&pPortData->dwLegacy,
+ &dwSize);
+ if (dwError != ERROR_SUCCESS)
+ {
+ ERR("RegQueryValueExW failed (Error %lu)\n", dwError);
+ }
+
+ RegCloseKey(hKey);
+ }
+}
+
+
+static
+DWORD
+ChangePortNumber(
+ _In_ PPORT_DATA pPortData,
+ _In_ DWORD dwNewPortNumber)
+{
+ WCHAR szDeviceDescription[256];
+ WCHAR szFriendlyName[256];
+ WCHAR szNewPortName[16];
+ HKEY hDeviceKey = INVALID_HANDLE_VALUE;
+ DWORD dwError;
+
+ /* We are done if old and new port number are the same */
+ if (pPortData->dwPortNumber == dwNewPortNumber)
+ return ERROR_SUCCESS;
+
+ /* Build the new port name */
+ swprintf(szNewPortName, L"LPT%lu", dwNewPortNumber);
+
+ /* Open the devices hardware key */
+ hDeviceKey = SetupDiOpenDevRegKey(pPortData->DeviceInfoSet,
+ pPortData->DeviceInfoData,
+ DICS_FLAG_GLOBAL,
+ 0,
+ DIREG_DEV,
+ KEY_READ | KEY_WRITE);
+ if (hDeviceKey == INVALID_HANDLE_VALUE)
+ {
+ return GetLastError();
+ }
+
+ /* Set the new 'PortName' value */
+ dwError = RegSetValueExW(hDeviceKey,
+ L"PortName",
+ 0,
+ REG_SZ,
+ (LPBYTE)szNewPortName,
+ (wcslen(szNewPortName) + 1) * sizeof(WCHAR));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ /* Save the new port name and number */
+ wcscpy(pPortData->szPortName, szNewPortName);
+ pPortData->dwPortNumber = dwNewPortNumber;
+
+ /* Get the device description... */
+ if (SetupDiGetDeviceRegistryProperty(pPortData->DeviceInfoSet,
+ pPortData->DeviceInfoData,
+ SPDRP_DEVICEDESC,
+ NULL,
+ (PBYTE)szDeviceDescription,
+ sizeof(szDeviceDescription),
+ NULL))
+ {
+ /* ... and use it to build a new friendly name */
+ swprintf(szFriendlyName,
+ L"%s (%s)",
+ szDeviceDescription,
+ szNewPortName);
+ }
+ else
+ {
+ /* ... or build a generic friendly name */
+ swprintf(szFriendlyName,
+ L"Parallel Port (%s)",
+ szNewPortName);
+ }
+
+ /* Set the friendly name for the device */
+ SetupDiSetDeviceRegistryProperty(pPortData->DeviceInfoSet,
+ pPortData->DeviceInfoData,
+ SPDRP_FRIENDLYNAME,
+ (PBYTE)szFriendlyName,
+ (wcslen(szFriendlyName) + 1) * sizeof(WCHAR));
+
+done:
+ if (hDeviceKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hDeviceKey);
+
+ return dwError;
+}
+
+
+static
+VOID
+WritePortSettings(
+ HWND hwnd,
+ PPORT_DATA pPortData)
+{
+ DWORD dwDisposition;
+ DWORD dwFilterResourceMethod;
+ DWORD dwLegacy;
+ DWORD dwPortNumber;
+ DWORD dwPortMap;
+ HKEY hKey;
+ DWORD dwError;
+
+ TRACE("WritePortSettings(%p)\n", pPortData);
+
+ dwFilterResourceMethod = 1;
+ if (Button_GetCheck(GetDlgItem(hwnd, IDC_TRY_INTERRUPT)) == BST_CHECKED)
+ dwFilterResourceMethod = 0;
+ else if (Button_GetCheck(GetDlgItem(hwnd, IDC_NEVER_INTERRUPT)) == BST_CHECKED)
+ dwFilterResourceMethod = 1;
+ else if (Button_GetCheck(GetDlgItem(hwnd, IDC_ANY_INTERRUPT)) == BST_CHECKED)
+ dwFilterResourceMethod = 2;
+
+ if (dwFilterResourceMethod != pPortData->dwFilterResourceMethod)
+ {
+ hKey = SetupDiOpenDevRegKey(pPortData->DeviceInfoSet,
+ pPortData->DeviceInfoData,
+ DICS_FLAG_GLOBAL,
+ 0,
+ DIREG_DEV,
+ KEY_WRITE);
+ if (hKey != INVALID_HANDLE_VALUE)
+ {
+ dwError = RegSetValueExW(hKey,
+ L"FilterResourceMethod",
+ 0,
+ REG_DWORD,
+ (PBYTE)&dwFilterResourceMethod,
+ sizeof(dwFilterResourceMethod));
+ if (dwError != ERROR_SUCCESS)
+ {
+ ERR("RegSetValueExW failed (Error %lu)\n", dwError);
+ }
+
+ RegCloseKey(hKey);
+ pPortData->dwFilterResourceMethod = dwFilterResourceMethod;
+ }
+ }
+
+ dwLegacy = 0;
+ if (Button_GetCheck(GetDlgItem(hwnd, IDC_PARALLEL_LEGACY)) == BST_CHECKED)
+ dwLegacy = 1;
+
+ if (dwLegacy != pPortData->dwLegacy)
+ {
+ dwError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
+ L"SYSTEM\\CurrentControlSet\\Services\\Parport\\Parameters",
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_WRITE,
+ NULL,
+ &hKey,
+ &dwDisposition);
+ if (dwError == ERROR_SUCCESS)
+ {
+ dwError = RegSetValueExW(hKey,
+ L"ParEnableLegacyZip",
+ 0,
+ REG_DWORD,
+ (LPBYTE)&dwLegacy,
+ sizeof(dwLegacy));
+ RegCloseKey(hKey);
+
+ if (dwError == ERROR_SUCCESS)
+ {
+ FIXME("Notify the driver!\n");
+
+ pPortData->dwLegacy = dwLegacy;
+ }
+ }
+ }
+
+ dwPortNumber = ComboBox_GetCurSel(GetDlgItem(hwnd, IDC_PARALLEL_NAME));
+ if (dwPortNumber != LB_ERR)
+ {
+ dwPortNumber++;
+ if (dwPortNumber != pPortData->dwPortNumber)
+ {
+ GetUsedPorts(&dwPortMap);
+
+ if (dwPortMap & 1 << dwPortNumber)
+ {
+ ERR("Port LPT%lu is already in use!\n", dwPortNumber);
+ return;
+ }
+
+ ChangePortNumber(pPortData,
+ dwPortNumber);
+ }
+ }
+}
+
+
static
BOOL
OnInitDialog(HWND hwnd,
WPARAM wParam,
LPARAM lParam)
{
- TRACE("Port_OnInit()\n");
+ WCHAR szBuffer[256];
+ WCHAR szPortInUse[64];
+ PPORT_DATA pPortData;
+ HWND hwndControl;
+ DWORD dwPortMap;
+ UINT i;
+
+ TRACE("OnInitDialog()\n");
+
+ pPortData = (PPORT_DATA)((LPPROPSHEETPAGEW)lParam)->lParam;
+ if (pPortData == NULL)
+ {
+ ERR("pPortData is NULL\n");
+ return FALSE;
+ }
+
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)pPortData);
+
+ /* Read and parse the port settings */
+ ReadPortSettings(pPortData);
+
+ /* Set the 'Filter Resource Method' radiobuttons */
+ hwndControl = GetDlgItem(hwnd,
+ IDC_TRY_INTERRUPT + pPortData->dwFilterResourceMethod);
+ if (hwndControl)
+ Button_SetCheck(hwndControl, BST_CHECKED);
+
+ /* Disable the 'Enable legacy PNP detection' checkbox */
+ hwndControl = GetDlgItem(hwnd, IDC_PARALLEL_LEGACY);
+ if (hwndControl)
+ {
+ Button_SetCheck(GetDlgItem(hwnd, IDC_PARALLEL_LEGACY),
+ pPortData->dwLegacy ? BST_CHECKED : BST_UNCHECKED);
+ }
+
+ LoadStringW(hInstance, IDS_PORT_IN_USE, szPortInUse, ARRAYSIZE(szPortInUse));
+
+ /* Fill the 'LPT Port Number' combobox */
+ hwndControl = GetDlgItem(hwnd, IDC_PARALLEL_NAME);
+ if (hwndControl)
+ {
+ GetUsedPorts(&dwPortMap);
+
+ for (i = 1; i < 4; i++)
+ {
+ swprintf(szBuffer, L"LPT%lu", i);
+
+ if ((dwPortMap & (1 << i)) && (pPortData->dwPortNumber != i))
+ wcscat(szBuffer, szPortInUse);
+
+ ComboBox_AddString(hwndControl, szBuffer);
+
+ if (_wcsicmp(pPortData->szPortName, szBuffer) == 0)
+ pPortData->dwPortNumber = i;
+ }
+
+ if (pPortData->dwPortNumber != 0)
+ {
+ ComboBox_SetCurSel(hwndControl, pPortData->dwPortNumber - 1);
+ }
+ }
+
return TRUE;
}
+static
+VOID
+OnNotify(
+ HWND hwnd,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ PPORT_DATA pPortData;
+
+ TRACE("OnNotify()\n");
+
+ pPortData = (PPORT_DATA)GetWindowLongPtr(hwnd, DWLP_USER);
+ if (pPortData == NULL)
+ {
+ ERR("pPortData is NULL\n");
+ return;
+ }
+
+ if (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY)
+ {
+ TRACE("PSN_APPLY!\n");
+ WritePortSettings(hwnd, pPortData);
+ }
+}
+
+
+static
+VOID
+OnDestroy(
+ HWND hwnd)
+{
+ PPORT_DATA pPortData;
+
+ TRACE("OnDestroy()\n");
+
+ pPortData = (PPORT_DATA)GetWindowLongPtr(hwnd, DWLP_USER);
+ if (pPortData == NULL)
+ {
+ ERR("pPortData is NULL\n");
+ return;
+ }
+
+ HeapFree(GetProcessHeap(), 0, pPortData);
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)NULL);
+}
+
+
static
INT_PTR
CALLBACK
{
case WM_INITDIALOG:
return OnInitDialog(hwnd, wParam, lParam);
+
+ case WM_NOTIFY:
+ OnNotify(hwnd, wParam, lParam);
+ break;
+
+ case WM_DESTROY:
+ OnDestroy(hwnd);
+ break;
}
return FALSE;
{
PROPSHEETPAGEW PropSheetPage;
HPROPSHEETPAGE hPropSheetPage;
+ PPORT_DATA pPortData;
TRACE("ParallelPortPropPageProvider(%p %p %lx)\n",
lpPropSheetPageRequest, lpfnAddPropSheetPageProc, lParam);
+ pPortData = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof(PORT_DATA));
+ if (pPortData == NULL)
+ {
+ ERR("Port data allocation failed!\n");
+ return FALSE;
+ }
+
+ pPortData->DeviceInfoSet = lpPropSheetPageRequest->DeviceInfoSet;
+ pPortData->DeviceInfoData = lpPropSheetPageRequest->DeviceInfoData;
+
if (lpPropSheetPageRequest->PageRequested == SPPSR_ENUM_ADV_DEVICE_PROPERTIES)
{
TRACE("SPPSR_ENUM_ADV_DEVICE_PROPERTIES\n");
PropSheetPage.hInstance = hInstance;
PropSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_PARALLELSETTINGS);
PropSheetPage.pfnDlgProc = ParallelSettingsDlgProc;
- PropSheetPage.lParam = 0;
+ PropSheetPage.lParam = (LPARAM)pPortData;
PropSheetPage.pfnCallback = NULL;
hPropSheetPage = CreatePropertySheetPageW(&PropSheetPage);
if (hPropSheetPage == NULL)
{
- TRACE("CreatePropertySheetPageW() failed!\n");
+ ERR("CreatePropertySheetPageW() failed!\n");
return FALSE;
}
if (!(*lpfnAddPropSheetPageProc)(hPropSheetPage, lParam))
{
- TRACE("lpfnAddPropSheetPageProc() failed!\n");
+ ERR("lpfnAddPropSheetPageProc() failed!\n");
DestroyPropertySheetPage(hPropSheetPage);
return FALSE;
}