You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
539 lines
12 KiB
539 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 1990-2003 Microsoft Corporation
|
|
All rights reserved
|
|
|
|
Module Name:
|
|
|
|
config.c
|
|
|
|
Abstract:
|
|
|
|
Handles spooler entry points for adding, deleting, and configuring
|
|
localui ports.
|
|
|
|
// @@BEGIN_DDKSPLIT
|
|
Environment:
|
|
|
|
User Mode -Win32
|
|
|
|
Revision History:
|
|
// @@END_DDKSPLIT
|
|
--*/
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include "spltypes.h"
|
|
#include "localui.h"
|
|
#include "local.h"
|
|
#include "lmon.h"
|
|
|
|
/* From Control Panel's control.h:
|
|
*/
|
|
#define CHILD_PORTS 0
|
|
|
|
/* From cpl.h:
|
|
*/
|
|
#define CPL_INIT 1
|
|
#define CPL_DBLCLK 5
|
|
#define CPL_EXIT 7
|
|
|
|
// @@BEGIN_DDKSPLIT
|
|
/* Hack:
|
|
*/
|
|
// @@END_DDKSPLIT
|
|
#define CHILD_PORTS_HELPID 0
|
|
|
|
/* ConfigCOMPort
|
|
*
|
|
* Calls the Control Panel Ports applet
|
|
* to permit user to set Baud rate etc.
|
|
*/
|
|
typedef void (WINAPI *CFGPROC)(HWND, ULONG, ULONG, ULONG);
|
|
|
|
|
|
BOOL
|
|
ConfigLPTPort(
|
|
HWND hWnd,
|
|
HANDLE hXcv
|
|
);
|
|
|
|
BOOL
|
|
ConfigCOMPort(
|
|
HWND hWnd,
|
|
HANDLE hXcv,
|
|
PCWSTR pszServer,
|
|
PCWSTR pszPortName
|
|
);
|
|
|
|
LPWSTR
|
|
GetPortName(
|
|
HWND hWnd,
|
|
HANDLE hXcv
|
|
);
|
|
|
|
|
|
BOOL
|
|
AddPortUI(
|
|
PCWSTR pszServer,
|
|
HWND hWnd,
|
|
PCWSTR pszMonitorNameIn,
|
|
PWSTR *ppszPortNameOut
|
|
)
|
|
{
|
|
PWSTR pszPortName = NULL;
|
|
BOOL rc = TRUE;
|
|
WCHAR szLocalMonitor[MAX_PATH+1];
|
|
DWORD dwReturn, dwStatus;
|
|
DWORD cbNeeded;
|
|
PRINTER_DEFAULTS Default;
|
|
PWSTR pszServerName = NULL;
|
|
HANDLE hXcv = NULL;
|
|
DWORD dwLastError = ERROR_SUCCESS;
|
|
//
|
|
//
|
|
//
|
|
if (hWnd && !IsWindow (hWnd))
|
|
{
|
|
//
|
|
// Invalid parent window handle causes problems in function with DialogBoxParam call.
|
|
// That function when the handle is bad returns ZERO, the same value as ERROR_SUCCEED.
|
|
// PortNameDlg function calls EndDialog (ERROR_SUCCEES) if everything is alright.
|
|
//
|
|
SetLastError (ERROR_INVALID_WINDOW_HANDLE);
|
|
if (ppszPortNameOut)
|
|
{
|
|
*ppszPortNameOut = NULL;
|
|
}
|
|
return FALSE;
|
|
}
|
|
//
|
|
//
|
|
//
|
|
/* Get the user to enter a port name:
|
|
*/
|
|
|
|
if (!(pszServerName = ConstructXcvName(pszServer, pszMonitorNameIn, L"XcvMonitor"))) {
|
|
rc = FALSE;
|
|
goto Done;
|
|
}
|
|
|
|
Default.pDatatype = NULL;
|
|
Default.pDevMode = NULL;
|
|
Default.DesiredAccess = SERVER_ACCESS_ADMINISTER;
|
|
|
|
if (!(rc = OpenPrinter((PWSTR) pszServerName, &hXcv, &Default))) {
|
|
rc = FALSE;
|
|
goto Done;
|
|
}
|
|
|
|
if (!(pszPortName = GetPortName(hWnd, hXcv))) {
|
|
rc = FALSE;
|
|
goto Done;
|
|
}
|
|
|
|
// We can't Add, Configure, or Delete Remote COM ports
|
|
if (IS_COM_PORT(pszPortName) || IS_LPT_PORT(pszPortName)) {
|
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|
rc = FALSE;
|
|
goto Done;
|
|
}
|
|
|
|
if(IS_COM_PORT(pszPortName))
|
|
CharUpperBuff(pszPortName, 3);
|
|
else if(IS_LPT_PORT(pszPortName))
|
|
CharUpperBuff(pszPortName, 3);
|
|
|
|
rc = XcvData( hXcv,
|
|
L"AddPort",
|
|
(PBYTE) pszPortName,
|
|
(wcslen(pszPortName) + 1)*sizeof(WCHAR),
|
|
(PBYTE) &dwReturn,
|
|
0,
|
|
&cbNeeded,
|
|
&dwStatus);
|
|
|
|
if (rc) {
|
|
if(dwStatus == ERROR_SUCCESS) {
|
|
if(ppszPortNameOut)
|
|
*ppszPortNameOut = AllocSplStr(pszPortName);
|
|
|
|
if(IS_LPT_PORT(pszPortName))
|
|
rc = ConfigLPTPort(hWnd, hXcv);
|
|
else if(IS_COM_PORT(pszPortName))
|
|
rc = ConfigCOMPort(hWnd, hXcv, pszServer, pszPortName);
|
|
|
|
} else if (dwStatus == ERROR_ALREADY_EXISTS) {
|
|
Message( hWnd, MSG_ERROR, IDS_LOCALMONITOR, IDS_PORTALREADYEXISTS_S, pszPortName );
|
|
|
|
} else {
|
|
SetLastError(dwStatus);
|
|
rc = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
Done:
|
|
dwLastError = GetLastError ();
|
|
|
|
FreeSplStr(pszPortName);
|
|
FreeSplMem(pszServerName);
|
|
|
|
if (hXcv)
|
|
ClosePrinter(hXcv);
|
|
|
|
SetLastError (dwLastError);
|
|
return rc;
|
|
}
|
|
|
|
|
|
BOOL
|
|
DeletePortUI(
|
|
PCWSTR pszServer,
|
|
HWND hWnd,
|
|
PCWSTR pszPortName
|
|
)
|
|
{
|
|
PRINTER_DEFAULTS Default;
|
|
PWSTR pszServerName = NULL;
|
|
DWORD dwOutput;
|
|
DWORD cbNeeded;
|
|
BOOL bRet;
|
|
HANDLE hXcv = NULL;
|
|
DWORD dwStatus;
|
|
DWORD dwLastError = ERROR_SUCCESS;
|
|
//
|
|
//
|
|
//
|
|
if (hWnd && !IsWindow (hWnd))
|
|
{
|
|
SetLastError (ERROR_INVALID_WINDOW_HANDLE);
|
|
return FALSE;
|
|
}
|
|
//
|
|
//
|
|
//
|
|
if (!(pszServerName = ConstructXcvName(pszServer, pszPortName, L"XcvPort"))) {
|
|
bRet = FALSE;
|
|
goto Done;
|
|
}
|
|
|
|
Default.pDatatype = NULL;
|
|
Default.pDevMode = NULL;
|
|
Default.DesiredAccess = SERVER_ACCESS_ADMINISTER;
|
|
|
|
if (!(bRet = OpenPrinter((PWSTR) pszServerName, &hXcv, &Default)))
|
|
goto Done;
|
|
|
|
// Since we can't Add or Configure Remote COM ports, let's not allow deletion either
|
|
|
|
if (IS_COM_PORT(pszPortName) || IS_LPT_PORT(pszPortName)) {
|
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|
bRet = FALSE;
|
|
|
|
} else {
|
|
|
|
bRet = XcvData( hXcv,
|
|
L"DeletePort",
|
|
(PBYTE) pszPortName,
|
|
(wcslen(pszPortName) + 1)*sizeof(WCHAR),
|
|
(PBYTE) &dwOutput,
|
|
0,
|
|
&cbNeeded,
|
|
&dwStatus);
|
|
|
|
if (!bRet && (ERROR_BUSY == dwStatus))
|
|
{
|
|
//
|
|
// Port cannot be deleted cause it is in use.
|
|
//
|
|
ErrorMessage (
|
|
hWnd,
|
|
dwStatus
|
|
);
|
|
//
|
|
// Error is handled here and caller does not need to do anything
|
|
//
|
|
SetLastError (ERROR_CANCELLED);
|
|
}
|
|
else if (bRet && (ERROR_SUCCESS != dwStatus))
|
|
{
|
|
SetLastError(dwStatus);
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
|
|
Done:
|
|
dwLastError = GetLastError ();
|
|
if (hXcv)
|
|
ClosePrinter(hXcv);
|
|
|
|
FreeSplMem(pszServerName);
|
|
|
|
SetLastError (dwLastError);
|
|
return bRet;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ConfigurePortUI
|
|
*
|
|
*/
|
|
BOOL
|
|
ConfigurePortUI(
|
|
PCWSTR pName,
|
|
HWND hWnd,
|
|
PCWSTR pPortName
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
PRINTER_DEFAULTS Default;
|
|
PWSTR pServerName = NULL;
|
|
HANDLE hXcv = NULL;
|
|
DWORD dwLastError = ERROR_SUCCESS;
|
|
//
|
|
//
|
|
//
|
|
if (hWnd && !IsWindow (hWnd))
|
|
{
|
|
SetLastError (ERROR_INVALID_WINDOW_HANDLE);
|
|
return FALSE;
|
|
}
|
|
//
|
|
//
|
|
//
|
|
if (!(pServerName = ConstructXcvName(pName, pPortName, L"XcvPort"))) {
|
|
bRet = FALSE;
|
|
goto Done;
|
|
}
|
|
|
|
Default.pDatatype = NULL;
|
|
Default.pDevMode = NULL;
|
|
Default.DesiredAccess = SERVER_ACCESS_ADMINISTER;
|
|
|
|
if (!(bRet = OpenPrinter((PWSTR) pServerName, &hXcv, &Default)))
|
|
goto Done;
|
|
|
|
|
|
if( IS_LPT_PORT( (PWSTR) pPortName ) )
|
|
bRet = ConfigLPTPort(hWnd, hXcv);
|
|
else if( IS_COM_PORT( (PWSTR) pPortName ) )
|
|
bRet = ConfigCOMPort(hWnd, hXcv, pName, pPortName);
|
|
else {
|
|
Message( hWnd, MSG_INFORMATION, IDS_LOCALMONITOR,
|
|
IDS_NOTHING_TO_CONFIGURE );
|
|
|
|
SetLastError(ERROR_CANCELLED);
|
|
bRet = FALSE;
|
|
}
|
|
|
|
Done:
|
|
dwLastError = GetLastError ();
|
|
|
|
FreeSplMem(pServerName);
|
|
|
|
if (hXcv) {
|
|
ClosePrinter(hXcv);
|
|
hXcv = NULL;
|
|
}
|
|
SetLastError (dwLastError);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
|
|
/* ConfigLPTPort
|
|
*
|
|
* Calls a dialog box which prompts the user to enter timeout and retry
|
|
* values for the port concerned.
|
|
* The dialog writes the information to the registry (win.ini for now).
|
|
*/
|
|
BOOL
|
|
ConfigLPTPort(
|
|
HWND hWnd,
|
|
HANDLE hXcv
|
|
)
|
|
{
|
|
PORTDIALOG Port;
|
|
INT iRet;
|
|
//
|
|
//
|
|
ZeroMemory (&Port, sizeof (Port));
|
|
iRet = -1;
|
|
//
|
|
//
|
|
Port.hXcv = hXcv;
|
|
|
|
iRet = (INT)DialogBoxParam(hInst, MAKEINTRESOURCE( DLG_CONFIGURE_LPT ),
|
|
hWnd, ConfigureLPTPortDlg, (LPARAM) &Port);
|
|
|
|
if (iRet == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// DialogBoxParam returns zero if hWnd is invalid.
|
|
// ERROR_SUCCESS is equal to zero.
|
|
// => We need to check LastError too.
|
|
//
|
|
return ERROR_SUCCESS == GetLastError ();
|
|
}
|
|
|
|
if (iRet == -1)
|
|
return FALSE;
|
|
|
|
SetLastError(iRet);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/* ConfigCOMPort
|
|
*
|
|
*/
|
|
BOOL
|
|
ConfigCOMPort(
|
|
HWND hWnd,
|
|
HANDLE hXcv,
|
|
PCWSTR pszServer,
|
|
PCWSTR pszPortName
|
|
)
|
|
{
|
|
DWORD dwStatus;
|
|
BOOL bRet = FALSE;
|
|
COMMCONFIG CommConfig;
|
|
COMMCONFIG *pCommConfig = &CommConfig;
|
|
COMMCONFIG *pCC = NULL;
|
|
PWSTR pszPort = NULL;
|
|
DWORD cbNeeded;
|
|
|
|
|
|
// GetDefaultCommConfig can't handle trailing :, so remove it!
|
|
if (!(pszPort = (PWSTR) AllocSplStr(pszPortName)))
|
|
goto Done;
|
|
pszPort[wcslen(pszPort) - 1] = L'\0';
|
|
|
|
cbNeeded = sizeof CommConfig;
|
|
|
|
if (!XcvData( hXcv,
|
|
L"GetDefaultCommConfig",
|
|
(PBYTE) pszPort,
|
|
(wcslen(pszPort) + 1)*sizeof *pszPort,
|
|
(PBYTE) pCommConfig,
|
|
cbNeeded,
|
|
&cbNeeded,
|
|
&dwStatus))
|
|
goto Done;
|
|
|
|
if (dwStatus != ERROR_SUCCESS) {
|
|
if (dwStatus != ERROR_INSUFFICIENT_BUFFER) {
|
|
SetLastError(dwStatus);
|
|
goto Done;
|
|
}
|
|
|
|
if (!(pCommConfig = pCC = AllocSplMem(cbNeeded)))
|
|
goto Done;
|
|
|
|
if (!XcvData( hXcv,
|
|
L"GetDefaultCommConfig",
|
|
(PBYTE) pszPort,
|
|
(wcslen(pszPort) + 1)*sizeof *pszPort,
|
|
(PBYTE) pCommConfig,
|
|
cbNeeded,
|
|
&cbNeeded,
|
|
&dwStatus))
|
|
goto Done;
|
|
|
|
if (dwStatus != ERROR_SUCCESS) {
|
|
SetLastError(dwStatus);
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
if (CommConfigDialog(pszPort, hWnd, pCommConfig)) {
|
|
if (!XcvData( hXcv,
|
|
L"SetDefaultCommConfig",
|
|
(PBYTE) pCommConfig,
|
|
pCommConfig->dwSize,
|
|
(PBYTE) NULL,
|
|
0,
|
|
&cbNeeded,
|
|
&dwStatus))
|
|
goto Done;
|
|
|
|
if (dwStatus != ERROR_SUCCESS) {
|
|
SetLastError(dwStatus);
|
|
goto Done;
|
|
}
|
|
bRet = TRUE;
|
|
}
|
|
|
|
|
|
Done:
|
|
|
|
FreeSplMem(pCC);
|
|
FreeSplStr(pszPort);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Support routines
|
|
//
|
|
|
|
|
|
/* GetPortName
|
|
*
|
|
* Puts up a dialog containing a free entry field.
|
|
* The dialog allocates a string for the name, if a selection is made.
|
|
*/
|
|
|
|
LPWSTR
|
|
GetPortName(
|
|
HWND hWnd,
|
|
HANDLE hXcv
|
|
)
|
|
{
|
|
PORTDIALOG Port;
|
|
INT Result;
|
|
LPWSTR pszPort = NULL;
|
|
//
|
|
//
|
|
ZeroMemory (&Port, sizeof (Port));
|
|
Result = -1;
|
|
//
|
|
//
|
|
Port.hXcv = hXcv;
|
|
|
|
Result = (INT)DialogBoxParam(hInst,
|
|
MAKEINTRESOURCE(DLG_PORTNAME),
|
|
hWnd,
|
|
PortNameDlg,
|
|
(LPARAM)&Port);
|
|
|
|
if (Result == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// DialogBoxParam returns zero if hWnd is invalid.
|
|
// ERROR_SUCCESS is equal to zero.
|
|
// => We need to check LastError too.
|
|
//
|
|
if (ERROR_SUCCESS == GetLastError ())
|
|
{
|
|
//
|
|
// DialogBoxParam executed successfully and a port name was retrieved
|
|
//
|
|
pszPort = Port.pszPortName;
|
|
}
|
|
}
|
|
else if (Result != -1)
|
|
{
|
|
//
|
|
// DialogBoxParam executed successfully, but the user canceled the dialog
|
|
//
|
|
SetLastError(Result);
|
|
}
|
|
|
|
return pszPort;
|
|
}
|