X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=dll%2Fwin32%2Fmsports%2Fparallel.c;h=b06fd9eef6ee116b86d34f30013648cc129a8dbb;hp=4764a8ccc76f154d456a0b411a54bc886d83c2a4;hb=c603c54ab00fc3064526dd64f3c0dfbfd44fbc42;hpb=e5b5525a8a3eb4550044dc06e51e6f184f10d530 diff --git a/dll/win32/msports/parallel.c b/dll/win32/msports/parallel.c index 4764a8ccc76..b06fd9eef6e 100644 --- a/dll/win32/msports/parallel.c +++ b/dll/win32/msports/parallel.c @@ -8,17 +8,464 @@ #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 @@ -33,6 +480,14 @@ ParallelSettingsDlgProc(HWND hwnd, { case WM_INITDIALOG: return OnInitDialog(hwnd, wParam, lParam); + + case WM_NOTIFY: + OnNotify(hwnd, wParam, lParam); + break; + + case WM_DESTROY: + OnDestroy(hwnd); + break; } return FALSE; @@ -47,10 +502,23 @@ ParallelPortPropPageProvider(PSP_PROPSHEETPAGE_REQUEST lpPropSheetPageRequest, { 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"); @@ -60,19 +528,19 @@ ParallelPortPropPageProvider(PSP_PROPSHEETPAGE_REQUEST lpPropSheetPageRequest, 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; }