+
+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);
+ }
+ }
+}
+
+