portmon.c
来自「虚拟打印端口」· C语言 代码 · 共 2,232 行 · 第 1/4 页
C
2,232 行
/* Say that writing to this port is supported, */
/* but reading is not. */
/* Using fPortType = 3 is wrong. */
/* Options are PORT_TYPE_WRITE=1, PORT_TYPE_READ=2, */
/* PORT_TYPE_REDIRECTED=4, PORT_TYPE_NET_ATTACHED=8 */
pi2[i].fPortType = PORT_TYPE_WRITE;
pi2[i].Reserved = 0;
}
i++;
cbData = sizeof(portname);
rc = RedMonEnumKey(hMonitor, hkey, i, portname, &cbData);
}
*pcReturned = i;
RedMonCloseKey(hMonitor, hkey);
return TRUE;
}
/* 95 / NT40 */
BOOL WINAPI rEnumPorts(LPTSTR pName, DWORD Level, LPBYTE pPorts,
DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
{
return rsEnumPorts(NULL,
pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
}
typedef BOOL (WINAPI *pfnRealEnumPorts)
(LPTSTR pName, DWORD Level, LPBYTE pPorts,
DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned);
BOOL sPortExists(HANDLE hMonitor, LPTSTR pszPortName)
{
BOOL port_exists = FALSE;
HGLOBAL hglobal;
LPBYTE ports;
DWORD cbBuf, needed, returned;
PORT_INFO_2 *pi2;
int j;
pfnRealEnumPorts RealEnumPorts;
#ifdef NT35
HINSTANCE hWinspool;
#endif
#ifdef DEBUG_REDMON
syslog(TEXT("sPortExists "));
syslog(pszPortName);
syslog(TEXT("\r\n"));
{TCHAR buf[MAXSTR];
wsprintf(buf, TEXT(" hMonitor=0x%0x\r\n"), hMonitor);
syslog(buf);
}
#endif
/* Get the list of existing ports. */
/* Ask for all ports, not just ours.
* If we ask for only RedMon ports by calling rsEnumPorts, a user
* can create a second LPT1: This isn't useful because it doesn't
* get serviced before the Local Port, and we can't delete it
* with the Delete Port button. Instead we have to use the
* Registry Editor to clean up the mess.
* To avoid this, stop users from entering any existing port name.
*/
#ifdef NT35
/*
* To enumerate all ports, we need to call EnumPorts in the
* winspool DLL, not our own implementation which has the
* same name in the NT35 version.
*/
hWinspool = LoadLibrary(TEXT("winspool.drv"));
if (hWinspool < (HINSTANCE)HINSTANCE_ERROR)
return FALSE;
RealEnumPorts = (pfnRealEnumPorts)GetProcAddress(hWinspool, "EnumPortsW");
if (RealEnumPorts == (pfnRealEnumPorts)NULL)
return FALSE;
#else
RealEnumPorts = EnumPorts;
#endif
needed = 0;
/* 1998-01-08
* The TELES.FaxMon monitor is buggy - it returns an incorrect
* value for "needed" if we use the following call.
* EnumPorts(NULL, 2, NULL, 0, &needed, &returned);
* To dodge this bug, pass it buffer of non-zero size.
*/
cbBuf = 4096;
hglobal = GlobalAlloc(GPTR, (DWORD)cbBuf);
ports = GlobalLock(hglobal);
if (ports == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
#ifdef NT35
FreeLibrary(hWinspool);
#endif
return FALSE;
}
if (!RealEnumPorts(NULL, 2, ports, cbBuf, &needed, &returned)) {
#ifdef DEBUG_REDMON
DWORD err = GetLastError();
syslog(TEXT("EnumPorts failed\r\n"));
syserror(err);
#endif
GlobalUnlock(hglobal);
GlobalFree(hglobal);
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
#ifdef NT35
FreeLibrary(hWinspool);
#endif
return FALSE; /* give up */
}
else {
/* try again, with requested size */
cbBuf = needed;
/* If there are no ports installed, avoid trying to
* allocate 0 bytes
*/
hglobal = GlobalAlloc(GPTR, (DWORD)cbBuf+4);
ports = GlobalLock(hglobal);
if (ports == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
#ifdef NT35
FreeLibrary(hWinspool);
#endif
return FALSE;
}
if (!RealEnumPorts(NULL, 2, ports, cbBuf, &needed, &returned)) {
#ifdef DEBUG_REDMON
DWORD err = GetLastError();
syslog(TEXT("EnumPorts failed\r\n"));
syserror(err);
#endif
GlobalUnlock(hglobal);
GlobalFree(hglobal);
#ifdef NT35
FreeLibrary(hWinspool);
#endif
return FALSE;
return FALSE;
}
}
}
#ifdef NT35
FreeLibrary(hWinspool);
#endif
#ifdef DEBUG_REDMON
syslog(TEXT("EnumPorts returns "));
sysnum(returned);
syslog(TEXT(" port \r\n"));
#endif
pi2 = (PORT_INFO_2 *)ports;
for (j=0; j<(int)returned; j++) {
#ifdef DEBUG_REDMON
syslog(TEXT(" port "));
sysnum(j);
syslog(TEXT("='"));
syslog(pi2[j].pPortName);
syslog(TEXT("'\r\n"));
#endif
if (lstrcmp(pszPortName, pi2[j].pPortName) == 0)
port_exists = TRUE;
}
GlobalUnlock(hglobal);
GlobalFree(hglobal);
#ifdef DEBUG_REDMON
syslog(TEXT("sPortExists returns "));
syslog(port_exists ? TEXT("true\r\n") : TEXT("false\r\n"));
#endif
return port_exists;
}
TCHAR XcvMonitor[] = TEXT("XcvMonitor");
TCHAR XcvPort[] = TEXT("XcvPort");
/* Copy to pServerName the printer name for accessing
* the port monitor server */
BOOL MakeXcvName(LPTSTR pServerName, LPCTSTR pServer, LPCTSTR pType,
LPCTSTR pName)
{
DWORD len = 2 + lstrlen(pServer) + 2 + lstrlen(pType) + 1 +
lstrlen(pName) + 1;
if (len > MAXSTR)
return FALSE;
*pServerName = 0;
if (pServer) {
lstrcat(pServerName, pServer);
lstrcat(pServerName, TEXT("\\"));
}
lstrcat(pServerName, TEXT(","));
lstrcat(pServerName, pType);
lstrcat(pServerName, TEXT(" "));
if (pName)
lstrcat(pServerName, pName);
return TRUE;
}
/* 95 / NT 40 */
BOOL WINAPI rConfigurePort(LPTSTR pName, HWND hWnd, LPTSTR pPortName)
{
DWORD config_len = redmon_sizeof_config();
HGLOBAL hglobal = GlobalAlloc(GPTR, config_len);
RECONFIG *pconfig = GlobalLock(hglobal);
BOOL flag = TRUE;
/* NT4 spooler does not support remote ConfigurePort calls */
/* pName can be ignored */
if (pName != NULL) {
SetLastError(ERROR_ACCESS_DENIED);
flag = FALSE;
}
if (flag && !redmon_get_config(NULL, pPortName, pconfig))
flag = FALSE;
if (flag && DialogBoxParam(hdll, MAKEINTRESOURCE(IDD_CONFIGPORT),
hWnd, ConfigDlgProc, (LPARAM)pconfig)) {
flag = redmon_set_config(NULL, pconfig);
}
GlobalUnlock(hglobal);
GlobalFree(hglobal);
return flag;
}
#ifdef NT50
DWORD
cConfigurePortUI(HANDLE hXcv, HWND hWnd, PCWSTR pszPortName)
{
DWORD config_len = redmon_sizeof_config();
HGLOBAL hglobal = GlobalAlloc(GPTR, config_len);
RECONFIG *pconfig = GlobalLock(hglobal);
DWORD dwOutput = 0;
DWORD dwNeeded = 0;
DWORD dwError = ERROR_SUCCESS;
#ifdef DEBUG_REDMON
syslog(TEXT("cConfigurePortUI\r\n"));
#endif
/* get current configuration */
if (!XcvData(hXcv, TEXT("GetConfig"), (PBYTE)pszPortName,
sizeof(TCHAR)*(lstrlen(pszPortName)+1),
(PBYTE)pconfig, config_len, &dwNeeded, &dwError))
dwError = GetLastError();
/* update it */
if (dwError == ERROR_SUCCESS) {
if (DialogBoxParam(hdll, MAKEINTRESOURCE(IDD_CONFIGPORT),
hWnd, ConfigDlgProc, (LPARAM)pconfig)) {
if (!XcvData(hXcv, TEXT("SetConfig"),
(PBYTE)pconfig, config_len,
(PBYTE)(&dwOutput), 0, &dwNeeded, &dwError))
dwError = GetLastError();
}
}
GlobalUnlock(hglobal);
GlobalFree(hglobal);
return dwError;
}
BOOL WINAPI rcConfigurePortUI(PCWSTR pszServer, HWND hWnd, PCWSTR pszPortName)
{
TCHAR pszServerName[MAXSTR];
HANDLE hXcv = NULL;
DWORD dwError;
PRINTER_DEFAULTS pd;
if (!MakeXcvName(pszServerName, pszServer, XcvPort, pszPortName))
return FALSE;
pd.pDatatype = NULL;
pd.pDevMode = NULL;
pd.DesiredAccess = SERVER_ACCESS_ADMINISTER;
#ifdef DEBUG_REDMON
syslog(TEXT("OpenPrinter "));
syslog(pszServerName);
syslog(TEXT("\r\n"));
#endif
if (!OpenPrinter(pszServerName, &hXcv, &pd))
return FALSE;
dwError = cConfigurePortUI(hXcv, hWnd, pszPortName);
ClosePrinter(hXcv);
return (dwError == ERROR_SUCCESS);
}
#endif /* NT50 */
BOOL sAddPort(HANDLE hMonitor, LPTSTR pszPortName)
{
LONG rc;
HKEY hkey, hsubkey;
TCHAR szPortDesc[MAXSHORTSTR];
#ifdef DEBUG_REDMON
syslog(TEXT("sAddPort\r\n"));
#endif
if (sPortExists(hMonitor, pszPortName))
return FALSE;
/* store new port name in registry */
LoadString(hdll, IDS_MONITORNAME, szPortDesc,
sizeof(szPortDesc)/sizeof(TCHAR)-1);
rc = RedMonOpenKey(hMonitor, PORTSNAME, KEY_ALL_ACCESS, &hkey);
if (rc != ERROR_SUCCESS) {
/* try to create the Ports key */
rc = RedMonOpenKey(hMonitor, NULL, KEY_ALL_ACCESS, &hkey);
if (rc == ERROR_SUCCESS) {
rc = RedMonCreateKey(hMonitor, hkey, PORTSNAME, 0,
KEY_ALL_ACCESS, NULL, &hsubkey, NULL);
if (rc == ERROR_SUCCESS)
RedMonCloseKey(hMonitor, hsubkey);
RedMonCloseKey(hMonitor, hkey);
}
rc = RedMonOpenKey(hMonitor, PORTSNAME, KEY_ALL_ACCESS, &hkey);
}
if (rc == ERROR_SUCCESS) {
rc = RedMonCreateKey(hMonitor, hkey, pszPortName, 0, KEY_ALL_ACCESS,
NULL, &hsubkey, NULL);
if (rc == ERROR_SUCCESS) {
rc = RedMonSetValue(hMonitor, hsubkey, DESCKEY, REG_SZ,
(CONST BYTE *)szPortDesc, (lstrlen(szPortDesc)+1)*sizeof(TCHAR));
RedMonCloseKey(hMonitor, hsubkey);
}
RedMonCloseKey(hMonitor, hkey);
}
return (rc == ERROR_SUCCESS);
}
/* 95 / NT 40 */
BOOL WINAPI rAddPort(LPTSTR pName, HWND hWnd, LPTSTR pMonitorName)
{
TCHAR portdesc[MAXSHORTSTR];
TCHAR buf[MAXSTR], str[MAXSTR];
BOOL unique;
int i;
DWORD config_len = redmon_sizeof_config();
HGLOBAL hglobal;
RECONFIG *pconfig;
BOOL flag = TRUE;
LPTSTR portname;
/* NT4 spooler does not support remote AddPort calls */
/* pName and pMonitorName can be ignored */
if (pName != NULL) {
SetLastError(ERROR_ACCESS_DENIED);
return FALSE;
}
hglobal = GlobalAlloc(GPTR, config_len);
pconfig = GlobalLock(hglobal);
portname = redmon_init_config(pconfig);
unique = TRUE;
do {
if (!unique) {
LoadString(hdll, IDS_NOTUNIQUE, str, sizeof(str)/sizeof(TCHAR)-1);
wsprintf(buf, str, portname);
LoadString(hdll, IDS_ADDPORT, str, sizeof(str)/sizeof(TCHAR)-1);
if (MessageBox(hWnd, buf, str, MB_OKCANCEL) == IDCANCEL) {
flag = FALSE;
break;
}
}
/* Suggest a unique port name */
for (i=1; i<100; i++) {
if (!redmon_suggest_portname(portname, MAXSHORTSTR, i))
break;
if (!sPortExists(NULL, portname))
break;
}
LoadString(hdll, IDS_MONITORNAME, portdesc,
sizeof(portdesc)/sizeof(TCHAR)-1);
if (!DialogBoxParam(hdll, MAKEINTRESOURCE(IDD_ADDPORT),
hWnd, AddDlgProc, (LPARAM)pconfig)) {
flag = FALSE;
break;
}
if (lstrlen(portname) && portname[lstrlen(portname)-1] != ':')
lstrcat(portname, TEXT(":")); /* append ':' if not present */
if (sPortExists(NULL, portname))
unique = FALSE;
} while (!unique);
if (flag)
flag = sAddPort(NULL, portname);
if (flag)
flag = redmon_set_config(NULL, pconfig);
GlobalUnlock(hglobal);
GlobalFree(hglobal);
return flag;
}
#ifdef NT50
LONG cAddPortUI(HANDLE hXcv, HWND hWnd,
PCWSTR pszPortNameIn, PWSTR pszPortNameOut)
{
DWORD dwStatus;
DWORD dwOutput;
DWORD dwNeeded;
TCHAR str[MAXSTR];
TCHAR buf[MAXSTR];
BOOL unique;
int i;
DWORD config_len = redmon_sizeof_config();
HGLOBAL hglobal;
RECONFIG *pconfig;
LPTSTR portname; /* pointer to port name in RECONFIG */
#ifdef DEBUG_REDMON
syslog(TEXT("cAddPortUI "));
syslog(pszPortNameIn);
syslog(TEXT("\r\n"));
#endif
*pszPortNameOut = '\0';
hglobal = GlobalAlloc(GPTR, config_len);
pconfig = GlobalLock(hglobal);
if (pconfig == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
portname = redmon_init_config(pconfig);
dwStatus = ERROR_SUCCESS;
unique = TRUE;
do {
if (!unique) {
LoadString(hdll, IDS_NOTUNIQUE, str, sizeof(str)/sizeof(TCHAR)-1);
wsprintf(buf, str, portname);
LoadString(hdll, IDS_ADDPORT, str, sizeof(str)/sizeof(TCHAR)-1);
if (MessageBox(hWnd, buf, str, MB_OKCANCEL) == IDCANCEL) {
dwStatus = ERROR_CANCELLED;
break;
}
}
if (dwStatus == ERROR_CANCELLED)
break;
/* Suggest a unique port name */
for (i=1; i<10; i++) {
if (!redmon_suggest_portname(portname, MAXSHORTSTR, i))
break;
dwStatus = ERROR_SUCCESS;
if (!XcvData(hXcv, TEXT("PortExists"), (PBYTE)portname,
sizeof(TCHAR)*(lstrlen(portname)+1),
(PBYTE)(&dwOutput), 0, &dwNeeded, &dwStatus)) {
dwStatus = GetLastError();
}
if (dwStatus == ERROR_SUCCESS)
break; /* unique name */
}
if (!DialogBoxParam(hdll, MAKEINTRESOURCE(IDD_ADDPORT),
hWnd, AddDlgProc, (LPARAM)pconfig)) {
dwStatus = ERROR_CANCELLED;
break;
}
if (lstrlen(portname) && portname[lstrlen(portname)-1] != ':')
lstrcat(portname, TEXT(":")); /* append ':' if not present */
dwStatus = ERROR_SUCCESS;
if (!XcvData(hXcv, TEXT("PortExists"), (PBYTE)portname,
sizeof(TCHAR)*(lstrlen(portname)+1),
(PBYTE)(&dwOutput), 0, &dwNeeded, &dwStatus))
dwStatus = GetLastError();
if (dwStatus != ERROR_SUCCESS)
unique = FALSE;
} while (!unique);
if (dwStatus == ERROR_SUCCESS) {
if (!XcvData(hXcv, TEXT("AddPort"), (PBYTE)portname,
sizeof(TCHAR)*(lstrlen(portname)+1),
(PBYTE)(&dwOutput), 0, &dwNeeded, &dwStatus))
dwStatus = GetLastError();
else
lstrcpyn(pszPortNameOut, portname, MAXSTR-1);
}
if (dwStatus == ERROR_SUCCESS) {
/* Set configuration if supplied */
dwOutput = 0;
dwNeeded = 0;
if (!XcvData(hXcv, TEXT("SetConfig"),
(PBYTE)pconfig, config_len,
(PBYTE)(&dwOutput), 0, &dwNeeded, &dwStatus))
dwStatus = GetLastError();
}
GlobalUnlock(hglobal);
GlobalFree(hglobal);
return dwStatus;
}
BOOL WINAPI rcAddPortUI(PCWSTR pszServer, HWND hWnd,
PCWSTR pszPortNameIn, PWSTR *ppszPortNameOut)
{
TCHAR pszServerName[MAXSTR];
TCHAR portname[MAXSTR];
PRINTER_DEFAULTS pd;
HANDLE hXcv = NULL;
DWORD dwError;
#ifdef DEBUG_REDMON
syslog(TEXT("rcAddPortUI\r\n"));
syslog(TEXT("pszServer=\042"));
syslog(pszServer);
syslog(TEXT("\042\r\n"));
syslog(TEXT("pszPortNameIn=\042"));
syslog(pszPortNameIn);
syslog(TEXT("\042\r\n"));
#endif
if (!MakeXcvName(pszServerName, pszServer, XcvMonitor, pszPortNameIn)) {
#ifdef DEBUG_REDMON
syslog(TEXT("MakeXcvName failed\r\n"));
#endif
return FALSE;
}
pd.pDatatype = NULL;
pd.pDevMode = NULL;
pd.DesiredAccess = SERVER_ACCESS_ADMINISTER;
#ifdef DEBUG_REDMON
syslog(TEXT("OpenPrinter "));
syslog(pszServerName);
syslog(TEXT("\r\n"));
#endif
if (!OpenPrinter(pszServerName, &hXcv, &pd)) {
#ifdef DEBUG_REDMON
TCHAR buf[MAXSTR];
wsprintf(buf, TEXT("OpenPrinter failed error=%d\r\n"),
GetLastError());
syslog(buf);
wsprintf(buf, TEXT(" OpenPrinter handle=0x%x\r\n"), hXcv);
syslog(buf);
#endif
return FALSE;
}
dwError = cAddPortUI(hXcv, hWnd, pszPortNameIn, portname);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?