portmon.c

来自「虚拟打印端口」· C语言 代码 · 共 2,232 行 · 第 1/4 页

C
2,232
字号

    if (dwError == ERROR_SUCCESS) {
#ifdef DEBUG_REDMON
	syslog(TEXT("Added port "));
	syslog(portname);
	syslog(TEXT("\r\n"));
#endif
	if (ppszPortNameOut) {
	    DWORD len = sizeof(TCHAR)*(lstrlen(portname)+1);
	    *ppszPortNameOut = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, len);
	    if (*ppszPortNameOut)
		CopyMemory(*ppszPortNameOut, portname, len);
	}
    }

    ClosePrinter(hXcv);

    return (dwError == ERROR_SUCCESS);
}
#endif /* NT50 */


#if defined(NT35) || defined(NT40)
/* Windows NT only */
/* untested */
BOOL WINAPI rAddPortEx(LPWSTR pName, DWORD Level, LPBYTE lpBuffer, 
     LPWSTR lpMonitorName)
{
    TCHAR *portname;

    if (Level == 1) {
	PORT_INFO_1 *addpi1 = (PORT_INFO_1 *)lpBuffer;
	portname = addpi1->pName;
    }
    if (Level == 2) {
	PORT_INFO_2 *addpi2 = (PORT_INFO_2 *)lpBuffer;
	portname = addpi2->pPortName;
    }

    return sAddPort(NULL, portname);
}
#endif


BOOL sDeletePort(HANDLE hMonitor, LPCTSTR pPortName)
{
    HKEY hkey;
    LONG rc;
#ifdef DEBUG_REDMON
    syslog(TEXT("sDeletePort "));
    syslog(pPortName);
    syslog(TEXT("\r\n"));
#endif
    rc = RedMonOpenKey(hMonitor, PORTSNAME, KEY_ALL_ACCESS, &hkey);
#ifdef DEBUG_REDMON
    syslog(TEXT(" hMonitor="));
    syshex((DWORD)hMonitor);
    syslog(TEXT("\r\n"));
    syslog(TEXT(" hKey="));
    syshex((DWORD)hkey);
    syslog(TEXT("\r\n"));
    syslog(TEXT(" pPortName="));
    syshex((DWORD)pPortName);
    syslog(TEXT(" \042"));
    syslog(pPortName);
    syslog(TEXT("\042\r\n"));
#endif
    if (rc == ERROR_SUCCESS) {
	rc = RedMonDeleteKey(hMonitor, hkey, pPortName);
	RedMonCloseKey(hMonitor, hkey);
    }
    return (rc == ERROR_SUCCESS);
}

BOOL WINAPI rDeletePort(LPTSTR pName, HWND hWnd, LPTSTR pPortName)
{
    if (pName != NULL)
	return FALSE;

    return sDeletePort(NULL, pPortName);
}

#ifdef NT50
BOOL WINAPI rcDeletePortUI(PCWSTR pszServer, HWND hWnd, PCWSTR pszPortName)
{
    TCHAR pszServerName[MAXSTR];
    HANDLE hXcv = NULL;
    DWORD dwStatus = ERROR_SUCCESS;
    DWORD dwError = ERROR_SUCCESS;
    DWORD dwOutput = 0;
    DWORD dwNeeded = 0;
    PRINTER_DEFAULTS pd;

#ifdef DEBUG_REDMON
    syslog(TEXT("rcDeletePortUI "));
    syslog(pszPortName);
    syslog(TEXT("\r\n"));
#endif

    if (!MakeXcvName(pszServerName, pszServer, XcvPort, pszPortName)) {
#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
	dwError = GetLastError();
	syslog(TEXT("OpenPrinter failed\r\n"));
	syserror(dwError);
#endif
	return FALSE;
    }

#ifdef DEBUG_REDMON
    {TCHAR buf[MAXSTR];
    wsprintf(buf, TEXT("rcDeletePortUI hXcv=0x%x\r\n"), hXcv); 
    syslog(buf);
    }
#endif

    /* Delete port */
    if (!XcvData(hXcv, TEXT("DeletePort"), (PBYTE)pszPortName, 
	sizeof(TCHAR)*(lstrlen(pszPortName)+1),
	(PBYTE)(&dwOutput), 0, &dwNeeded, &dwStatus)) {
#ifdef DEBUG_REDMON
	dwError = GetLastError();
	syslog(TEXT("XcvData failed\r\n"));
	syserror(dwError);
#endif
    }

#ifdef DEBUG_REDMON
    syslog(TEXT("XcvData DeletePort returns "));
    sysnum(dwStatus);
    syslog(TEXT("\r\n"));
    if (dwStatus)
        syserror(dwStatus);
#endif

    ClosePrinter(hXcv);

    return (dwStatus == ERROR_SUCCESS);
}
#endif


#ifdef NT50
typedef struct tagREXCVPORT {
    DWORD dwSize;
    HANDLE hMonitor;
    TCHAR szPortName[MAXSTR];
    ACCESS_MASK GrantedAccess;
} REXCVPORT;

BOOL WINAPI rsXcvOpenPort(HANDLE hMonitor, LPCWSTR pszObject, 
	ACCESS_MASK GrantedAccess, PHANDLE phXcv)
{
    REXCVPORT *xcv;
#ifdef DEBUG_REDMON
    syslog(TEXT("rsXcvOpenPort\r\n"));
#endif
    *phXcv = (PHANDLE)NULL;
    xcv = GlobalLock(GlobalAlloc(GPTR, (DWORD)sizeof(REXCVPORT)));
    if (xcv == NULL)
	return FALSE;

    memset(xcv, 0, sizeof(REXCVPORT));
    xcv->dwSize = sizeof(REXCVPORT);
    xcv->hMonitor = hMonitor;
    lstrcpyn(xcv->szPortName, pszObject, 
	sizeof(xcv->szPortName)/sizeof(TCHAR) - 1);
    xcv->GrantedAccess = GrantedAccess;
#ifdef DEBUG_REDMON
    {TCHAR buf[MAXSTR];
    wsprintf(buf, TEXT("rsXcvOpenPort hXcv=0x%x\r\n"), xcv); 
    wsprintf(buf, TEXT(" hMonitor = 0x%x\r\n"), xcv->hMonitor); 
    syslog(buf);
    }
#endif
    *phXcv = (PHANDLE)xcv;
    return TRUE;
}
 

DWORD WINAPI rsXcvDataPort(HANDLE hXcv, LPCWSTR pszDataName, PBYTE pInputData, 
	DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, 
	PDWORD pcbOutputNeeded)
{
    REXCVPORT *xcv = (REXCVPORT *)hXcv;

#ifdef DEBUG_REDMON
    syslog(TEXT("rsXcvDataPort\r\n  "));
    syslog(pszDataName);
    syslog(TEXT("\r\n"));
    syshex((DWORD)hXcv);
    syslog(TEXT("\r\n"));
#endif

    if ((xcv == NULL) || (xcv->dwSize != sizeof(REXCVPORT))) {
#ifdef DEBUG_REDMON
        syslog(TEXT("Invalid parameter\r\n"));
#endif
	return ERROR_INVALID_PARAMETER;
    }

    if (lstrcmp(pszDataName, TEXT("AddPort"))==0) {
	if (!(xcv->GrantedAccess & SERVER_ACCESS_ADMINISTER))
	    return ERROR_ACCESS_DENIED;
	/* pInputData contains the port name */
	if (sAddPort(xcv->hMonitor, (LPTSTR)pInputData))
	    return ERROR_SUCCESS;
    }
    else if (lstrcmp(pszDataName, TEXT("DeletePort"))==0) {
	if (!(xcv->GrantedAccess & SERVER_ACCESS_ADMINISTER))
	    return ERROR_ACCESS_DENIED;
	if (sDeletePort(xcv->hMonitor, (LPTSTR)pInputData))
	    return ERROR_SUCCESS;
    }
    else if (lstrcmp(pszDataName, TEXT("MonitorUI"))==0) {
	/* Our server and UI DLLs are combined */
	TCHAR buf[MAXSTR];
        DWORD len;
	if (pOutputData == NULL)
	    return ERROR_INSUFFICIENT_BUFFER;
	len = GetModuleFileName(hdll, buf, sizeof(buf)/sizeof(TCHAR)-1);
#ifdef DEBUG_REDMON
	{
	TCHAR mess[MAXSTR];
	wsprintf(mess, TEXT("GetModuleFileName=\042%s\042 len=%d\r\n"),
	    buf, len);
	syslog(mess);
	}
#endif
	*pcbOutputNeeded = (len + 1) * sizeof(TCHAR);
	if (*pcbOutputNeeded > cbOutputData)
	   return ERROR_INSUFFICIENT_BUFFER;
	memcpy(pOutputData, buf, *pcbOutputNeeded);
#ifdef DEBUG_REDMON
        syslog(TEXT(" returned UI name="));
        syslog((LPTSTR)pOutputData);
        syslog(TEXT("\r\n"));
#endif
	return ERROR_SUCCESS;
    }
    else if (lstrcmp(pszDataName, TEXT("PortExists"))==0) {
	/* pInputData contains the port name */
	if (sPortExists(xcv->hMonitor, (LPTSTR)pInputData))
	    return ERROR_PRINTER_ALREADY_EXISTS;	/* TRUE */
	else
	    return ERROR_SUCCESS;			/* FALSE */
    }
    else if (lstrcmp(pszDataName, TEXT("GetConfig"))==0) {
	*pcbOutputNeeded = redmon_sizeof_config();
	if (*pcbOutputNeeded > cbOutputData)
	   return ERROR_INSUFFICIENT_BUFFER;
	if (redmon_get_config(xcv->hMonitor, (LPCTSTR)pInputData,
	    (RECONFIG *)pOutputData))
	    return ERROR_SUCCESS;
    }
    else if (lstrcmp(pszDataName, TEXT("SetConfig"))==0) {
	if (!(xcv->GrantedAccess & SERVER_ACCESS_ADMINISTER))
	    return ERROR_ACCESS_DENIED;
	if (!redmon_validate_config((RECONFIG *)pInputData))
	    return ERROR_INVALID_PARAMETER;
	if (redmon_set_config(xcv->hMonitor, (RECONFIG *)pInputData))
	    return ERROR_SUCCESS;
    }

    return ERROR_INVALID_PARAMETER;
}

BOOL WINAPI rsXcvClosePort(HANDLE hXcv)
{
    REXCVPORT *xcv = (REXCVPORT *)hXcv;
#ifdef DEBUG_REDMON
    syslog(TEXT("rsXcvClosePort\r\n"));
#endif
    if ((xcv == NULL) || (xcv->dwSize != sizeof(REXCVPORT)))
	return FALSE;
    GlobalUnlock(GlobalHandle(hXcv));
    GlobalFree(GlobalHandle(hXcv));
    return TRUE;
}

VOID WINAPI rsShutdown(HANDLE hMonitor) 
{
    /* undo InitializePrintMonitor2 */
    /* nothing to do */
#ifdef DEBUG_REDMON
    syslog(TEXT("rsShutDown\r\n"));
#endif
}


#ifdef MAKEEXE
/* test routine which calls local function */
BOOL WINAPI XcvData(HANDLE hXcv, LPCWSTR pszDataName, 
    PBYTE pInputData, DWORD cbInputData, 
    PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded,
    PDWORD pdwStatus) 
{
    *pdwStatus = rsXcvDataPort(hXcv, pszDataName, pInputData, cbInputData,
	pOutputData, cbOutputData, pcbOutputNeeded);
    return TRUE;
}
#else	/* !MAKEEXE */
/* #if _MSC_VER <= 1100   /* MSVC++ 5.0 or earlier */
#if _MSC_VER <= 1200   /* MSVC++ 6.0 or earlier */
/* We don't have XcvData in the import library, so we must use
 * run time linking.  This is inefficient, but fortunately we 
 * only need this for port configuration, not for normal use.
 * Using run time linking also allows to have one DLL which 
 * works for both Windows NT4 and 2000. */
typedef BOOL (WINAPI *pfnXcvData)(HANDLE hXcv, LPCWSTR pszDataName, 
    PBYTE pInputData, DWORD cbInputData, 
    PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded,
    PDWORD pdwStatus);

BOOL WINAPI XcvData(HANDLE hXcv, LPCWSTR pszDataName, 
    PBYTE pInputData, DWORD cbInputData, 
    PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded,
    PDWORD pdwStatus) 
{
    pfnXcvData fpXcvData = NULL;
    BOOL flag = FALSE;
    /* Load the spooler DLL.  This shouldn't be too slow, since
     * the DLL should already be loaded */
    HINSTANCE hInstance = LoadLibrary(TEXT("winspool.drv"));
#ifdef DEBUG_REDMON
    syslog(TEXT("loader for XcvData "));
    syslog(pszDataName);
    syslog(TEXT("\r\n"));
#endif
    if (hInstance != NULL) {
	fpXcvData = (pfnXcvData)GetProcAddress(hInstance, "XcvDataW"); 
	if (fpXcvData != NULL) {
	    flag = fpXcvData(hXcv, pszDataName, pInputData, cbInputData,
		pOutputData, cbOutputData, pcbOutputNeeded, pdwStatus);
#ifdef DEBUG_REDMON
	    {TCHAR buf[MAXSTR];
	    DWORD dwError = GetLastError();
	    wsprintf(buf, 
		TEXT("XcvData returns %d, dwStatus=%d, GetLastError=%d\r\n"),
		flag, *pdwStatus, dwError);
	    syslog(buf);
	    if (flag == 0)
		syserror(dwError);
	    wsprintf(buf, TEXT("hXcv=0x%x\r\n"), hXcv);
	    syslog(buf);
	    }
#endif
	}
#ifdef DEBUG_REDMON
	else {
	    syslog(TEXT("failed to load XcvData\r\n"));
	}
#endif
	FreeLibrary(hInstance);
    }
    return flag;
} 
#endif	/* MSVC++ 5.0 or earlier */
#endif	/* !MAKEEXE */

#endif /* NT50 */


BOOL WINAPI rsOpenPort(HANDLE hMonitor, LPTSTR pName, PHANDLE pHandle)
{
    BOOL flag;
#ifdef BETA
    if (beta())
	return FALSE;
#endif

#ifdef DEBUG_REDMON
    syslog(TEXT("rsOpenPort"));
    syslog(TEXT("  hMonitor="));
    syshex((DWORD)hMonitor);
    syslog(TEXT("\r\n"));
    syslog(TEXT("  pName="));
    syslog(pName);
    syslog(TEXT("\r\n"));
    syslog(TEXT("\r\n"));
#endif

    flag = redmon_open_port(hMonitor, pName, pHandle); 

#ifdef DEBUG_REDMON
    syslog(TEXT("rsOpenPort returns "));
    sysnum(flag);
    syslog(TEXT("\r\n"));
#endif
    return flag;
} 


/* 95 / NT4 */
BOOL WINAPI rOpenPort(LPTSTR pName, PHANDLE pHandle)
{
    return rsOpenPort(NULL, pName, pHandle);
}

#ifdef UNUSED
/* Don't use OpenPortEx in a Port Monitor */
BOOL WINAPI rOpenPortEx(LPTSTR  pPortName, 
        LPTSTR  pPrinterName, PHANDLE pHandle, struct _MONITOR 
        FAR *pMonitor);
#endif



/* 95 / NT 40 / NT 50 */
BOOL WINAPI rStartDocPort(HANDLE hPort, LPTSTR pPrinterName, 
        DWORD JobId, DWORD Level, LPBYTE pDocInfo)
{
    REDATA *prd = GlobalLock((HGLOBAL)hPort);
    BOOL flag;

#ifdef DEBUG_REDMON
    syslog(TEXT("rStartDocPort\r\n"));
    syslog(TEXT("  hPort="));
    syshex((DWORD)hPort);
    syslog(TEXT("\r\n"));
#endif

    if (prd == (REDATA *)NULL) {
	SetLastError(ERROR_INVALID_HANDLE);
	return FALSE;
    }

    reset_redata(prd);

    flag = redmon_start_doc_port(prd, pPrinterName, JobId, Level, pDocInfo);

    GlobalUnlock((HGLOBAL)hPort);

#ifdef DEBUG_REDMON
    syslog(TEXT("rStartDocPort returns "));
    sysnum(flag);
    syslog(TEXT("\r\n"));
#endif
    return flag;
}


/* WritePort is normally called between StartDocPort and EndDocPort,
 * but can be called outside this pair for bidirectional printers.
 */
BOOL WINAPI rWritePort(HANDLE  hPort, LPBYTE  pBuffer, 
        DWORD   cbBuf, LPDWORD pcbWritten)
{
    REDATA *prd = GlobalLock((HGLOBAL)hPort);
    BOOL flag;
#ifdef DEBUG_REDMON
    syslog(TEXT("rWritePort "));
    sysnum(cbBuf);
    syslog(TEXT("\r\n"));
#endif

    if (prd == (REDATA *)NULL) {
	SetLastError(ERROR_INVALID_HANDLE);
	return FALSE;
    }

    *pcbWritten = 0;
    flag = redmon_write_port(prd, pBuffer, cbBuf, pcbWritten);

    GlobalUnlock((HGLOBAL)hPort);

#ifdef DEBUG_REDMON
    syslog(TEXT("rWritePort returns TRUE\r\n"));
#endif
    return TRUE;	/* returning FALSE crashes Win95 spooler */
}

/* ReadPort can be called within a Start/EndDocPort pair,
 * and also outside this pair.
 */
BOOL WINAPI rReadPort(HANDLE hPort, LPBYTE pBuffer, 
        DWORD  cbBuffer, LPDWORD pcbRead)
{
    BOOL flag;
    REDATA *prd = GlobalLock((HGLOBAL)hPort);
#ifdef DEBUG_REDMON
    syslog(TEXT("rReadPort\r\n"));
#endif

    /* we don't support reading */
    *pcbRead = 0;

    if (prd == (REDATA *)NULL) {
	SetLastError(ERROR_INVALID_HANDLE);
#ifdef DEBUG_REDMON
        syslog(TEXT("rReadPort returns FALSE.  Not our port handle.\r\n"));
#endif
	return FALSE;
    }

    flag = redmon_read_port(prd, pBuffer, cbBuffer, pcbRead);

    GlobalUnlock((HGLOBAL)hPort);

#ifdef DEBUG_REDMON
    syslog(TEXT("rReadPort returns "));
    sysnum(flag);
    syslog(TEXT("\r\n"));
#endif
    return flag;
}

BOOL WINAPI rEndDocPort(HANDLE hPort)
{
    REDATA *prd = GlobalLock((HGLOBAL)hPort);
    BOOL flag;
#ifdef DEBUG_REDMON
    syslog(TEXT("rEndDocPort\r\n"));
#endif

    if (prd == (REDATA *)NULL) {
	SetLastError(ERROR_INVALID_HANDLE);
	return FALSE;
    }

    flag = redmon_end_doc_port(prd);

    reset_redata(prd);

    GlobalUnlock((HGLOBAL)hPort);

#ifdef DEBUG_REDMON
    syslog(TEXT("rEndDocPort returns TRUE\r\n"));
#endif
    return TRUE;
}


BOOL WINAPI 
rClosePort(HANDLE hPort)
{
    BOOL flag;
#ifdef DEBUG_REDMON
    syslog(TEXT("rClosePort\r\n"));
#endif
    flag = redmon_close_port(hPort);
#ifdef DEBUG_REDMON

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?