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 + -
显示快捷键?