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