/** * @name _HandleSetDefaultCommConfig * * Sets the default configuration of a legacy port. Checks for granted SERVER_ACCESS_ADMINISTER access. * You have to supply the port name (with colon!) in XcvOpenPort. * The opposite function is _HandleGetDefaultCommConfig. * * @param pXcv * Pointer to the LOCALMON_XCV structure of the currently opened Xcv port. * * @param pInputData * Pointer to the COMMCONFIG structure that shall be passed to SetDefaultCommConfigW. * * @param pcbOutputNeeded * Pointer to a DWORD that will be zeroed on return. * * @return * An error code indicating success or failure. */ static DWORD _HandleSetDefaultCommConfig(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded) { DWORD dwErrorCode; HANDLE hToken = NULL; LPCOMMCONFIG pCommConfig; PWSTR pwszPortNameWithoutColon = NULL; // Sanity checks // pwszObject needs to be at least 2 characters long to be a port name with a trailing colon. if (!pXcv || !pXcv->pwszObject || !pXcv->pwszObject[0] || !pXcv->pwszObject[1] || !pInputData || !pcbOutputNeeded) { dwErrorCode = ERROR_INVALID_PARAMETER; goto Cleanup; } *pcbOutputNeeded = 0; // This action can only happen at SERVER_ACCESS_ADMINISTER access level. if (!(pXcv->GrantedAccess & SERVER_ACCESS_ADMINISTER)) { dwErrorCode = ERROR_ACCESS_DENIED; goto Cleanup; } // SetDefaultCommConfigW needs the port name without colon. dwErrorCode = GetPortNameWithoutColon(pXcv->pwszObject, &pwszPortNameWithoutColon); if (dwErrorCode != ERROR_SUCCESS) goto Cleanup; // Switch to the SYSTEM context for setting the port configuration. hToken = RevertToPrinterSelf(); if (!hToken) { dwErrorCode = GetLastError(); ERR("RevertToPrinterSelf failed with error %lu!\n", dwErrorCode); goto Cleanup; } // Finally pass the parameters to SetDefaultCommConfigW. pCommConfig = (LPCOMMCONFIG)pInputData; if (!SetDefaultCommConfigW(pwszPortNameWithoutColon, pCommConfig, pCommConfig->dwSize)) { dwErrorCode = GetLastError(); ERR("SetDefaultCommConfigW failed with error %lu!\n", dwErrorCode); goto Cleanup; } dwErrorCode = ERROR_SUCCESS; Cleanup: if (hToken) ImpersonatePrinterClient(hToken); if (pwszPortNameWithoutColon) DllFreeSplMem(pwszPortNameWithoutColon); return dwErrorCode; }
/*********************************************************************** * SetDefaultCommConfigA (KERNEL32.@) * * Initializes the default configuration for a communication device. * * See SetDefaultCommConfigW. * */ BOOL WINAPI SetDefaultCommConfigA(LPCSTR lpszDevice, LPCOMMCONFIG lpCommConfig, DWORD dwSize) { BOOL r; LPWSTR lpDeviceW = NULL; DWORD len; TRACE("(%s, %p, %u)\n", debugstr_a(lpszDevice), lpCommConfig, dwSize); if (lpszDevice) { len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 ); lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len ); } r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize); HeapFree( GetProcessHeap(), 0, lpDeviceW ); return r; }
/***************************************************** * localmon_XcvDataPort [exported through MONITOREX] * * Execute command through a Communication-Channel * * PARAMS * hXcv [i] The Handle to work with * pszDataName [i] Name of the command to execute * pInputData [i] Buffer for extra Input Data (needed only for some commands) * cbInputData [i] Size in Bytes of Buffer at pInputData * pOutputData [o] Buffer to receive additional Data (needed only for some commands) * cbOutputData [i] Size in Bytes of Buffer at pOutputData * pcbOutputNeeded [o] PTR to receive the minimal Size in Bytes of the Buffer at pOutputData * * RETURNS * Success: ERROR_SUCCESS * Failure: win32 error code * * NOTES * * Minimal List of commands, that every Printmonitor DLL should support: * *| "MonitorUI" : Return the Name of the Userinterface-DLL as WSTR in pOutputData *| "AddPort" : Add a Port (Name as WSTR in pInputData) *| "DeletePort": Delete a Port (Name as WSTR in pInputData) * * */ static DWORD WINAPI localmon_XcvDataPort(HANDLE hXcv, LPCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded) { WCHAR buffer[16]; /* buffer for a decimal number */ LPWSTR ptr; DWORD res; DWORD needed; HKEY hroot; TRACE("(%p, %s, %p, %d, %p, %d, %p)\n", hXcv, debugstr_w(pszDataName), pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded); if (!lstrcmpW(pszDataName, cmd_AddPortW)) { TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData)); res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot); if (res == ERROR_SUCCESS) { if (does_port_exist((LPWSTR) pInputData)) { RegCloseKey(hroot); TRACE("=> %u\n", ERROR_ALREADY_EXISTS); return ERROR_ALREADY_EXISTS; } res = RegSetValueExW(hroot, (LPWSTR) pInputData, 0, REG_SZ, (const BYTE *) emptyW, sizeof(emptyW)); RegCloseKey(hroot); } TRACE("=> %u\n", res); return res; } if (!lstrcmpW(pszDataName, cmd_ConfigureLPTPortCommandOKW)) { TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData)); res = RegCreateKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_WindowsW, &hroot); if (res == ERROR_SUCCESS) { res = RegSetValueExW(hroot, TransmissionRetryTimeoutW, 0, REG_SZ, pInputData, cbInputData); RegCloseKey(hroot); } return res; } if (!lstrcmpW(pszDataName, cmd_DeletePortW)) { TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData)); res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot); if (res == ERROR_SUCCESS) { res = RegDeleteValueW(hroot, (LPWSTR) pInputData); RegCloseKey(hroot); TRACE("=> %u with %u\n", res, GetLastError() ); return res; } return ERROR_FILE_NOT_FOUND; } if (!lstrcmpW(pszDataName, cmd_GetDefaultCommConfigW)) { TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData)); *pcbOutputNeeded = cbOutputData; res = GetDefaultCommConfigW((LPWSTR) pInputData, (LPCOMMCONFIG) pOutputData, pcbOutputNeeded); TRACE("got %u with %u\n", res, GetLastError() ); return res ? ERROR_SUCCESS : GetLastError(); } if (!lstrcmpW(pszDataName, cmd_GetTransmissionRetryTimeoutW)) { * pcbOutputNeeded = sizeof(DWORD); if (cbOutputData >= sizeof(DWORD)) { /* the w2k resource kit documented a default of 90, but that's wrong */ *((LPDWORD) pOutputData) = 45; res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_WindowsW, &hroot); if (res == ERROR_SUCCESS) { needed = sizeof(buffer) - sizeof(WCHAR); res = RegQueryValueExW(hroot, TransmissionRetryTimeoutW, NULL, NULL, (LPBYTE) buffer, &needed); if ((res == ERROR_SUCCESS) && (buffer[0])) { *((LPDWORD) pOutputData) = strtoulW(buffer, NULL, 0); } RegCloseKey(hroot); } return ERROR_SUCCESS; } return ERROR_INSUFFICIENT_BUFFER; } if (!lstrcmpW(pszDataName, cmd_MonitorUIW)) { * pcbOutputNeeded = sizeof(dllnameuiW); if (cbOutputData >= sizeof(dllnameuiW)) { memcpy(pOutputData, dllnameuiW, sizeof(dllnameuiW)); return ERROR_SUCCESS; } return ERROR_INSUFFICIENT_BUFFER; } if (!lstrcmpW(pszDataName, cmd_PortIsValidW)) { TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData)); res = get_type_from_name((LPCWSTR) pInputData); TRACE("detected as %u\n", res); /* names, that we have recognized, are valid */ if (res) return ERROR_SUCCESS; /* ERROR_ACCESS_DENIED, ERROR_PATH_NOT_FOUND or something else */ TRACE("=> %u\n", GetLastError()); return GetLastError(); } if (!lstrcmpW(pszDataName, cmd_SetDefaultCommConfigW)) { /* get the portname from the Handle */ ptr = strchrW(((xcv_t *)hXcv)->nameW, ' '); if (ptr) { ptr++; /* skip the space */ } else { ptr = ((xcv_t *)hXcv)->nameW; } lstrcpynW(buffer, ptr, sizeof(buffer)/sizeof(WCHAR)); if (buffer[0]) buffer[lstrlenW(buffer)-1] = '\0'; /* remove the ':' */ res = SetDefaultCommConfigW(buffer, (LPCOMMCONFIG) pInputData, cbInputData); TRACE("got %u with %u\n", res, GetLastError() ); return res ? ERROR_SUCCESS : GetLastError(); } FIXME("command not supported: %s\n", debugstr_w(pszDataName)); return ERROR_INVALID_PARAMETER; }
/*********************************************************************** * SERIALUI_ConfigDialogProc * * Shows a dialog for configuring a COMM port */ INT_PTR CALLBACK SERIALUI_ConfigDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static const WCHAR szSettings[] = { 'S','e','t','t','i','n','g','s',' ','f','o','r',' ',0 }; WCHAR szTitle[40]; SERIALUI_DialogInfo *info; switch (uMsg) { case WM_INITDIALOG: info = (SERIALUI_DialogInfo*) lParam; if(!info) return FALSE; SetWindowLongPtrW(hWnd, DWLP_USER, lParam); strcpyW( szTitle, szSettings ); strcatW( szTitle, info->lpszDevice ); SetWindowTextW(hWnd, szTitle); SERIALUI_DCBToDialogInfo(hWnd, info); return TRUE; case WM_COMMAND: { WORD wID = LOWORD(wParam); info = (SERIALUI_DialogInfo *) GetWindowLongPtrW(hWnd, DWLP_USER); if(!info) EndDialog(hWnd,0); switch (wID) { case IDOK: SERIALUI_DialogInfoToDCB(hWnd,info); EndDialog(hWnd,1); return TRUE; case IDCANCEL: EndDialog(hWnd,0); return TRUE; /* test code for Get/SetDefaultCommConfig begins */ case ID_GETDEFAULT: { DWORD r,dwConfSize = sizeof (COMMCONFIG); r = GetDefaultCommConfigW(info->lpszDevice, info->lpCommConfig, &dwConfSize); if(!r) MessageBoxA(hWnd,"Failed","GetDefaultCommConfig",MB_OK); } SERIALUI_DCBToDialogInfo(hWnd, info); break; case ID_SETDEFAULT: { DWORD r; SERIALUI_DialogInfoToDCB(hWnd,info); r = SetDefaultCommConfigW(info->lpszDevice, info->lpCommConfig, sizeof (COMMCONFIG)); if(!r) MessageBoxA(hWnd,"Failed","GetDefaultCommConfig",MB_OK); } break; /* test code for Get/SetDefaultCommConfig ends */ } } default: return FALSE; } }