diff options
Diffstat (limited to 'private/net/dosprint')
-rw-r--r-- | private/net/dosprint/dosprint.c | 1363 | ||||
-rw-r--r-- | private/net/dosprint/dosprtp.c | 440 | ||||
-rw-r--r-- | private/net/dosprint/dosprtw.c | 2284 | ||||
-rw-r--r-- | private/net/dosprint/dosspool.c | 614 | ||||
-rw-r--r-- | private/net/dosprint/dosspool.h | 125 | ||||
-rw-r--r-- | private/net/dosprint/makefile | 6 | ||||
-rw-r--r-- | private/net/dosprint/myspool.h | 125 | ||||
-rw-r--r-- | private/net/dosprint/sources | 47 |
8 files changed, 5004 insertions, 0 deletions
diff --git a/private/net/dosprint/dosprint.c b/private/net/dosprint/dosprint.c new file mode 100644 index 000000000..0a9eb2ca1 --- /dev/null +++ b/private/net/dosprint/dosprint.c @@ -0,0 +1,1363 @@ +/*++ + +Copyright (c) 1991-1993 Microsoft Corporation + +Module Name: + + dosprint.c + +Abstract: + + This module provides the ANSI mapping layer from the old DosPrint APIs to + the new all singing all dancing beautiful Print APIs. (The UNICODE mapping + layer is in DosPrtW.c in this directory.) + +Author: + + Dave Snipp (DaveSn) 26-Apr-1991 + +Revision History: + + 09-Jul-1992 JohnRo + RAID 10324: net print vs. UNICODE. + Fixed many wrong error codes. + Use PREFIX_ equates. + Use offsetof() as provided by implmentation, not our own (nonportable). + Made changes suggested by PC-LINT, including one bug fix. + 03-Oct-1992 JohnRo + RAID 3556: DosPrintQGetInfo(from downlevel) level 3, rc=124. (4&5 too.) + RAID 8333: view printer queues hangs DOS LM enh client. + Make sure data type in job level 1 is null terminated. + Fixed job submitted times. + Fixed DosPrintQEnumA level 5 array bug. + Fixed DosPrintJobEnumA levels 2 and 3. + Also implemented DosPrintJobGetInfo levels 0, 1, and 3. + Fixed bug calling OpenPrinter with wrong char set here and there. + Fixed job comment field (was set to document by mistake). + Fixed error code if GlobalAlloc fails. + Avoid compiler warnings due to new winspool.h. + 04-Dec-1992 JohnRo + RAID 1661: downlevel to NT DosPrintDestEnum not supported. + Added code to track down empty queue name. + Quiet normal debug output. + Avoid const vs. volatile compiler warnings. + Avoid new compiler warnings. + Made changes suggested by PC-LINT 5.0 + 08-Feb-1993 JohnRo + RAID 10164: Data misalignment error during XsDosPrintQGetInfo(). + 22-Mar-1993 JohnRo + RAID 2974: NET PRINT says NT printer is held when it isn't. + DosPrint API cleanup: reduced this file to just ANSI wrappers. + Made more changes suggested by PC-LINT 5.0 + Added some IN and OUT keywords. + Clarified many debug messages. + 07-Apr-1993 JohnRo + RAID 5670: "NET PRINT \\server\share" gives err 124 (bad level) on NT. + 11-May-1993 JohnRo + RAID 9942: workaround Windows For Workgroups (WFW) bug in DosPrintQEnum. + Also fixed "NET PRINT \\server\share" and "NET SHARE printshare /DEL" + GP faults. + +--*/ + + +#define NOMINMAX +#define NOSERVICE // Avoid <winsvc.h> vs. <lmsvc.h> conflicts. +#include <windows.h> + +#include <lmcons.h> + +#include <dosprint.h> // My prototypes. +#include <dosprtp.h> // IF_DEBUG(), some of my prototypes. +#include <lmapibuf.h> // NetApiBufferFree(), etc. +#include <netdebug.h> // DBGSTATIC, NetpKdPrint(()), etc. +#include <prefix.h> // PREFIX_ equates. +#include <stddef.h> // offsetof(). +#include <string.h> // memcpy(), strncpy(). +#include <tstring.h> // NetpAlloc{type}From{type}. +#include <winerror.h> // NO_ERROR, ERROR_ equates. + + +#define MAX_WORD ( (WORD) (~0) ) + + +SPLERR SPLENTRY DosPrintQGetInfoA( + IN LPSTR pszServer OPTIONAL, + IN LPSTR pszQueueName, + IN WORD uLevel, + OUT PBYTE pbBuf, + IN WORD cbBuf, + OUT PUSHORT pcbNeeded + ) +{ + DWORD cbBufW; + DWORD rc; + USHORT cbNeeded; + LPWSTR QueueNameW = NULL; + LPWSTR ServerNameW = NULL; + LPVOID TempBufferW = NULL; + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint((PREFIX_DOSPRINT + "DosPrintQGetInfoA(%s, %s, %d, %x, %d, %x)\n", + (pszServer!=NULL) ? pszServer : "(local)", + (pszQueueName!=NULL) ? pszQueueName : "(missing)", + uLevel, + pbBuf, + cbBuf, + pcbNeeded)); + } + + QueueNameW = NetpAllocWStrFromStr( pszQueueName ); + if (QueueNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + // Compute wide buff size. + cbBufW = cbBuf * sizeof(WCHAR); + if ( cbBufW > (DWORD) MAX_WORD ) { + cbBufW = (DWORD) MAX_WORD; + } + + rc = NetApiBufferAllocate( + cbBuf * sizeof(WCHAR), + (LPVOID *) (LPVOID) &TempBufferW ); + if (rc != NO_ERROR) { + goto Cleanup; + } + + // + // Process the API (locally or remotely) and get results (with + // UNICODE strings). + // + rc = DosPrintQGetInfoW( + ServerNameW, + QueueNameW, + uLevel, + TempBufferW, + (WORD) cbBufW, + (PUSHORT) &cbNeeded); + *pcbNeeded = cbNeeded; // BUGBUG: really? + + // + // Convert results back from UNICODE. + // + if (rc == NO_ERROR) { + LPBYTE StringAreaA = (LPBYTE)pbBuf + cbBuf; + + // Translate UNICODE strings back to ANSI. + rc = NetpConvertPrintQCharSet( + uLevel, + FALSE, // not add or setinfo API + TempBufferW, // from info + pbBuf, // to info + FALSE, // no, don't convert to UNICODE. + & StringAreaA ); // conv strings and update ptr + + if (rc == ERROR_MORE_DATA) + { + *pcbNeeded = (USHORT)cbBufW ; // Unicode call succeeded but no room to go + // Ansi. we know the Unicode buffer size is + // definitely good enough. This is temporary + // fix. + } + } + +Cleanup: + if (QueueNameW != NULL) { + (VOID) NetApiBufferFree( QueueNameW ); + } + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + if (TempBufferW != NULL) { + (VOID) NetApiBufferFree( TempBufferW ); + } + return rc; +} + + +SPLERR SPLENTRY DosPrintJobGetInfoA( + IN LPSTR pszServer OPTIONAL, + IN WORD uJobId, + IN WORD uLevel, + OUT PBYTE pbBuf, + IN WORD cbBuf, + OUT PUSHORT pcbNeeded + ) +{ + DWORD cbBufW; + DWORD rc; + USHORT cbNeeded; + LPWSTR ServerNameW = NULL; + LPVOID TempBufferW = NULL; + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint((PREFIX_DOSPRINT + "DosPrintJobGetInfoA(" FORMAT_LPSTR ", %d, %d, %x, %d, %x)\n", + pszServer ? pszServer : "(local)", + uJobId, + uLevel, + pbBuf, + cbBuf, + pcbNeeded)); + } + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + // Compute wide buff size. + cbBufW = cbBuf * sizeof(WCHAR); + if ( cbBufW > (DWORD) MAX_WORD ) { + cbBufW = (DWORD) MAX_WORD; + } + + rc = NetApiBufferAllocate( + cbBufW, + (LPVOID *) (LPVOID) &TempBufferW ); + if (rc != NO_ERROR) { + goto Cleanup; + } + + // Process the API (local or remote) and get results (with UNICODE strings). + rc = DosPrintJobGetInfoW( + ServerNameW, + uJobId, + uLevel, + TempBufferW, + (WORD) cbBufW, + &cbNeeded); + *pcbNeeded = cbNeeded; // BUGBUG: is this right? + + if (rc == NO_ERROR) { + LPBYTE StringAreaA = (LPBYTE)pbBuf + cbBuf; + + // Translate UNICODE strings back to ANSI. + rc = NetpConvertPrintJobCharSet( + uLevel, + FALSE, // not add or setinfo API + TempBufferW, // from info + pbBuf, // to info + FALSE, // no, don't convert to UNICODE. + & StringAreaA ); // conv strings and update ptr + } + +Cleanup: + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + if (TempBufferW != NULL) { + (VOID) NetApiBufferFree( TempBufferW ); + } + return (rc); +} + +SPLERR SPLENTRY DosPrintJobDelA( + LPSTR pszServer, + WORD uJobId +) +{ + DWORD rc; + LPWSTR ServerNameW = NULL; + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintJobDelA...\n" )); + } + + rc = DosPrintJobDelW( ServerNameW, uJobId ); + +Cleanup: + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + + return (rc); +} + +SPLERR SPLENTRY DosPrintJobContinueA( + LPSTR pszServer, + WORD uJobId +) +{ + DWORD rc; + LPWSTR ServerNameW = NULL; + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + } + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintJobContinueA(%d)\n", uJobId)); + } + + rc = DosPrintJobContinueW( ServerNameW, uJobId ); + +Cleanup: + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + + return (rc); +} + +SPLERR SPLENTRY DosPrintJobPauseA( + IN LPSTR pszServer, + IN WORD uJobId + ) +{ + DWORD rc; + LPWSTR ServerNameW = NULL; + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + } + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint(( PREFIX_DOSPRINT + "DosPrintJobPauseA(" FORMAT_LPSTR ", %d)\n", + pszServer ? pszServer : "(local)", + uJobId)); + } + + rc = DosPrintJobPauseW( ServerNameW, uJobId ); + +Cleanup: + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + + return rc; +} + +SPLERR SPLENTRY DosPrintJobEnumA( + IN LPSTR pszServer OPTIONAL, + IN LPSTR pszQueueName, + IN WORD uLevel, + OUT PBYTE pbBuf, + IN WORD cbBuf, + OUT PWORD pcReturned, + OUT PWORD pcTotal + ) +{ + DWORD cbBufW; + DWORD rc; + LPWSTR QueueNameW = NULL; + LPWSTR ServerNameW = NULL; + LPVOID TempBufferW = NULL; + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint((PREFIX_DOSPRINT + "DosPrintJobEnumA(" FORMAT_LPSTR ", %s, %d, %x, %d, %x, %x)\n", + pszServer ? pszServer : "(local)", + pszQueueName, uLevel, pbBuf, cbBuf, pcReturned, pcTotal)); + } + + QueueNameW = NetpAllocWStrFromStr( pszQueueName ); + if (QueueNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + // Compute wide buff size. + cbBufW = cbBuf * sizeof(WCHAR); + if ( cbBufW > (DWORD) MAX_WORD ) { + cbBufW = (DWORD) MAX_WORD; + } + + rc = NetApiBufferAllocate( + cbBufW, + (LPVOID *) (LPVOID) &TempBufferW ); + if (rc != NO_ERROR) { + goto Cleanup; + } + + // Process API (local/remote), get UNICODE results. + rc = DosPrintJobEnumW( + ServerNameW, + QueueNameW, + uLevel, + TempBufferW, + (WORD) cbBufW, + pcReturned, + pcTotal); + + if (rc == NO_ERROR) { + LPBYTE StringAreaA = (LPBYTE)pbBuf + cbBuf; + + // Translate UNICODE strings back to ANSI. + rc = NetpConvertPrintJobArrayCharSet( + uLevel, + FALSE, // not add or setinfo API + TempBufferW, // from info + pbBuf, // to info + FALSE, // no, don't convert to UNICODE. + & StringAreaA, // conv strings and update ptr + (DWORD) (*pcTotal) ); + } + +Cleanup: + if (QueueNameW != NULL) { + (VOID) NetApiBufferFree( QueueNameW ); + } + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + if (TempBufferW != NULL) { + (VOID) NetApiBufferFree( TempBufferW ); + } + + return (rc); +} + + +SPLERR SPLENTRY +DosPrintDestEnumA( + IN LPSTR pszServer OPTIONAL, + IN WORD uLevel, + OUT PBYTE pbBuf, + IN WORD cbBuf, + OUT PUSHORT pcReturned, + OUT PUSHORT pcTotal + ) +{ + DWORD cbBufW; + WORD cReturned, cTotal; + DWORD rc; + LPWSTR ServerNameW = NULL; + LPVOID TempBufferW = NULL; + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint(( PREFIX_DOSPRINT + "DosPrintDestEnumA(" FORMAT_LPSTR ", %d, %x, %d, %x, %x)\n", + (pszServer!=NULL) ? pszServer : "(local)", + uLevel, pbBuf, cbBuf, pcReturned, pcTotal)); + } + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + // Compute wide buff size. + cbBufW = cbBuf * sizeof(WCHAR); + if ( cbBufW > (DWORD) MAX_WORD ) { + cbBufW = (DWORD) MAX_WORD; + } + + rc = NetApiBufferAllocate( + cbBufW, + (LPVOID *) (LPVOID) &TempBufferW ); + if (rc != NO_ERROR) { + goto Cleanup; + } + + // Invoke wide-char version of API, which will do local or downlevel for us. + rc = DosPrintDestEnumW( + ServerNameW, + uLevel, + TempBufferW, + (WORD) cbBufW, + &cReturned, + &cTotal); + *pcReturned = (USHORT)cReturned; + *pcTotal = (USHORT)cTotal; + + // Convert from wide chars for caller. + if (rc == NO_ERROR) { + LPBYTE StringAreaA = (LPBYTE)pbBuf + cbBuf; + + // Translate UNICODE strings back to ANSI. + rc = NetpConvertPrintDestArrayCharSet( + uLevel, + FALSE, // not add or setinfo API + TempBufferW, // from info + pbBuf, // to info + FALSE, // no, don't convert to UNICODE. + & StringAreaA, // conv strings and update ptr + cTotal ); + } + +Cleanup: + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + if (TempBufferW != NULL) { + (VOID) NetApiBufferFree( TempBufferW ); + } + return (rc); +} + +SPLERR SPLENTRY DosPrintDestControlA( + IN LPSTR pszServer OPTIONAL, + IN LPSTR pszDevName, + IN WORD uControl + ) +{ + LPWSTR DestNameW = NULL; + DWORD rc; + LPWSTR ServerNameW = NULL; + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint((PREFIX_DOSPRINT + "DosPrintDestEnumA(" FORMAT_LPSTR ", %s, %d)\n", + pszServer ? pszServer : "(local)", + pszDevName, uControl)); + } + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + DestNameW = NetpAllocWStrFromStr( pszDevName ); + if (DestNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + rc = DosPrintDestControlW(ServerNameW, DestNameW, uControl); + +Cleanup: + if (DestNameW != NULL) { + (VOID) NetApiBufferFree( DestNameW ); + } + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + return (rc); + +} // DosPrintDestControlA + + +SPLERR SPLENTRY DosPrintDestGetInfoA( + IN LPSTR pszServer OPTIONAL, + IN LPSTR pszName, + IN WORD uLevel, + OUT PBYTE pbBuf, + IN WORD cbBuf, + OUT PUSHORT pcbNeeded + ) +{ + DWORD cbBufW; + DWORD rc; + LPWSTR DestNameW = NULL; + LPWSTR ServerNameW = NULL; + LPVOID TempBufferW = NULL; + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint((PREFIX_DOSPRINT + "DosPrintDestGetInfoA(" FORMAT_LPSTR ", %s, %d, %x, %d, %x)\n", + pszServer ? pszServer : "(local)", + pszName, + uLevel, + pbBuf, + cbBuf, + pcbNeeded)); + } + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + DestNameW = NetpAllocWStrFromStr( pszName ); + if (DestNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + // Compute wide buff size. + cbBufW = cbBuf * sizeof(WCHAR); + if ( cbBufW > (DWORD) MAX_WORD ) { + cbBufW = (DWORD) MAX_WORD; + } + + rc = NetApiBufferAllocate( + cbBufW, + (LPVOID *) (LPVOID) &TempBufferW ); + if (rc != NO_ERROR) { + goto Cleanup; + } + + // Process the API (local or remote) and get results (with UNICODE strings). + rc = DosPrintDestGetInfoW( + ServerNameW, + DestNameW, + uLevel, + TempBufferW, + (WORD) cbBufW, + pcbNeeded); // BUGBUG:wrong value returned here? + + if (rc == NO_ERROR) { // BUGBUG: ERROR_MORE_DATA? + LPBYTE StringAreaA = (LPBYTE)pbBuf + cbBuf; + + // Translate UNICODE strings back to ANSI. + rc = NetpConvertPrintDestCharSet( + uLevel, + FALSE, // not add or setinfo API + TempBufferW, // from info + pbBuf, // to info + FALSE, // no, don't convert to UNICODE. + & StringAreaA ); // conv strings and update ptr + } + +Cleanup: + if (DestNameW != NULL) { + (VOID) NetApiBufferFree( DestNameW ); + } + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + if (TempBufferW != NULL) { + (VOID) NetApiBufferFree( TempBufferW ); + } + return (rc); +} + +SPLERR SPLENTRY DosPrintDestAddA( + IN LPSTR pszServer OPTIONAL, + IN WORD uLevel, + IN PBYTE pbBuf, + IN WORD cbBuf + ) +{ + DWORD cbBufW; + DWORD rc; + LPWSTR ServerNameW = NULL; + LPBYTE StringAreaW; + LPVOID TempBufferW = NULL; + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint(( PREFIX_DOSPRINT + "DosPrintDestAddA(" FORMAT_LPSTR ", %d, %x, %d)\n", + pszServer ? pszServer : "(local)", + uLevel, pbBuf, cbBuf)); + } + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + // Compute wide buff size. + cbBufW = cbBuf * sizeof(WCHAR); + if ( cbBufW > (DWORD) MAX_WORD ) { + cbBufW = (DWORD) MAX_WORD; + } + + rc = NetApiBufferAllocate( + cbBufW, + (LPVOID *) (LPVOID) &TempBufferW ); + if (rc != NO_ERROR) { + goto Cleanup; + } + + StringAreaW = (LPBYTE)TempBufferW + cbBufW; + + rc = NetpConvertPrintDestCharSet( + uLevel, + TRUE, // yes, is add or setinfo API + pbBuf, // from info + TempBufferW, // to info + TRUE, // yes, convert to UNICODE. + & StringAreaW ); // conv strings and update ptr + if (rc != NO_ERROR) { + goto Cleanup; + } + + rc = DosPrintDestAddW( + ServerNameW, + uLevel, + TempBufferW, + (WORD) cbBufW); + + +Cleanup: + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + if (TempBufferW != NULL) { + (VOID) NetApiBufferFree( TempBufferW ); + } + return (rc); +} + + +SPLERR SPLENTRY DosPrintDestSetInfoA( + IN LPSTR pszServer OPTIONAL, + IN LPSTR pszName, + IN WORD uLevel, + IN PBYTE pbBuf, + IN WORD cbBuf, + IN WORD uParmNum + ) +{ + DWORD cbBufW; + LPWSTR DestNameW = NULL; + DWORD rc; + LPWSTR ServerNameW = NULL; + LPBYTE StringAreaW; + LPVOID TempBufferW = NULL; + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint(( PREFIX_DOSPRINT + "DosPrintDestSetInfoA(" FORMAT_LPSTR ", %s, %d, %x, %d, %d)\n", + pszServer ? pszServer : "(local)", + pszName, + uLevel, + pbBuf, + cbBuf, + uParmNum)); + } + + if (pszServer && *pszServer) { + + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + DestNameW = NetpAllocWStrFromStr( pszName ); + if (DestNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + // Compute wide buff size. + cbBufW = cbBuf * sizeof(WCHAR); + if ( cbBufW > (DWORD) MAX_WORD ) { + cbBufW = (DWORD) MAX_WORD; + } + + rc = NetApiBufferAllocate( + cbBufW, + (LPVOID *) (LPVOID) &TempBufferW ); + if (rc != NO_ERROR) { + goto Cleanup; + } + + StringAreaW = (LPBYTE)TempBufferW + cbBufW; + + rc = NetpConvertPrintDestCharSet( + uLevel, + TRUE, // yes, is add or setinfo API + pbBuf, // from info + TempBufferW, // to info + TRUE, // yes, convert to UNICODE. + & StringAreaW ); // conv strings and update ptr + if (rc != NO_ERROR) { + goto Cleanup; + } + + rc = DosPrintDestSetInfoW( + ServerNameW, + DestNameW, + uLevel, + TempBufferW, + (WORD) cbBufW, + uParmNum); + +Cleanup: + if (DestNameW != NULL) { + (VOID) NetApiBufferFree( DestNameW ); + } + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + if (TempBufferW != NULL) { + (VOID) NetApiBufferFree( TempBufferW ); + } + return (rc); +} + +SPLERR SPLENTRY DosPrintDestDelA( + IN LPSTR pszServer OPTIONAL, + IN LPSTR pszPrinterName + ) +{ + LPWSTR PrinterNameW = NULL; + DWORD rc; + LPWSTR ServerNameW = NULL; + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint((PREFIX_DOSPRINT + "DosPrintDestDelA(" FORMAT_LPSTR ", %s)\n", + pszServer ? pszServer : "(local)", + pszPrinterName)); + } + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + PrinterNameW = NetpAllocWStrFromStr( pszPrinterName ); + if (PrinterNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + rc = DosPrintDestDelW( + ServerNameW, + PrinterNameW); + +Cleanup: + if (PrinterNameW != NULL) { + (VOID) NetApiBufferFree( PrinterNameW ); + } + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + return (rc); +} + +SPLERR SPLENTRY DosPrintQEnumA( + IN LPSTR pszServer OPTIONAL, + IN WORD uLevel, + OUT PBYTE pbBuf, + IN WORD cbBuf, + OUT PUSHORT pcReturned, + OUT PUSHORT pcTotal + ) +{ + DWORD cbBufW; + DWORD rc; + LPWSTR ServerNameW = NULL; + LPVOID TempBufferW = NULL; // queue structure with UNICODE strings. + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint((PREFIX_DOSPRINT + "DosPrintQEnumA(" FORMAT_LPSTR ", %d, %x, %d, %x, %x)\n", + pszServer ? pszServer : "(local)", + uLevel, pbBuf, cbBuf, pcReturned, pcTotal)); + } + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + // Compute wide buff size. + cbBufW = cbBuf * sizeof(WCHAR); + if ( cbBufW > (DWORD) MAX_WORD ) { + cbBufW = (DWORD) MAX_WORD; + } + + rc = NetApiBufferAllocate( + cbBufW, + (LPVOID *) (LPVOID) &TempBufferW ); + if (rc != NO_ERROR) { + goto Cleanup; + } + + // Process local/remote, get UNICODE results. + rc = DosPrintQEnumW( + ServerNameW, + uLevel, + TempBufferW, + (WORD) cbBufW, + pcReturned, + pcTotal); + + // Convert back to UNICODE. + if (rc == NO_ERROR) { + LPBYTE StringAreaA = (LPBYTE)pbBuf + cbBuf; + rc = (DWORD) NetpConvertPrintQArrayCharSet( + uLevel, + FALSE, // not add or setinfo API + TempBufferW, // from info + pbBuf, // to info + FALSE, // no, not converting to UNICODE + &StringAreaA, // string area; update ptr + *pcReturned ); // Q count + + } + + +Cleanup: + +#if DBG + IF_DEBUG( DOSPRINT ) { + if (rc == NO_ERROR) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintQEnumA: returning array:\n" )); + NetpDbgDisplayPrintQArray( + uLevel, + pbBuf, + *pcReturned, + FALSE ); + } + } +#endif + + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + if (TempBufferW != NULL) { + (VOID) NetApiBufferFree( TempBufferW ); + } + + + return (rc); +} + +SPLERR SPLENTRY DosPrintQSetInfoA( + IN LPSTR pszServer OPTIONAL, + IN LPSTR pszQueueName, + IN WORD uLevel, + IN PBYTE pbBuf, + IN WORD cbBuf, + IN WORD uParmNum + ) +{ + DWORD cbBufW; + LPWSTR QueueNameW = NULL; + DWORD rc; + LPWSTR ServerNameW = NULL; + LPBYTE StringAreaW; + LPVOID TempBufferW = NULL; + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint((PREFIX_DOSPRINT + "DosPrintQSetInfoA(" FORMAT_LPSTR ", %s, %d, %x, %d, %d)\n", + pszServer ? pszServer : "(local)", + pszQueueName, uLevel, pbBuf, cbBuf, uParmNum)); + } + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + QueueNameW = NetpAllocWStrFromStr( pszQueueName ); + if (QueueNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + // Compute wide buff size. + cbBufW = cbBuf * sizeof(WCHAR); + if ( cbBufW > (DWORD) MAX_WORD ) { + cbBufW = (DWORD) MAX_WORD; + } + + rc = NetApiBufferAllocate( + cbBufW, + (LPVOID *) (LPVOID) &TempBufferW ); + if (rc != NO_ERROR) { + goto Cleanup; + } + + StringAreaW = (LPBYTE)TempBufferW + cbBufW; + + rc = NetpConvertPrintQCharSet( + uLevel, + TRUE, // yes, is add or setinfo API + pbBuf, // from info + TempBufferW, // to info + TRUE, // yes, convert to UNICODE. + & StringAreaW ); // conv strings and update ptr + if (rc != NO_ERROR) { + goto Cleanup; + } + + rc = DosPrintQSetInfoW( + ServerNameW, + QueueNameW, + uLevel, + TempBufferW, + (WORD) cbBufW, + uParmNum); + +Cleanup: + if (QueueNameW != NULL) { + (VOID) NetApiBufferFree( QueueNameW ); + } + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + if (TempBufferW != NULL) { + (VOID) NetApiBufferFree( TempBufferW ); + } + return (rc); +} + +SPLERR SPLENTRY DosPrintQPauseA( + IN LPSTR pszServer OPTIONAL, + IN LPSTR pszQueueName + ) +{ + LPWSTR QueueNameW = NULL; + DWORD rc; + LPWSTR ServerNameW = NULL; + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint((PREFIX_DOSPRINT + "DosPrintQPauseA(" FORMAT_LPSTR ", %s)\n", + pszServer ? pszServer : "(local)", + pszQueueName)); + } + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + QueueNameW = NetpAllocWStrFromStr( pszQueueName ); + if (QueueNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + rc = DosPrintQPauseW(ServerNameW, QueueNameW); + +Cleanup: + if (QueueNameW != NULL) { + (VOID) NetApiBufferFree( QueueNameW ); + } + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + return (rc); +} + +SPLERR SPLENTRY DosPrintQContinueA( + IN LPSTR pszServer OPTIONAL, + IN LPSTR pszQueueName + ) +{ + LPWSTR QueueNameW = NULL; + DWORD rc; + LPWSTR ServerNameW = NULL; + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint((PREFIX_DOSPRINT + "DosPrintQContinueA(" FORMAT_LPSTR ", %s)\n", + pszServer ? pszServer : "(local)", + pszQueueName)); + } + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + QueueNameW = NetpAllocWStrFromStr( pszQueueName ); + if (QueueNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + rc = DosPrintQContinueW( ServerNameW, QueueNameW ); + +Cleanup: + if (QueueNameW != NULL) { + (VOID) NetApiBufferFree( QueueNameW ); + } + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + return (rc); +} + +SPLERR SPLENTRY DosPrintQPurgeA( + IN LPSTR pszServer OPTIONAL, + IN LPSTR pszQueueName + ) +{ + LPWSTR QueueNameW = NULL; + DWORD rc; + LPWSTR ServerNameW = NULL; + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint((PREFIX_DOSPRINT + "DosPrintQPurgeA(" FORMAT_LPSTR ", %s)\n", + pszServer ? pszServer : "(local)", + pszQueueName)); + } + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + QueueNameW = NetpAllocWStrFromStr( pszQueueName ); + if (QueueNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + rc = DosPrintQPurgeW(ServerNameW, QueueNameW); + +Cleanup: + if (QueueNameW != NULL) { + (VOID) NetApiBufferFree( QueueNameW ); + } + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + return (rc); +} + +SPLERR SPLENTRY DosPrintQAddA( + IN LPSTR pszServer OPTIONAL, + IN WORD uLevel, + IN PBYTE pbBuf, + IN WORD cbBuf + ) +{ + DWORD cbBufW; + DWORD rc; + LPWSTR ServerNameW = NULL; + LPBYTE StringAreaW; + LPVOID TempBufferW = NULL; + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint((PREFIX_DOSPRINT + "DosPrintQAddA(" FORMAT_LPSTR ", %d, %x, %d)\n", + pszServer ? pszServer : "(local)", + uLevel, pbBuf, cbBuf)); + } + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + // Compute wide buff size. + cbBufW = cbBuf * sizeof(WCHAR); + if ( cbBufW > (DWORD) MAX_WORD ) { + cbBufW = (DWORD) MAX_WORD; + } + + rc = NetApiBufferAllocate( + cbBufW, + (LPVOID *) (LPVOID) &TempBufferW ); + if (rc != NO_ERROR) { + goto Cleanup; + } + + StringAreaW = (LPBYTE)TempBufferW + cbBufW; + + rc = NetpConvertPrintQCharSet( + uLevel, + TRUE, // yes, is add or setinfo API + pbBuf, // from info + TempBufferW, // to info + TRUE, // yes, convert to UNICODE. + & StringAreaW ); // conv strings and update ptr + if (rc != NO_ERROR) { + goto Cleanup; + } + + rc = DosPrintQAddW( + ServerNameW, + uLevel, + TempBufferW, + (WORD) cbBufW ); + +Cleanup: + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + if (TempBufferW != NULL) { + (VOID) NetApiBufferFree( TempBufferW ); + } + return (rc); +} + +SPLERR SPLENTRY DosPrintQDelA( + IN LPSTR pszServer OPTIONAL, + IN LPSTR pszQueueName + ) +{ + LPWSTR QueueNameW = NULL; + DWORD rc; + LPWSTR ServerNameW = NULL; + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint((PREFIX_DOSPRINT + "DosPrintQDelA(" FORMAT_LPSTR " , %s)\n", + pszServer ? pszServer : "(local)", + pszQueueName)); + } + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + QueueNameW = NetpAllocWStrFromStr( pszQueueName ); + if (QueueNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + rc = DosPrintQDelW(ServerNameW, QueueNameW); + +Cleanup: + if (QueueNameW != NULL) { + (VOID) NetApiBufferFree( QueueNameW ); + } + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + return (rc); +} + +SPLERR SPLENTRY DosPrintJobSetInfoA( + IN LPSTR pszServer OPTIONAL, + IN WORD uJobId, + IN WORD uLevel, + IN PBYTE pbBuf, + IN WORD cbBuf, + IN WORD uParmNum + ) +{ + DWORD cbBufW; + DWORD rc; + LPWSTR ServerNameW = NULL; + LPBYTE StringAreaW; + LPVOID TempBufferW = NULL; // job structure with UNICODE strings. + + IF_DEBUG( DOSPRINT ) { + NetpKdPrint(( PREFIX_DOSPRINT + "DosPrintJobSetInfoA(" FORMAT_LPSTR ":, %d, %d, %x, %d, %d)\n", + pszServer ? pszServer : "(local)", + uJobId, + uLevel, + pbBuf, + cbBuf, + uParmNum)); + } + + if (pszServer && *pszServer) { + ServerNameW = NetpAllocWStrFromStr( pszServer ); + if (ServerNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } + + // Compute wide buff size. + cbBufW = cbBuf * sizeof(WCHAR); + if ( cbBufW > (DWORD) MAX_WORD ) { + cbBufW = (DWORD) MAX_WORD; + } + + rc = NetApiBufferAllocate( + cbBufW, + (LPVOID *) (LPVOID) &TempBufferW ); + if (rc != NO_ERROR) { + goto Cleanup; + } + + StringAreaW = (LPBYTE)TempBufferW + cbBufW; + + // Translate ANSI strings to UNICODE. + rc = NetpConvertPrintJobCharSet( + uLevel, + TRUE, // yes, is add or setinfo API + TempBufferW, // from info + pbBuf, // to info + TRUE, // yes, convert to UNICODE. + & StringAreaW ); // conv strings and update ptr + if (rc != NO_ERROR) { + goto Cleanup; + } + + // Process the actual API. + rc = DosPrintJobSetInfoW( + ServerNameW, + uJobId, + uLevel, + TempBufferW, + (WORD) cbBufW, + uParmNum); + +Cleanup: + if (ServerNameW != NULL) { + (VOID) NetApiBufferFree( ServerNameW ); + } + if (TempBufferW != NULL) { + (VOID) NetApiBufferFree( TempBufferW ); + } + return (rc); +} + diff --git a/private/net/dosprint/dosprtp.c b/private/net/dosprint/dosprtp.c new file mode 100644 index 000000000..aa41d0daf --- /dev/null +++ b/private/net/dosprint/dosprtp.c @@ -0,0 +1,440 @@ +/*++ + +Copyright (c) 1992-1993 Microsoft Corporation + +Module Name: + + DosPrtP.c + +Abstract: + + This contains macros and prototypes private to the DosPrint APIs. + +Author: + + John Rogers (JohnRo) 02-Oct-1992 + +Notes: + +Revision History: + + 02-Oct-1992 JohnRo + Created for RAID 3556: DosPrintQGetInfo(from downlevel) level 3, rc=124. + (4&5 too.) + 08-Feb-1993 JohnRo + RAID 10164: Data misalignment error during XsDosPrintQGetInfo(). + DosPrint API cleanup: avoid const vs. volatile compiler warnings. + Extracted job count routine to netlib for use by convprt.c stuff. + Added some IN and OUT keywords. + 24-Mar-1993 JohnRo + RAID 2974: NET PRINT says NT printer is held when it isn't. + 17-May-1993 JohnRo + FindLocalJob() should use INVALID_HANDLE_VALUE for consistentcy. + Use NetpKdPrint() where possible. + 29-Mar-1995 AlbertT + Support for pause/resume/purge printer queue added. + +--*/ + + +#ifndef UNICODE +#error "RxPrint APIs assume RxRemoteApi uses wide characters." +#endif + +#define NOMINMAX +#define NOSERVICE // Avoid <winsvc.h> vs. <lmsvc.h> conflicts. +#include <windows.h> + +#include <lmcons.h> // NET_API_STATUS. +#include <netdebug.h> // NetpKdPrint(), etc. + +#ifdef _WINSPOOL_ +#error "Include of winspool.h moved, make sure it doesn't get UNICODE." +#endif + +#undef UNICODE +#include <winspool.h> +#define UNICODE + +#ifndef _WINSPOOL_ +#error "Oops, winspool.h changed, make sure this code is still OK." +#endif + + +#include <dosprtp.h> // IF_DEBUG(), some of my prototypes. +#include <lmapibuf.h> // NetApiBufferFree(), etc. +#include <lmerr.h> // NO_ERROR, NERR_, and ERROR_ equates. +#include <lmshare.h> // SHARE_INFO_2, STYPE_ equates, etc. +#include <prefix.h> // PREFIX_ equates. +#include <rxprint.h> // PPRQINFOW, etc. +#include <string.h> // strrchr(). +#include <tstring.h> // NetpAlloc{type}From{type}. +#include <wchar.h> // wscrchr(). +#include "myspool.h" + +NET_API_STATUS +CommandALocalPrinterW( + IN LPWSTR PrinterName, + IN DWORD Command // PRINTER_CONTROL_PAUSE, etc. + ) +{ + NET_API_STATUS ApiStatus; + HANDLE PrinterHandle = INVALID_HANDLE_VALUE; + PRINTER_DEFAULTSW pd = { NULL, NULL, PRINTER_ACCESS_ADMINISTER }; + + IF_DEBUG( DOSPRTP ) { + NetpKdPrint(( PREFIX_DOSPRINT + "CommandALocalPrinterW: issuing command " FORMAT_DWORD + " for printer " FORMAT_LPWSTR ".\n", Command, PrinterName )); + } + + if ( !MyOpenPrinterW(PrinterName, &PrinterHandle, &pd)) { + ApiStatus = GetLastError(); + goto Cleanup; + } + + if ( !MySetPrinterW( + PrinterHandle, + 0, // info level + NULL, // no job structure + Command) ) { + + ApiStatus = GetLastError(); + + NetpKdPrint(( PREFIX_DOSPRINT + "CommandALocalPrinterW: FAILED COMMAND " FORMAT_DWORD + " for printer " FORMAT_LPWSTR ", api status " FORMAT_API_STATUS + ".\n", Command, PrinterName, ApiStatus )); + + goto Cleanup; + + } else { + ApiStatus = NO_ERROR; + } + + +Cleanup: + if (PrinterHandle != INVALID_HANDLE_VALUE) { + (VOID) MyClosePrinter(PrinterHandle); + } + + IF_DEBUG( DOSPRTP ) { + NetpKdPrint(( PREFIX_DOSPRINT + "CommandALocalPrinterW: returning api status " + FORMAT_API_STATUS ".\n", ApiStatus )); + } + return (ApiStatus); + +} // CommandALocalPrinterW + + +NET_API_STATUS +CommandALocalJob( + IN HANDLE PrinterHandle, OPTIONAL + IN DWORD JobId, + IN DWORD Level, + IN LPBYTE pJob, + IN DWORD Command // JOB_CONTROL_PAUSE, etc. + ) + +/*++ + +Routine Description: + + Sends a command to a Job based on a JobId. If a PrintHandle + is passed in, it is used; otherwise a temporary one is opened + and used instead. + + This is the Ansi version. + +Arguments: + + PrinterHandle - Print handle to use, may be NULL + + JobId - Job that should be modified + + Level - Specifies pJob info level + + pJob - Information to set about job, level specified by Level + + Command - Command to execute on job + +Return Value: + + Return code, may be a win32 error code (!?) + +--*/ + +{ + NET_API_STATUS ApiStatus; + HANDLE PrinterHandleClose = INVALID_HANDLE_VALUE; + + IF_DEBUG( DOSPRTP ) { + NetpKdPrint(( PREFIX_DOSPRINT + "CommandALocalJob: issuing command " FORMAT_DWORD " for job " + FORMAT_DWORD ".\n", Command, JobId )); + } + + // + // If a print handle wasn't passed in, open one ourselves. + // We store it in PrinterHandleClose so that we can close it later. + // + if ( PrinterHandle == NULL ) { + if ( !MyOpenPrinter( NULL, &PrinterHandle, NULL )) { + + ApiStatus = GetLastError(); + goto Cleanup; + } + PrinterHandleClose = PrinterHandle; + } + + if ( !MySetJobA( + PrinterHandle, + JobId, + Level, + pJob, + Command) ) { + + ApiStatus = GetLastError(); + + NetpKdPrint(( PREFIX_DOSPRINT + "CommandALocalJob: FAILED COMMAND " FORMAT_DWORD " for job " + FORMAT_DWORD ", api status " FORMAT_API_STATUS ".\n", + Command, JobId, ApiStatus )); + + goto Cleanup; + + } else { + ApiStatus = NO_ERROR; + } + + +Cleanup: + if (PrinterHandleClose != INVALID_HANDLE_VALUE) { + (VOID) MyClosePrinter(PrinterHandle); + } + + IF_DEBUG( DOSPRTP ) { + NetpKdPrint(( PREFIX_DOSPRINT + "CommandALocalJob: returning api status " FORMAT_API_STATUS + ".\n", ApiStatus )); + } + return (ApiStatus); + +} // CommandALocalJob + + +// Note: FindLocalJob() calls SetLastError() to indicate the cause of an error. +// Return INVALID_HANDLE_VALUE on error. +HANDLE +FindLocalJob( + IN DWORD JobId + ) +{ + DWORD cbPrinter, cReturned, rc, cbJob, i; + LPPRINTER_INFO_1 pPrinter; + LPPRINTER_INFO_1 pPrinterArray = NULL; + LPJOB_INFO_2 pJob = NULL; + HANDLE hPrinter = INVALID_HANDLE_VALUE; + + if (!MyEnumPrinters(PRINTER_ENUM_LOCAL, NULL, 1, NULL, 0, &cbPrinter, + &cReturned)) { + + rc=GetLastError(); + if (rc != ERROR_INSUFFICIENT_BUFFER) { + goto CleanupError; + } + + pPrinterArray = (LPVOID) GlobalAlloc(GMEM_FIXED, cbPrinter); + if (pPrinterArray == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto CleanupError; + } + + if ( !MyEnumPrinters(PRINTER_ENUM_LOCAL, + NULL, 1, (LPBYTE)pPrinterArray, cbPrinter, + &cbPrinter, &cReturned) ) { + + rc = GetLastError(); + NetpKdPrint(( PREFIX_DOSPRINT + "FindLocalJob: MyEnumPrinters(2nd) failed, rc = " + FORMAT_API_STATUS )); + + NetpAssert( FALSE ); // "can't happen". + goto CleanupError; + } + } + + pPrinter = pPrinterArray; + for (i=0; i<cReturned; i++) { + + if (MyOpenPrinter(pPrinter->pName, &hPrinter, NULL)) { + + NetpAssert( hPrinter != INVALID_HANDLE_VALUE ); + + if (!MyGetJob(hPrinter, JobId, 2, NULL, 0, &cbJob)) { + + rc=GetLastError(); + + if (rc == ERROR_INSUFFICIENT_BUFFER) { + + pJob = (LPVOID) GlobalAlloc(GMEM_FIXED, cbJob); + if (pJob == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto CleanupError; + } + + if ( !MyGetJob(hPrinter, + JobId, 2, (LPBYTE)pJob, cbJob, &cbJob) ) { + + rc = GetLastError(); + NetpKdPrint(( PREFIX_DOSPRINT + "FindLocalJob: MyGetJob(2nd) failed, rc = " + FORMAT_API_STATUS )); + + NetpAssert( FALSE ); // "can't happen". + goto CleanupError; + } + + // Got it! + (VOID) GlobalFree(pPrinterArray); + + (VOID) GlobalFree(pJob); + + return(hPrinter); + } + } + + (VOID) MyClosePrinter(hPrinter); + } + // BUGBUG: Ignore errors from OpenPrinter? + + // Not in this queue, so keep checking... + pPrinter++; + + } + + IF_DEBUG( DOSPRTP ) { + NetpKdPrint(( PREFIX_DOSPRINT + "FindLocalJob: couldn't find job " FORMAT_DWORD " in " + FORMAT_DWORD " queue(s).\n", JobId, cReturned )); + } + + + rc = NERR_JobNotFound; + +CleanupError: + + if (pJob != NULL) { + (VOID) GlobalFree(pJob); + } + if (pPrinterArray != NULL) { + (VOID) GlobalFree(pPrinterArray); + } + + SetLastError( rc ); + + return (INVALID_HANDLE_VALUE); + +} // FindLocalJob + + + +LPSTR +FindQueueNameInPrinterNameA( + IN LPCSTR PrinterName + ) +{ + LPSTR QueueName; + NetpAssert( PrinterName != NULL ); + + QueueName = strrchr( PrinterName, '\\'); + + if (QueueName) { + ++QueueName; // Skip past the backslash. + } else { + QueueName = (LPSTR) PrinterName; + } + NetpAssert( QueueName != NULL ); + return (QueueName); +} + + +LPWSTR +FindQueueNameInPrinterNameW( + IN LPCWSTR PrinterName + ) +{ + LPWSTR QueueName; + NetpAssert( PrinterName != NULL ); + + QueueName = wcsrchr( PrinterName, L'\\'); + if (QueueName) { + ++QueueName; // Skip past the backslash. + } else { + QueueName = (LPWSTR) PrinterName; + } + NetpAssert( QueueName != NULL ); + return (QueueName); +} + + +WORD +PrjStatusFromJobStatus( + IN DWORD JobStatus + ) +{ + WORD PrjStatus = 0; + + if (JobStatus & JOB_STATUS_SPOOLING) + + PrjStatus |= PRJ_QS_SPOOLING; + + if (JobStatus & JOB_STATUS_PAUSED) + + PrjStatus |= PRJ_QS_PAUSED; + + if (JobStatus & JOB_STATUS_PRINTING) + + PrjStatus |= PRJ_QS_PRINTING; + + if (JobStatus & JOB_STATUS_ERROR) + + PrjStatus |= PRJ_ERROR; + + return (PrjStatus); + +} // PrjStatusFromJobStatus + + +WORD +PrqStatusFromPrinterStatus( + IN DWORD PrinterStatus + ) +{ + WORD PrqStatus; + + if (PrinterStatus & PRINTER_STATUS_PAUSED) { + + PrqStatus = PRQ_PAUSED; + + } else if (PrinterStatus & PRINTER_STATUS_ERROR) { + + PrqStatus = PRQ_ERROR; + + } else if (PrinterStatus & PRINTER_STATUS_PENDING_DELETION) { + + PrqStatus = PRQ_PENDING; + + } else { + + PrqStatus = PRQ_ACTIVE; + + } + + return (PrqStatus); + +} // PrqStatusFromPrinterStatus + + + diff --git a/private/net/dosprint/dosprtw.c b/private/net/dosprint/dosprtw.c new file mode 100644 index 000000000..820fa894d --- /dev/null +++ b/private/net/dosprint/dosprtw.c @@ -0,0 +1,2284 @@ +/*++ + +Copyright (c) 1991-1993 Microsoft Corporation + +Module Name: + + DosPrtW.c + +Abstract: + + This module provides the UNICODE mapping layer from the old DosPrint APIs + to the new all singing all dancing beautiful Print APIs. (The ANSI + mapping layer is in DosPrint.c) + +Author: + + Dave Snipp (DaveSn) 26-Apr-1991 + +Revision History: + + 09-Jul-1992 JohnRo + Created this file (from DaveSn's DosPrint.c) for RAID 10324: net print + vs. UNICODE. + 05-Oct-1992 JohnRo + RAID 3556: DosPrintQGetInfo(from downlevel) level 3, rc=124. (4&5 too.) + RAID 3580: lmsvcs.exe: access violation from OS/2 DosPrintJobGetInfo. + RAID 8333: view printer queues hangs DOS LM enh client. + Make sure data type in job level 1 is null terminated. + Fixed job submitted times. + Fixed error code if GlobalAlloc fails. + Fixed memory leak in DosPrintQGetInfoW. + Fixed DosPrintQEnumW level 5 array bug. + Fixed DosPrintJobEnumW levels 2 and 3. + 25-Nov-1992 JohnRo + RAID 1661: downlevel to NT DosPrintDestEnum not supported. + Added code to track down empty queue name. + Quiet normal debug output. + Avoid const vs. volatile compiler warnings. + Avoid other new compiler warnings. + 08-Feb-1993 JohnRo + RAID 10164: Data misalignment error during XsDosPrintQGetInfo(). + 22-Mar-1993 JohnRo + RAID 2974: NET PRINT says NT printer is held when it isn't. + 11-May-1993 JohnRo + RAID 9942: fix queue name in job info level 3. + 14-May-1993 JohnRo + RAID 9961: DosPrintDestEnum returns NO_ERROR to downlevel but + pcReturned=0; should return NERR_DestNotFound. + Fixed data type returned from PrjInfoFixedSizeW(). + 18-May-1993 JohnRo + DosPrintQGetInfoW underestimates number of bytes needed. + Use NetpKdPrint() where possible. + Made changes suggested by PC-LINT. + 04-Jun-1993 JohnRo + RAID 10222: DosPrintQEnumW returns ERROR_INVALID_USER_BUFFER + when queue is empty. + Made changes suggested by PC-LINT 5.0 + 08-Jul-1993 JohnRo + RAID 15509: GetJob() API sometimes returned TRUE, even on error case. + Also added some >64KB checks. + Added some assert checks... + 13-Jul-1993 JohnRo + Intermittent empty print queue (was buggy after some MyEnumJobs calls). + 29-Mar-1995 AlbertT + Support for pause/resume/purge printer queue added. + SetJobInfo 1 comment field (translated into document name) support + added so that chicago clients can set the doc name. + +--*/ + + +#ifndef UNICODE +#error "RxPrint APIs assume RxRemoteApi uses wide characters." +#endif + +#define NOMINMAX +#define NOSERVICE // Avoid <winsvc.h> vs. <lmsvc.h> conflicts. +#include <windows.h> + +//#include <lm.h> +#include <netdebug.h> + +#include <string.h> + + +#ifdef _WINSPOOL_ +#error "Include of winspool.h moved, make sure it doesn't get UNICODE." +#endif + +#undef UNICODE +#include <winspool.h> +#define UNICODE + +#ifndef _WINSPOOL_ +#error "Oops, winspool.h changed, make sure this code is still OK." +#endif + + +#include <dosprint.h> +#include <dosprtp.h> // IF_DEBUG(), CommandALocalJob(), etc. +#include <lmapibuf.h> // NetApiBufferFree(), etc. +#include <lmerr.h> // NO_ERROR, NERR_, and ERROR_ equates. +#include <lmshare.h> // LPSHARE_INFO_1, STYPE_ equates, etc. +#include <prefix.h> // PREFIX_ equates. +#include <stddef.h> // offsetof(). +#include <timelib.h> // NetpSystemTimeToGmtTime(). +#include <tstring.h> // WCSSIZE(), NetpNCopy{type}To{type}. +#include <wchar.h> // wsclen(), wcscpy(), etc. +#include "myspool.h" + + +#define STR_CONV_SIZE(psz) ( (strlen(psz)+1) * sizeof(WCHAR) ) + +// NULL_STR_CONV_SIZE: Compute size needed for converted string, which +// is possibly a null pointer but downlevel really wants ptr to null char. +#define NULL_STR_CONV_SIZE(psz) ( (psz) ? STR_CONV_SIZE(psz) : sizeof(WCHAR) ) + + +#define ARRAY_END ((DWORD) -1) + +#define MAX_WORD ( (WORD) (~0) ) + +// BUGBUG: Come up with a better error code for this? +#define MY_PROTOCOL_LIMIT_ERROR ERROR_NOT_ENOUGH_MEMORY + +#define WIN95_ENVIRONMENT "Windows 4.0" +#define WIN95_DRIVER_SHARE "\\print$\\WIN40\\0" + + + +DBGSTATIC LPWSTR +PackAnsiStringsToW( + LPSTR *pSource, + LPBYTE pDest, + CONST DWORD *DestOffsets, + LPWSTR pEnd +) +{ + while (*DestOffsets != ARRAY_END) { + if (*pSource) { + pEnd-=(strlen(*pSource) + 1); + + // Copy the string and convert chars while we're at it. + NetpCopyStrToWStr(pEnd, *pSource); + + *(LPWSTR *)(pDest+*DestOffsets) = pEnd; + } else { + + // BUGBUG? I think this first version is wrong, as downlevel (e.g. + // OS/2 print manager) doesn't handle null pointers well? + // --JR, 19-Jun-1992 + // + // *(LPWSTR *)(pDest+*DestOffsets)=0; + + --pEnd; // need 1 char for this. + *pEnd = L'\0'; + *(LPWSTR *)(pDest+*DestOffsets) = pEnd; + } + pSource++; + DestOffsets++; + } + + return pEnd; +} + +DBGSTATIC DWORD +PrjInfoFixedSizeW( + IN DWORD Level // assumed valid + ) +{ + switch (Level) { + + case 0: + return sizeof(WORD); // job number. + case 1: + return (sizeof(PRJINFOW)); + case 2: + return (sizeof(PRJINFO2W)); + case 3: + return (sizeof(PRJINFO3W)); + default: + NetpAssert( FALSE ); + return (0); + } + /*NOTREACHED*/ +} + +DBGSTATIC DWORD +GetPrjInfoSizeW( + IN DWORD Level, + IN LPJOB_INFO_2 pJob, + IN LPCWSTR QueueNameW, + IN LPPRINTER_INFO_2 pPrinter OPTIONAL +) +{ + NetpAssert( pJob != NULL ); + switch (Level) { + + case 0: + + return sizeof(WORD); // job number. + + case 1: + + return sizeof(PRJINFOW) + + NULL_STR_CONV_SIZE( (LPSTR) (pJob->pParameters) ) + + NULL_STR_CONV_SIZE( (LPSTR) (pJob->pStatus) ) + + NULL_STR_CONV_SIZE( (LPSTR) (pJob->pDocument) ); // fake pszComment + + case 2: + + return sizeof(PRJINFO2W) + + NULL_STR_CONV_SIZE( (LPSTR) (pJob->pUserName) ) + + NULL_STR_CONV_SIZE( (LPSTR) (pJob->pDocument) ) + // fake pszComment + NULL_STR_CONV_SIZE( (LPSTR) (pJob->pDocument) ); + + case 3: + + NetpAssert( pPrinter != NULL ); + NetpAssert( QueueNameW != NULL ); + + return sizeof(PRJINFO3W) + + NULL_STR_CONV_SIZE( (LPSTR) (pJob->pUserName) ) + + NULL_STR_CONV_SIZE( (LPSTR) (pJob->pDocument) ) + // fake pszComment + NULL_STR_CONV_SIZE( (LPSTR) (pJob->pDocument) ) + + NULL_STR_CONV_SIZE( (LPSTR) (pJob->pNotifyName) ) + + NULL_STR_CONV_SIZE( (LPSTR) (pJob->pDatatype) ) + + NULL_STR_CONV_SIZE( (LPSTR) (pJob->pParameters) ) + + NULL_STR_CONV_SIZE( (LPSTR) (pJob->pStatus) ) + + WCSSIZE( QueueNameW ) + // pszQueue + NULL_STR_CONV_SIZE( (LPSTR) (pPrinter->pPrintProcessor) ) + + NULL_STR_CONV_SIZE( (LPSTR) (pPrinter->pParameters) ) + + NULL_STR_CONV_SIZE( (LPSTR) (pJob->pDriverName) ) + + // BUGBUG: pDriverData? + NULL_STR_CONV_SIZE( (LPSTR) (pJob->pPrinterName) ); + + default: + NetpKdPrint(( PREFIX_DOSPRINT + "GetPrjInfoSizeW: invalid level!\n" )); + return 0; + + } + /*NOTREACHED*/ +} + +// Print job info string table (for level 1). +DBGSTATIC CONST DWORD PrjInfo1StringsW[]={ + offsetof(PRJINFOW, pszParms), + offsetof(PRJINFOW, pszStatus), + offsetof(PRJINFOW, pszComment), + ARRAY_END}; + +// Print job info string table (for level 2). +DBGSTATIC CONST DWORD PrjInfo2StringsW[]={ + offsetof(PRJINFO2W, pszUserName), + offsetof(PRJINFO2W, pszComment), + offsetof(PRJINFO2W, pszDocument), + (DWORD) -1}; + +// Print job info string table (for items which level 3 has on top of level 2). +DBGSTATIC CONST DWORD PrjInfo3StringsW[]={ + offsetof(PRJINFO3W, pszNotifyName), + offsetof(PRJINFO3W, pszDataType), + offsetof(PRJINFO3W, pszParms), + offsetof(PRJINFO3W, pszStatus), + offsetof(PRJINFO3W, pszQProcName), + offsetof(PRJINFO3W, pszQProcParms), + offsetof(PRJINFO3W, pszDriverName), + offsetof(PRJINFO3W, pszPrinterName), + (DWORD) -1}; + +DBGSTATIC LPWSTR +CopyJobToPrjInfoW( + IN DWORD Level, + IN LPJOB_INFO_2 pJob, + IN LPCWSTR QueueNameW, + IN LPPRINTER_INFO_2 pPrinter OPTIONAL, + OUT PBYTE pBuffer, + IN OUT LPWSTR pEnd + ) +{ + LPSTR *pSourceStrings; + NET_API_STATUS rc; + + NetpAssert( pBuffer != NULL ); + NetpAssert( pEnd != NULL ); + NetpAssert( pJob != NULL ); + + switch (Level) { + + case 0: + + { + PWORD pJobIds = (PWORD) pBuffer; + *pJobIds = (WORD)pJob->JobId; + } + break; + + case 1: + { + LPSTR SourceStrings[sizeof(PrjInfo1StringsW)/sizeof(DWORD)]; + PPRJINFOW pPrjInfo = (LPVOID) pBuffer; + + pSourceStrings=SourceStrings; + *pSourceStrings++ = (LPSTR) (pJob->pParameters); + *pSourceStrings++ = (LPSTR) (pJob->pStatus); + *pSourceStrings++ = (LPSTR) (pJob->pDocument); // fake pszComment + + pEnd = PackAnsiStringsToW( + SourceStrings, + (LPBYTE) (LPVOID) pPrjInfo, + PrjInfo1StringsW, + pEnd); + + pPrjInfo->uJobId = (WORD)pJob->JobId; + + if (pJob->pUserName) + (VOID) NetpNCopyStrToWStr( + (LPWSTR) (pPrjInfo->szUserName), + (LPSTR) (pJob->pUserName), + LM20_UNLEN+1); + else + pPrjInfo->szUserName[0] = L'\0'; + + if (pJob->pNotifyName) + (VOID) NetpNCopyStrToWStr( + (LPWSTR) (pPrjInfo->szNotifyName), + (LPSTR) (pJob->pNotifyName), + LM20_CNLEN+1); + else + pPrjInfo->szNotifyName[0] = L'\0'; + + if (pJob->pDatatype) { + (VOID) NetpNCopyStrToWStr( + (LPWSTR) (pPrjInfo->szDataType), + (LPSTR) (pJob->pDatatype), + DTLEN+1); + pPrjInfo->szDataType[DTLEN] = L'\0'; + } else { + pPrjInfo->szDataType[0] = L'\0'; + } + + pPrjInfo->uPosition = (WORD)pJob->Position; + + pPrjInfo->fsStatus = PrjStatusFromJobStatus( pJob->Status ); + + rc = NetpSystemTimeToGmtTime( + &pJob->Submitted, + &pPrjInfo->ulSubmitted ); + NetpAssert( rc == NO_ERROR ); + + pPrjInfo->ulSize = pJob->Size; + } + break; + + case 2: /*FALLTHROUGH*/ + case 3: + { + PPRJINFO2W pPrjInfo = (LPVOID) pBuffer; + LPSTR SourceStrings[sizeof(PrjInfo2StringsW)/sizeof(DWORD)]; + + pSourceStrings=SourceStrings; + *pSourceStrings++ = (LPSTR) (pJob->pUserName); + *pSourceStrings++ = (LPSTR) (pJob->pDocument); // fake pszComment + *pSourceStrings++ = (LPSTR) (pJob->pDocument); + + pEnd = PackAnsiStringsToW( + SourceStrings, + (LPBYTE) (LPVOID) pPrjInfo, + PrjInfo2StringsW, + pEnd); + + pPrjInfo->uJobId = (WORD)pJob->JobId; + pPrjInfo->uPriority = (WORD)pJob->Priority; + + pPrjInfo->uPosition = (WORD)pJob->Position; + + pPrjInfo->fsStatus = PrjStatusFromJobStatus( pJob->Status ); + + rc = NetpSystemTimeToGmtTime( + &pJob->Submitted, + &pPrjInfo->ulSubmitted ); + NetpAssert( rc == NO_ERROR ); + + pPrjInfo->ulSize = pJob->Size; + } + + if (Level == 3) { + PPRJINFO3W pPrjInfo = (LPVOID) pBuffer; + LPSTR SourceStrings[sizeof(PrjInfo3StringsW)/sizeof(DWORD)]; + + NetpAssert( pPrinter != NULL ); + + // + // Copy queue name first, as it is already right char set. + // + NetpAssert( QueueNameW != NULL ); + pEnd-=(wcslen(QueueNameW) + 1); + + (VOID) wcscpy(pEnd, QueueNameW); + + pPrjInfo->pszQueue = pEnd; + + // + // Copy and convert other strings. + // + pSourceStrings=SourceStrings; + *pSourceStrings++ = (LPSTR) (pJob->pNotifyName); + *pSourceStrings++ = (LPSTR) (pJob->pDatatype); + *pSourceStrings++ = (LPSTR) (pJob->pParameters); + *pSourceStrings++ = (LPSTR) (pJob->pStatus); + *pSourceStrings++ = pPrinter->pPrintProcessor; + *pSourceStrings++ = pPrinter->pParameters; + *pSourceStrings++ = (LPSTR) (pJob->pDriverName); + *pSourceStrings++ = (LPSTR) (pJob->pPrinterName); + + pEnd = PackAnsiStringsToW( + SourceStrings, + (LPBYTE) (LPVOID) pPrjInfo, + PrjInfo3StringsW, + pEnd); + + pPrjInfo->pDriverData = NULL; + } + + break; + + default: + NetpKdPrint(( PREFIX_DOSPRINT + "CopyJobToPrjInfoW: invalid level!\n" )); + + } + + IF_DEBUG( DOSPRTW ) { + if (NetpIsPrintJobLevelValid( Level, FALSE ) ) { + NetpKdPrint(( PREFIX_DOSPRINT "CopyJobToPrjInfoW: " + " created print job:\n" )); + NetpDbgDisplayPrintJob( Level, pBuffer, TRUE ); // Yes, has UNICODE. + } + } + + return pEnd; +} + +DBGSTATIC DWORD +GetPrqInfoSizeW( + IN DWORD Level, + IN LPCWSTR QueueNameW, + IN LPPRINTER_INFO_2 pPrinter + ) +{ + NetpAssert( QueueNameW != NULL ); + NetpAssert( (*QueueNameW) != L'\0' ); + + switch (Level) { + + case 0: + + return ( (LM20_QNLEN+1) * sizeof(WCHAR) ); + + case 1: /*FALLTHROUGH*/ + case 2: + + return sizeof(PRQINFOW) + + NULL_STR_CONV_SIZE( pPrinter->pSepFile ) + + NULL_STR_CONV_SIZE( pPrinter->pPrintProcessor ) + + NULL_STR_CONV_SIZE( pPrinter->pPortName ) + + NULL_STR_CONV_SIZE( pPrinter->pParameters ) + + NULL_STR_CONV_SIZE( pPrinter->pComment ); + + case 3: /*FALLTHROUGH*/ + case 4: + + NetpAssert( QueueNameW != NULL ); + + return sizeof(PRQINFO3W) + + WCSSIZE( QueueNameW ) + // pszName + NULL_STR_CONV_SIZE( pPrinter->pSepFile ) + + NULL_STR_CONV_SIZE( pPrinter->pPrintProcessor ) + + NULL_STR_CONV_SIZE( pPrinter->pParameters ) + + NULL_STR_CONV_SIZE( pPrinter->pComment ) + + NULL_STR_CONV_SIZE( pPrinter->pPortName ) + + NULL_STR_CONV_SIZE( pPrinter->pDriverName ); + // BUGBUG: no support for pszDriverData? + + case 5: + + NetpAssert( QueueNameW != NULL ); + + return sizeof(LPWSTR) + + WCSSIZE( QueueNameW ); // pszName + + default: + NetpKdPrint(( PREFIX_DOSPRINT + "GetPrqInfoSizeW: invalid level!\n" )); + + } + + return 0; +} + +DBGSTATIC DWORD +GetDrvInfoSizeW( + IN DWORD Level, + IN LPDRIVER_INFO_3A pDriverInfo3, + IN LPCSTR pUNCSharePath, + OUT LPDWORD pdwDependentFileCount + ) +{ + LPSTR psz; + DWORD dwSize; + + switch (Level) { + case 52: + dwSize = sizeof(PRQINFO52W) + + NULL_STR_CONV_SIZE(pDriverInfo3->pName) + + NULL_STR_CONV_SIZE(GetFileNameA(pDriverInfo3->pDriverPath)) + + NULL_STR_CONV_SIZE(GetFileNameA(pDriverInfo3->pDataFile)) + + NULL_STR_CONV_SIZE(GetFileNameA(pDriverInfo3->pConfigFile)) + + NULL_STR_CONV_SIZE(GetFileNameA(pDriverInfo3->pHelpFile)) + + NULL_STR_CONV_SIZE(pDriverInfo3->pDefaultDataType) + + NULL_STR_CONV_SIZE(pDriverInfo3->pMonitorName) + + NULL_STR_CONV_SIZE(pUNCSharePath); + + *pdwDependentFileCount = 0; + for ( psz = pDriverInfo3->pDependentFiles; + *psz ; psz += strlen(psz) + 1 ) { + + dwSize += NULL_STR_CONV_SIZE(GetFileNameA(psz)); + (*pdwDependentFileCount)++; + } + + // + // For the '\0's + // + dwSize += (MAX_DEPENDENT_FILES-*pdwDependentFileCount)*sizeof(WCHAR); + return dwSize; + + default: + NetpKdPrint(( PREFIX_DOSPRINT "GetDrvInfoSizeW: invalid level!\n" )); + + } + return 0; + +} + +DBGSTATIC DWORD +PrqInfoFixedSizeW( + IN DWORD Level // assumed valid + ) +{ + switch (Level) { + case 0: + return ( (LM20_QNLEN+1) * sizeof(WCHAR) ); + case 1: /*FALLTHROUGH*/ + case 2: + return (sizeof(PRQINFOW)); + case 3: /*FALLTHROUGH*/ + case 4: + return (sizeof(PRQINFO3W)); + case 5: + return (sizeof(LPWSTR)); + default: + NetpAssert( FALSE ); // Level should be valid! + return (0); + } + /*NOTREACHED*/ +} + +// String table for Q levels 1,2 +DBGSTATIC CONST DWORD PrqInfo1StringsW[]={ + offsetof(PRQINFOW, pszSepFile), + offsetof(PRQINFOW, pszPrProc), + offsetof(PRQINFOW, pszDestinations), + offsetof(PRQINFOW, pszParms), + offsetof(PRQINFOW, pszComment), + ARRAY_END}; + +// String table for Q levels 3,4. +DBGSTATIC CONST DWORD PrqInfo3StringsW[]={ + offsetof(PRQINFO3W, pszSepFile), + offsetof(PRQINFO3W, pszPrProc), + offsetof(PRQINFO3W, pszParms), + offsetof(PRQINFO3W, pszComment), + offsetof(PRQINFO3W, pszPrinters), + offsetof(PRQINFO3W, pszDriverName), + (DWORD) -1}; + +// Print driver info3 string table (for level 52) +DBGSTATIC CONST DWORD PrqInfo52StringsW[]={ + offsetof(PRQINFO52W, pszModelName), + offsetof(PRQINFO52W, pszDriverName), + offsetof(PRQINFO52W, pszDataFileName), + offsetof(PRQINFO52W, pszMonitorName), + offsetof(PRQINFO52W, pszDriverPath), + offsetof(PRQINFO52W, pszDefaultDataType), + offsetof(PRQINFO52W, pszHelpFile), + offsetof(PRQINFO52W, pszConfigFile), + offsetof(PRQINFO52W, pszDependentNames[0]), + offsetof(PRQINFO52W, pszDependentNames[1]), + offsetof(PRQINFO52W, pszDependentNames[2]), + offsetof(PRQINFO52W, pszDependentNames[3]), + offsetof(PRQINFO52W, pszDependentNames[4]), + offsetof(PRQINFO52W, pszDependentNames[5]), + offsetof(PRQINFO52W, pszDependentNames[6]), + offsetof(PRQINFO52W, pszDependentNames[7]), + offsetof(PRQINFO52W, pszDependentNames[8]), + offsetof(PRQINFO52W, pszDependentNames[9]), + offsetof(PRQINFO52W, pszDependentNames[10]), + offsetof(PRQINFO52W, pszDependentNames[11]), + offsetof(PRQINFO52W, pszDependentNames[12]), + offsetof(PRQINFO52W, pszDependentNames[13]), + offsetof(PRQINFO52W, pszDependentNames[14]), + offsetof(PRQINFO52W, pszDependentNames[15]), + offsetof(PRQINFO52W, pszDependentNames[16]), + offsetof(PRQINFO52W, pszDependentNames[17]), + offsetof(PRQINFO52W, pszDependentNames[18]), + offsetof(PRQINFO52W, pszDependentNames[19]), + (DWORD) -1}; + +DBGSTATIC LPWSTR +CopyPrinterToPrqInfoW( + IN LPPRINTER_INFO_2 pPrinter, + IN DWORD Level, + OUT LPBYTE pBuffer, + IN LPCWSTR QueueNameW, + OUT LPWSTR pEnd + ) +{ + LPSTR *pSourceStrings; + + NetpAssert( pEnd != NULL ); + NetpAssert( QueueNameW != NULL ); + NetpAssert( (*QueueNameW) != L'\0' ); + + switch (Level) { + + case 0: + (VOID) wcsncpy( + (LPWSTR) (LPVOID) pBuffer, + QueueNameW, + LM20_QNLEN); + break; + + case 1: /*FALLTHROUGH*/ + case 2: + + { + LPSTR SourceStrings[sizeof(PrqInfo1StringsW)/sizeof(DWORD)]; + PPRQINFOW pPrqInfo = (LPVOID) pBuffer; + + pSourceStrings=SourceStrings; + *pSourceStrings++ = pPrinter->pSepFile; + *pSourceStrings++ = pPrinter->pPrintProcessor; + *pSourceStrings++ = pPrinter->pPortName; + *pSourceStrings++ = pPrinter->pParameters; + *pSourceStrings++ = pPrinter->pComment; + + pEnd = PackAnsiStringsToW( + SourceStrings, + (LPBYTE) (LPVOID) pPrqInfo, + PrqInfo1StringsW, + pEnd); + + NetpAssert( QueueNameW != NULL ); + + (VOID) wcsncpy( + pPrqInfo->szName, // dest + QueueNameW, // src + LM20_QNLEN+1); // char count + + pPrqInfo->uPriority = (WORD)pPrinter->Priority; + pPrqInfo->uStartTime = (WORD)pPrinter->StartTime; + pPrqInfo->uUntilTime = (WORD)pPrinter->UntilTime; + + pPrqInfo->fsStatus = PrqStatusFromPrinterStatus( pPrinter->Status ); + + pPrqInfo->cJobs = (WORD)pPrinter->cJobs; + } + + break; + + case 3: /*FALLTHROUGH*/ + case 4: + { + LPSTR SourceStrings[sizeof(PrqInfo3StringsW)/sizeof(DWORD)]; + PPRQINFO3W pPrqInfo = (LPVOID) pBuffer; + + // + // Copy queue name first, as it is already right char set. + // + NetpAssert( QueueNameW != NULL ); + pEnd-=(wcslen(QueueNameW) + 1); + + (VOID) wcscpy(pEnd, QueueNameW); + + pPrqInfo->pszName = pEnd; + + // + // Copy and convert other strings. + // + pSourceStrings=SourceStrings; + *pSourceStrings++ = pPrinter->pSepFile; + *pSourceStrings++ = pPrinter->pPrintProcessor; + *pSourceStrings++ = pPrinter->pParameters; + *pSourceStrings++ = pPrinter->pComment; + *pSourceStrings++ = pPrinter->pPortName; // pszPrinters + *pSourceStrings++ = pPrinter->pDriverName; + + pEnd = PackAnsiStringsToW( + SourceStrings, + (LPBYTE) (LPVOID) pPrqInfo, + PrqInfo3StringsW, + pEnd); + + pPrqInfo->uPriority = (WORD)pPrinter->Priority; + pPrqInfo->uStartTime = (WORD)pPrinter->StartTime; + pPrqInfo->uUntilTime = (WORD)pPrinter->UntilTime; + + pPrqInfo->fsStatus = PrqStatusFromPrinterStatus( pPrinter->Status ); + + pPrqInfo->cJobs = (WORD)pPrinter->cJobs; + pPrqInfo->pDriverData = NULL; // BUGBUG better support for this? + + // Note: if level is 4, caller will add array of jobs after this. + + break; + } + + case 5: + NetpAssert( QueueNameW != NULL ); + + pEnd -= (wcslen( QueueNameW ) + 1); + * (LPWSTR *) pBuffer = pEnd; + + (VOID) wcscpy( + pEnd, // dest + QueueNameW ); // src + + + break; + + default: + NetpKdPrint(( PREFIX_DOSPRINT + "CopyPrinterToPrqInfoW: invalid level!\n" )); + + } + +#if DBG + IF_DEBUG( DOSPRTW ) { + if (NetpIsPrintQLevelValid( Level, FALSE) ) { + DWORD PretendLevel = Level; // we can use this level unless... + NetpKdPrint(( PREFIX_DOSPRINT "CopyPrinterToPrqInfoW: " + " created print queue:\n" )); + if ( (Level == 2) || (Level == 4) ) { + if (Level == 2) { + PretendLevel = 1; + } else { + PretendLevel = 3; + } + NetpKdPrint(( + " (no jobs copied yet, so pretending info level is " + FORMAT_DWORD ", real info level is " + FORMAT_DWORD ").\n", + PretendLevel, Level )); + } + NetpDbgDisplayPrintQ( + PretendLevel, + pBuffer, + TRUE ); // Yes, has UNICODE. + } + } +#endif + + return pEnd; +} + +DBGSTATIC LPWSTR +CopyDriverToPrqInfoW( + IN LPDRIVER_INFO_3A pDriver3, + IN DWORD dwDependentFileCount, + IN LPSTR pUNCSharePath, + IN DWORD Level, + OUT LPBYTE pBuffer, + OUT LPWSTR pEnd + ) +{ + LPSTR *pSourceStrings; + LPSTR psz; + + NetpAssert( pEnd != NULL ); + NetpAssert(MAX_DEPENDENT_FILES == 20); + + switch (Level) { + + case 52: + { + PPRQINFO52W pPrqInfo = (LPVOID) pBuffer; + LPSTR SourceStrings[sizeof(PrqInfo52StringsW)/sizeof(DWORD)]; + + ZeroMemory((LPBYTE)SourceStrings, sizeof(SourceStrings)); + + pSourceStrings=SourceStrings; + *pSourceStrings++ = pDriver3->pName; + *pSourceStrings++ = GetFileNameA(pDriver3->pDriverPath); + *pSourceStrings++ = GetFileNameA(pDriver3->pDataFile); + *pSourceStrings++ = GetFileNameA(pDriver3->pMonitorName); + *pSourceStrings++ = pUNCSharePath; + *pSourceStrings++ = GetFileNameA(pDriver3->pDefaultDataType); + *pSourceStrings++ = GetFileNameA(pDriver3->pHelpFile); + *pSourceStrings++ = GetFileNameA(pDriver3->pConfigFile); + + for ( psz = pDriver3->pDependentFiles ; *psz ; + psz += strlen(psz) + 1 ) { + + *pSourceStrings++ = GetFileNameA(psz); + } + + pEnd = PackAnsiStringsToW( + SourceStrings, + (LPBYTE) (LPVOID)pPrqInfo, + PrqInfo52StringsW, + pEnd); + + pPrqInfo->uVersion = (WORD)pDriver3->cVersion; + pPrqInfo->cDependentNames = (WORD)dwDependentFileCount; + } + + break; + + + default: + NetpKdPrint(( PREFIX_DOSPRINT + "CopyPrinterToPrqInfoW: invalid level!\n" )); + + } + + return pEnd; +} + +DBGSTATIC NET_API_STATUS +ComputeSpaceNeededForJobs( + IN LPCWSTR QueueNameW, + IN DWORD QLevel, + IN HANDLE PrinterHandle, + IN LPPRINTER_INFO_2 pPrinter, + OUT LPDWORD pcbNeeded + ) +{ + NET_API_STATUS ApiStatus; + DWORD cJobs; + DWORD cbJobs; + DWORD cbNeeded = 0; + DWORD JobLevel; + LPJOB_INFO_2 pJob = NULL; + LPJOB_INFO_2 pJobs = NULL; + + NetpAssert( (QLevel==2) || (QLevel==4) ); + NetpAssert( QueueNameW != NULL ); + NetpAssert( pPrinter != NULL ); + + if (QLevel==2) { + JobLevel = 1; + } else { + JobLevel = 2; + } + + + if (!MyEnumJobs(PrinterHandle, 0, (DWORD) -1, 2, NULL, 0, &cbJobs, &cJobs)) { + + ApiStatus = (NET_API_STATUS) GetLastError(); + if (ApiStatus == ERROR_INSUFFICIENT_BUFFER) { + + pJobs = (LPVOID) GlobalAlloc(GMEM_FIXED, cbJobs); + if (pJobs == NULL) { + + ApiStatus = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + } else { + NetpKdPrint(( PREFIX_DOSPRINT + "ComputeSpaceNeededForJobs: got error " FORMAT_API_STATUS + " from MyEnumJobs(first).\n", ApiStatus )); + goto Cleanup; + } + } + + if (!MyEnumJobs(PrinterHandle, 0, (DWORD) -1, 2, (LPBYTE)pJobs, cbJobs, + &cbJobs, &cJobs)) { + + ApiStatus = (NET_API_STATUS) GetLastError(); + NetpAssert( ApiStatus != ERROR_INSUFFICIENT_BUFFER ); + NetpKdPrint(( PREFIX_DOSPRINT + "ComputeSpaceNeededForJobs: got error " FORMAT_API_STATUS + " from MyEnumJobs(second)\n", ApiStatus )); + goto Cleanup; + } + + if (cJobs == 0) { + cbNeeded = 0; + ApiStatus = NO_ERROR; + goto Cleanup; + } + if (pJobs == NULL) { + NetpKdPrint(( PREFIX_DOSPRINT + "ComputeSpaceNeededForJobs: never allocated array!\n" )); + ApiStatus = NERR_InternalError; + goto Cleanup; + } + + pJob=pJobs; + + while (cJobs--) { + cbNeeded+=GetPrjInfoSizeW(JobLevel, pJob++, QueueNameW, pPrinter); + } + + *pcbNeeded=(WORD)cbNeeded; // final byte count for this queue's jobs. + + ApiStatus = NO_ERROR; + +Cleanup: + if (pJobs != NULL) { + (VOID) GlobalFree(pJobs); + } + + *pcbNeeded = cbNeeded; // final byte count for this queue's jobs. + + return (ApiStatus); + +} // ComputeSpaceNeededForJobs + + +DBGSTATIC NET_API_STATUS +AppendJobsToPrqW( + IN LPCWSTR QueueNameW, + IN DWORD QLevel, + IN HANDLE PrinterHandle, + IN LPPRINTER_INFO_2 pPrinter, + OUT LPBYTE pbBuf, + IN DWORD cbBuf, + IN LPVOID pEnd, + OUT LPVOID * pNewEnd, + OUT LPDWORD pcbNeeded, + OUT LPDWORD pcReturned + ) +{ + DWORD cJobs; + DWORD cbJobs; + DWORD cbNeeded = 0; + DWORD cbPrj; + DWORD JobLevel; + DWORD rc; + LPJOB_INFO_2 pJob = NULL; + LPJOB_INFO_2 pJobs = NULL; + + NetpAssert( (QLevel==2) || (QLevel==4) ); + NetpAssert( QueueNameW != NULL ); + NetpAssert( pPrinter != NULL ); + + if (QLevel==2) { + cbPrj = sizeof(PRJINFOW); + JobLevel = 1; + } else { + cbPrj = sizeof(PRJINFO2W); + JobLevel = 2; + } + + + if (!MyEnumJobs(PrinterHandle, 0, (DWORD) -1, 2, NULL, 0, &cbJobs, pcReturned)) { + + rc = GetLastError(); + if (rc == ERROR_INSUFFICIENT_BUFFER) { + + pJobs = (LPVOID) GlobalAlloc(GMEM_FIXED, cbJobs); + if (pJobs == NULL) { + + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + } else { + NetpKdPrint(( PREFIX_DOSPRINT + "AppendJobsToPrqW: got error " FORMAT_API_STATUS + " from MyEnumJobs(first)\n", rc )); + goto Cleanup; + } + } + + if (!MyEnumJobs(PrinterHandle, 0, (DWORD) -1, 2, (LPBYTE)pJobs, cbJobs, + &cbJobs, pcReturned)) { + + rc = GetLastError(); + NetpAssert( rc != ERROR_INSUFFICIENT_BUFFER ); + NetpKdPrint(( PREFIX_DOSPRINT + "AppendJobsToPrqW: got error " FORMAT_API_STATUS + " from MyEnumJobs(second)\n", rc )); + goto Cleanup; + } + + if (*pcReturned == 0) { + cbNeeded = 0; + rc = NO_ERROR; + goto Cleanup; + } + if (pJobs == NULL) { + NetpKdPrint(( PREFIX_DOSPRINT + "AppendJobsToPrqW: never allocated array!\n" )); + rc = NERR_InternalError; + goto Cleanup; + } + + cJobs = *pcReturned; + pJob=pJobs; + + while (cJobs--) + cbNeeded+=GetPrjInfoSizeW(JobLevel, pJob++, QueueNameW, pPrinter); + + *pcbNeeded=(WORD)cbNeeded; // final byte count for this queue's jobs. + + if (cbNeeded <= cbBuf) { + + cJobs = *pcReturned; + pJob=pJobs; + while (cJobs--) { + pEnd = CopyJobToPrjInfoW(JobLevel, pJob++, QueueNameW, + pPrinter, + pbBuf, + pEnd); + pbBuf += cbPrj; // Note: Wasn't DWORD aligned + } + rc = NO_ERROR; + + } else { + + rc = NERR_BufTooSmall; + } + +Cleanup: + if (pJobs != NULL) { + (VOID) GlobalFree(pJobs); + } + + *pcbNeeded=(WORD)cbNeeded; // final byte count for this queue's jobs. + + if (pNewEnd != NULL) { + *pNewEnd = pEnd; + } + + return (rc); + +} +SPLERR SPLENTRY DosPrintQGetInfoW( + LPWSTR pszServer, + LPWSTR pszQueueName, + WORD uLevel, + PBYTE pbBuf, + WORD cbBuf, + PUSHORT pcbNeeded + ) +{ + DWORD cJobsReturned; + LPWSTR pEnd; + DWORD rc; + HANDLE hPrinter = INVALID_HANDLE_VALUE; + LPPRINTER_INFO_2 pPrinter = NULL; + LPDRIVER_INFO_3A pDriver = NULL; + CHAR szDriverDir[MAX_PATH]; + DWORD cbNeeded, dwDependentFileCount; + DWORD cbNeededForJobs; + + if (pszServer && *pszServer) { + rc = RxPrintQGetInfo(pszServer, pszQueueName, uLevel, pbBuf, + cbBuf, &cbNeeded); + if (cbNeeded > MAX_WORD) { + rc = MY_PROTOCOL_LIMIT_ERROR; + goto Cleanup; + } + *pcbNeeded = (USHORT)cbNeeded; + goto Cleanup; + } + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintQGetInfoW(NULL, " + FORMAT_LPWSTR ", " FORMAT_DWORD ", " FORMAT_LPVOID ", " + FORMAT_DWORD ", " FORMAT_LPVOID ")\n", + (pszQueueName!=NULL) ? pszQueueName : (LPWSTR) L"(missing)", + uLevel, + pbBuf, + cbBuf, + pcbNeeded)); + } + + *pcbNeeded = 0; // in case an error occurs. + if ( !NetpIsPrintQLevelValid( uLevel, FALSE ) ) { + rc = ERROR_INVALID_LEVEL; + goto Cleanup; + } + if ( (pszQueueName==NULL) || ((*pszQueueName)==L'\0') ) { + rc = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + if ( !MyOpenPrinterW( pszQueueName, &hPrinter, NULL) ) { + + rc = GetLastError(); + if ( rc == ERROR_INVALID_PRINTER_NAME ) + rc = NERR_QNotFound; + goto Cleanup; + + } + + // + // Level 52 is meant for point and print from a Windows 95 clients + // can't use with other clients since no environment info is passed + // + if ( uLevel == 52 ) { + + cbNeeded = sizeof(szDriverDir)-2; + szDriverDir[0] = szDriverDir[1] = '\\'; + if ( !GetComputerNameA(szDriverDir+2, &cbNeeded) ) { + + rc = GetLastError(); + goto Cleanup; + } + + if ( strlen(szDriverDir) + strlen(WIN95_DRIVER_SHARE) + 1 + > sizeof(szDriverDir) ) { + + rc = ERROR_NOT_ENOUGH_MEMORY; + NetpAssert( rc != NO_ERROR ); // Always break + goto Cleanup; + } + + strcat(szDriverDir, WIN95_DRIVER_SHARE); + + (VOID)MyGetPrinterDriver(hPrinter, WIN95_ENVIRONMENT, 3, + NULL, 0, &cbNeeded); + rc = GetLastError(); + if ( rc != ERROR_INSUFFICIENT_BUFFER ) + goto Cleanup; + + pDriver = (LPVOID) GlobalAlloc(GMEM_FIXED, cbNeeded); + if ( !pDriver ) { + + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + if ( !MyGetPrinterDriver(hPrinter, WIN95_ENVIRONMENT, 3, + (LPVOID)pDriver, cbNeeded, &cbNeeded) ) { + + rc = GetLastError(); + goto Cleanup; + } + + cbNeeded=GetDrvInfoSizeW(uLevel, pDriver, + szDriverDir, &dwDependentFileCount); + if ( dwDependentFileCount > MAX_DEPENDENT_FILES ) { + + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } else { + + if (!MyGetPrinter(hPrinter, 2, NULL, 0, &cbNeeded)) { + + rc = GetLastError(); + if (rc == ERROR_INSUFFICIENT_BUFFER) { + + pPrinter = (LPVOID) GlobalAlloc(GMEM_FIXED, cbNeeded); + if (pPrinter == NULL) { + + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } else { + goto Cleanup; + } + + } + + if (!MyGetPrinter(hPrinter, 2, (LPBYTE)pPrinter, cbNeeded, &cbNeeded)) { + + rc = GetLastError(); + goto Cleanup; + } + + // How much for just the queue structure and its strings? + cbNeeded=GetPrqInfoSizeW(uLevel, pszQueueName, pPrinter); + } + + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint(( PREFIX_DOSPRINT + "DosPrintQGetInfoW: got " FORMAT_DWORD " for Q size.\n", + (DWORD) cbNeeded )); + } + if (cbNeeded > MAX_WORD) { + rc = MY_PROTOCOL_LIMIT_ERROR; + goto Cleanup; + } + *pcbNeeded = (WORD)cbNeeded; // Tell caller the size (so far). + + // + // Build the queue structure itself. + // + if (cbNeeded <= (DWORD) cbBuf) { + + if ( uLevel == 52 ) { + + ZeroMemory(pbBuf, cbNeeded); + pEnd = CopyDriverToPrqInfoW(pDriver, dwDependentFileCount, + szDriverDir, uLevel, pbBuf, + (LPWSTR) (pbBuf+cbBuf) ); + } else { + + pEnd = CopyPrinterToPrqInfoW(pPrinter, uLevel, pbBuf, pszQueueName, + (LPWSTR) (pbBuf+cbBuf) ); + } + + } else { + + // + // Too small. Well, need to find total size before we can tell caller. + // + if ( (uLevel==2) || (uLevel==4) ) { + rc = ComputeSpaceNeededForJobs( + pszQueueName, + uLevel, // Q info level + hPrinter, + pPrinter, + & cbNeededForJobs ); + if (rc != NO_ERROR) { + goto Cleanup; + } + cbNeeded += cbNeededForJobs; + } + if (cbNeeded > MAX_WORD) { + rc = MY_PROTOCOL_LIMIT_ERROR; + goto Cleanup; + } + rc = NERR_BufTooSmall; + goto Cleanup; + } + + // + // Append jobs if necessary. + // + + if ( (uLevel==2) || (uLevel==4) ) { + DWORD cbPrq = PrqInfoFixedSizeW( uLevel ); + + rc = AppendJobsToPrqW( + pszQueueName, + uLevel, // Q info level + hPrinter, + pPrinter, + pbBuf + cbPrq, // put first job here + cbBuf - cbNeeded, // bytes avail for jobs + pEnd, // str area + NULL, // don't need new pEnd + & cbNeededForJobs, + & cJobsReturned ); + + *pcbNeeded = (USHORT) (cbNeeded + cbNeededForJobs); + + // + // Update job count in queue structure, as it may be out of date. + // + + NetpSetJobCountForQueue( + uLevel, // queue info level + pbBuf, // queue structure to update + TRUE, // yes, UNICODE strings + cJobsReturned ); // actual job count + + if (rc != NO_ERROR) { + goto Cleanup; + } + + } + + rc = NO_ERROR; + +Cleanup: + + if (hPrinter != INVALID_HANDLE_VALUE) { + (VOID) MyClosePrinter( hPrinter ); + } + + if (pPrinter) { + (VOID) GlobalFree( pPrinter ); + } + + if (pDriver) { + + (VOID) GlobalFree( pDriver ); + } + + return rc; +} + + +SPLERR SPLENTRY DosPrintJobGetInfoW( + LPWSTR pszServer, + WORD uJobId, + WORD uLevel, + PBYTE pbBuf, + WORD cbBuf, + PUSHORT pcbNeeded +) +{ + DWORD cb; + DWORD cbPrinter; + HANDLE hPrinter = INVALID_HANDLE_VALUE; + LPSTR QueueNameA = NULL; + LPWSTR QueueNameW = NULL; + LPJOB_INFO_2 pJob = NULL; + LPWSTR pEnd; + LPPRINTER_INFO_2 pPrinter = NULL; + DWORD rc; + DWORD cbNeeded; + + if (pszServer && *pszServer) { + rc = RxPrintJobGetInfo(pszServer, uJobId, uLevel, pbBuf, + cbBuf, &cbNeeded); + *pcbNeeded = (USHORT)cbNeeded; + return rc; + } + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintJobGetInfoW(NULL, " FORMAT_DWORD + ", " FORMAT_DWORD ", " FORMAT_LPVOID ", " FORMAT_DWORD + ", " FORMAT_LPVOID ")\n", + uJobId, uLevel, pbBuf, cbBuf, pcbNeeded)); + } + + *pcbNeeded = 0; // in case an error occurs. + + if ( !NetpIsPrintJobLevelValid( uLevel, FALSE ) ) { + rc = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + hPrinter = FindLocalJob(uJobId); + if (hPrinter == INVALID_HANDLE_VALUE) { + rc = GetLastError(); + goto Cleanup; + } + + if (!MyGetPrinter(hPrinter, 2, NULL, 0, &cbPrinter)) { + + rc = GetLastError(); + if (rc == ERROR_INSUFFICIENT_BUFFER) { + + pPrinter = (LPVOID) GlobalAlloc(GMEM_FIXED, cbPrinter); + if (pPrinter == NULL) { + + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } else { + goto Cleanup; + } + + } + + if (!MyGetPrinter(hPrinter, 2, (LPBYTE)pPrinter, cbPrinter, &cbPrinter)) { + + rc = GetLastError(); + goto Cleanup; + } + + if (!MyGetJob(hPrinter, uJobId, 2, NULL, 0, &cb)) { + + rc=GetLastError(); + + NetpAssert( rc != NO_ERROR ); + if (rc == ERROR_INSUFFICIENT_BUFFER) { + + pJob = (LPVOID) GlobalAlloc(GMEM_FIXED, cb); + if (pJob == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + if ( !MyGetJob(hPrinter, uJobId, 2, (LPBYTE)pJob, cb, &cb) ) { + rc=GetLastError(); + NetpAssert( rc != NO_ERROR ); + goto Cleanup; + } + + } else { + if (rc == ERROR_INVALID_PARAMETER) { + rc = NERR_JobNotFound; + } + goto Cleanup; // Job deleted? Not enough mem? + } + + } + if (pJob == NULL) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintJobGetInfoW: " + "*** STILL INVALID RESULT FROM MyGetJob, pJob IS NULL!\n" )); + rc = NERR_InternalError; + goto Cleanup; + } + + NetpAssert( pJob != NULL ); + NetpAssert( pPrinter != NULL ); + NetpAssert( pPrinter->pPrinterName != NULL ); + QueueNameA = FindQueueNameInPrinterNameA( + (pPrinter->pPrinterName) ); + NetpAssert( QueueNameA != NULL ); + QueueNameW = NetpAllocWStrFromStr( QueueNameA ); + if (QueueNameW == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + NetpAssert( QueueNameW != NULL ); + + cb=GetPrjInfoSizeW(uLevel, pJob, QueueNameW, pPrinter); + + *pcbNeeded=(WORD)cb; + + if (cb > (DWORD) cbBuf) { + rc = NERR_BufTooSmall; + goto Cleanup; + } + + pEnd = (LPVOID) (pbBuf+cbBuf); + + (VOID) CopyJobToPrjInfoW(uLevel, pJob, QueueNameW, pPrinter, pbBuf, pEnd); + + rc = NO_ERROR; + +Cleanup: + + if (hPrinter != INVALID_HANDLE_VALUE) { + (VOID) MyClosePrinter( hPrinter ); + } + if (pJob != NULL) { + (VOID) GlobalFree( pJob ); + } + if (pPrinter != NULL) { + (VOID) GlobalFree( pPrinter ); + } + if (QueueNameW != NULL) { + (VOID) NetApiBufferFree( QueueNameW ); + } + + return (rc); + +} + +SPLERR SPLENTRY DosPrintJobDelW( + LPWSTR pszServer, + WORD uJobId +) +{ + + if (pszServer && *pszServer) + return RxPrintJobDel(pszServer, uJobId); + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint(( PREFIX_DOSPRINT + "DosPrintJobDelW(NULL, " FORMAT_DWORD ")\n", uJobId )); + } + + return (CommandALocalJob( NULL, uJobId, 0, NULL, JOB_CONTROL_CANCEL ) ); +} + +SPLERR SPLENTRY DosPrintJobContinueW( + LPWSTR pszServer, + WORD uJobId +) +{ + + if (pszServer && *pszServer) + return RxPrintJobContinue(pszServer, uJobId); + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintJobContinueW(NULL, " + FORMAT_DWORD ")\n", uJobId)); + } + + return (CommandALocalJob( NULL, uJobId, 0, NULL, JOB_CONTROL_RESUME ) ); +} + +SPLERR SPLENTRY DosPrintJobPauseW( + LPWSTR pszServer, + WORD uJobId +) +{ + + if (pszServer && *pszServer) + return RxPrintJobPause(pszServer, uJobId); + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT + "DosPrintJobPauseW(NULL, " FORMAT_DWORD ")\n", + uJobId)); + } + + return (CommandALocalJob( NULL, uJobId, 0, NULL, JOB_CONTROL_PAUSE ) ); +} + +SPLERR SPLENTRY DosPrintJobEnumW( + LPWSTR pszServer, + LPWSTR pszQueueName, + WORD uLevel, + PBYTE pbBuf, + WORD cbBuf, + PWORD pcReturned, + PWORD pcTotal +) +{ + DWORD cbPrinter; + LPJOB_INFO_2 pJob = NULL; + LPJOB_INFO_2 pJobs; + DWORD cb, cbJobs, cReturned, cJobs; + HANDLE hPrinter = INVALID_HANDLE_VALUE; + LPWSTR pEnd; + LPPRINTER_INFO_2 pPrinter = NULL; + DWORD rc; + DWORD cTotal; + + if (pszServer && *pszServer) { + rc = RxPrintJobEnum(pszServer, pszQueueName, uLevel, pbBuf, + cbBuf, &cReturned, &cTotal); + *pcReturned = (WORD)cReturned; + *pcTotal = (WORD)cTotal; + goto Cleanup; + } + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintJobEnumW(NULL, " FORMAT_LPWSTR + ", " FORMAT_DWORD ", " FORMAT_LPVOID ", " FORMAT_DWORD + ", " FORMAT_LPVOID ", " FORMAT_LPVOID ")\n", + pszQueueName, + uLevel, + pbBuf, + cbBuf, + pcReturned, + pcTotal)); + } + + *pcReturned=0; + *pcTotal = 0; + + if ( !NetpIsPrintJobLevelValid( uLevel, FALSE ) ) { + rc = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + if (!MyOpenPrinterW( pszQueueName, &hPrinter, NULL)) { + rc = GetLastError(); + goto Cleanup; + } + NetpAssert( hPrinter != INVALID_HANDLE_VALUE ); + + if (!MyGetPrinter(hPrinter, 2, NULL, 0, &cbPrinter)) { + + rc = GetLastError(); + if (rc == ERROR_INSUFFICIENT_BUFFER) { + + pPrinter = (LPVOID) GlobalAlloc(GMEM_FIXED, cbPrinter); + if (pPrinter == NULL) { + + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } else { + goto Cleanup; + } + + } + + if (!MyGetPrinter(hPrinter, 2, (LPBYTE)pPrinter, cbPrinter, + &cbPrinter)) { + + rc = GetLastError(); + NetpAssert( rc != ERROR_INSUFFICIENT_BUFFER ); + goto Cleanup; + } + + if (!MyEnumJobs(hPrinter, 0, (DWORD) -1, 2, NULL, 0, &cbJobs, &cReturned)) { + + rc = GetLastError(); + NetpAssert( rc != NO_ERROR ); + if (rc == ERROR_INSUFFICIENT_BUFFER) { + + if (pJob = (LPVOID) GlobalAlloc(GMEM_FIXED, cbJobs)) { + + if (!MyEnumJobs(hPrinter, 0, (DWORD) -1, 2, (LPBYTE)pJob, cbJobs, + &cbJobs, &cReturned)) { + + rc = GetLastError(); + NetpAssert( rc != NO_ERROR ); + NetpAssert( rc != ERROR_INSUFFICIENT_BUFFER ); // BUGBUG + NetpKdPrint(( PREFIX_DOSPRINT + "DosPrintJobEnumW: got error " FORMAT_API_STATUS + " from MyEnumJobs(first)\n", rc )); + goto Cleanup; + } + } else { + + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + } else { + NetpKdPrint(( PREFIX_DOSPRINT + "DosPrintJobEnumW: got error " FORMAT_API_STATUS + " from MyEnumJobs(first)\n", rc )); + goto Cleanup; + } + } + + if (cReturned == 0) { + *pcReturned = 0; + *pcTotal = 0; + rc = NO_ERROR; + goto Cleanup; + } + if (pJob == NULL) { + NetpKdPrint(( PREFIX_DOSPRINT + "DosPrintJobEnumW: never allocated array!\n" )); + rc = NERR_InternalError; + goto Cleanup; + } + + + *pcTotal = (WORD)cReturned; + + cb=0; + cJobs=cReturned; + pJobs=pJob; + while (cJobs--) + cb+=GetPrjInfoSizeW(uLevel, pJobs++, pszQueueName, pPrinter); + + if (cb <= (DWORD) cbBuf) { + + DWORD cbFixedPortion = PrjInfoFixedSizeW( uLevel ); + NetpAssert( cbFixedPortion != 0 ); // level already checked! + + pEnd = (LPWSTR)(pbBuf+cbBuf); + + cJobs=cReturned; + pJobs=pJob; + + while (cJobs--) { + + pEnd = CopyJobToPrjInfoW(uLevel, pJobs++, + pszQueueName, + pPrinter, + pbBuf, pEnd); + pbBuf += cbFixedPortion; + } + + *pcReturned = (WORD)cReturned; + rc = NO_ERROR; + + } else { + + rc = NERR_BufTooSmall; + goto Cleanup; + } + +Cleanup: + + if (hPrinter != INVALID_HANDLE_VALUE) { + (VOID) MyClosePrinter( hPrinter ); + } + if (pJob != NULL) { + (VOID) GlobalFree( pJob ); + } + if (pPrinter) { + (VOID) GlobalFree( pPrinter ); + } + + return rc; +} + +SPLERR SPLENTRY +DosPrintDestEnumW( + IN LPWSTR pszServer OPTIONAL, + IN WORD uLevel, + OUT PBYTE pbBuf, + IN WORD cbBuf, + OUT PUSHORT pcReturned, + OUT PUSHORT pcTotal + ) +{ + DWORD cReturned, cTotal, rc; + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint(( PREFIX_DOSPRINT "DosPrintDestEnumW(" FORMAT_LPWSTR ", " + FORMAT_DWORD + ", " FORMAT_LPVOID ", " FORMAT_DWORD ", " FORMAT_LPVOID + ", " FORMAT_LPVOID ")\n", + (pszServer!=NULL) ? pszServer : (LPWSTR) L"(local)", + uLevel, pbBuf, cbBuf, pcReturned, pcTotal)); + } + + if (pszServer && *pszServer) { + rc = RxPrintDestEnum(pszServer, uLevel, pbBuf, cbBuf, + &cReturned, &cTotal); + *pcReturned = (USHORT)cReturned; + *pcTotal = (USHORT)cTotal; + return rc; + } + + // Stub for local dest enum - no entries, dest not found. + *pcReturned = 0; + *pcTotal = 0; + return ERROR_NOT_SUPPORTED; +} + +SPLERR SPLENTRY DosPrintDestControlW( + LPWSTR pszServer, + LPWSTR pszDevName, + WORD uControl +) +{ + if (pszServer && *pszServer) + return RxPrintDestControl(pszServer, pszDevName, uControl); + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintDestEnumW(NULL, " + FORMAT_LPWSTR ", " FORMAT_DWORD ")\n", pszDevName, uControl)); + } + + return ERROR_NOT_SUPPORTED; +} + + +SPLERR SPLENTRY DosPrintDestGetInfoW( + LPWSTR pszServer, + LPWSTR pszName, + WORD uLevel, + PBYTE pbBuf, + WORD cbBuf, + PUSHORT pcbNeeded +) +{ + DWORD cbNeeded, rc; + + if (pszServer && *pszServer) { + rc = RxPrintDestGetInfo(pszServer, pszName, uLevel, pbBuf, + cbBuf, &cbNeeded); + *pcbNeeded = (USHORT)cbNeeded; + return rc; + } + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintDestGetInfoW(NULL, " + FORMAT_LPWSTR ", " FORMAT_DWORD ", " FORMAT_LPVOID + ", " FORMAT_DWORD ", " FORMAT_LPVOID ")\n", + pszName, uLevel, pbBuf, cbBuf, pcbNeeded)); + } + + return ERROR_NOT_SUPPORTED; +} + +SPLERR SPLENTRY DosPrintDestAddW( + LPWSTR pszServer, + WORD uLevel, + PBYTE pbBuf, + WORD cbBuf +) +{ + if (pszServer && *pszServer) + return RxPrintDestAdd(pszServer, uLevel, pbBuf, cbBuf); + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintDestAddW(NULL, " + FORMAT_DWORD ", " FORMAT_LPVOID ", " FORMAT_DWORD ")\n", + uLevel, pbBuf, cbBuf)); + } + + return ERROR_NOT_SUPPORTED; +} + +SPLERR SPLENTRY DosPrintDestSetInfoW( + LPWSTR pszServer, + LPWSTR pszName, + WORD uLevel, + PBYTE pbBuf, + WORD cbBuf, + WORD uParmNum +) +{ + if (pszServer && *pszServer) + return RxPrintDestSetInfo(pszServer, pszName, uLevel, pbBuf, + cbBuf, uParmNum); + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintDestSetInfoW(NULL, " FORMAT_LPWSTR + ", " FORMAT_DWORD ", " FORMAT_LPVOID ", " FORMAT_DWORD + ", " FORMAT_DWORD ")\n", + pszName, uLevel, pbBuf, cbBuf, uParmNum)); + } + + return ERROR_NOT_SUPPORTED; +} + +SPLERR SPLENTRY DosPrintDestDelW( + LPWSTR pszServer, + LPWSTR pszPrinterName +) +{ + if (pszServer && *pszServer) + return RxPrintDestDel(pszServer, pszPrinterName); + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintDestDelW(NULL, " + FORMAT_LPWSTR ")\n", + pszPrinterName)); + } + + return ERROR_NOT_SUPPORTED; +} + +SPLERR SPLENTRY DosPrintQEnumW( + LPWSTR pszServer, + WORD uLevel, + PBYTE pbBuf, + WORD cbBuf, + PUSHORT pcReturned, + PUSHORT pcTotal +) +{ + DWORD cJobsReturned; + DWORD Total, cbNeeded, rc; + HANDLE hPrinter = INVALID_HANDLE_VALUE; + DWORD i; + DWORD JobFixedEntrySize = 0; + DWORD JobLevel; + LPSHARE_INFO_1 pShareInfo = NULL; + DWORD cbPrinter; + LPPRINTER_INFO_2 pPrinter = NULL; + BOOL BufferTooSmall=FALSE; + DWORD cReturned, cTotal; +#if DBG + LPVOID OutputBufferStart = pbBuf; +#endif + LPVOID pEnd; + DWORD SharesRead; + + if ( !NetpIsPrintQLevelValid( uLevel, FALSE ) ) { + rc = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + if (pszServer && *pszServer) { + rc = RxPrintQEnum(pszServer, uLevel, pbBuf, cbBuf, &cReturned, &cTotal); + *pcReturned = (USHORT)cReturned; + *pcTotal = (USHORT)cTotal; + goto Cleanup; + } + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintQEnumW(NULL, " + FORMAT_DWORD ", " FORMAT_LPVOID ", " FORMAT_DWORD ", " + FORMAT_LPVOID ", " FORMAT_LPVOID ")\n", + uLevel, pbBuf, cbBuf, pcReturned, pcTotal)); + } + + *pcReturned = 0; + *pcTotal = 0; + + rc=NetShareEnum( + NULL, + 1, + (LPBYTE *)(LPVOID)&pShareInfo, + MAX_PREFERRED_LENGTH, + &SharesRead, + &Total, + NULL); + if (rc != NO_ERROR) { + + NetpKdPrint((PREFIX_DOSPRINT "DosPrintQEnumW: NetShareEnum returned " + FORMAT_API_STATUS "\n", rc)); + goto Cleanup; + } + + pEnd = (pbBuf + cbBuf); + + if (uLevel==2) { + JobLevel = 1; + JobFixedEntrySize = PrjInfoFixedSizeW( JobLevel ); + } else if (uLevel == 4) { + JobLevel = 2; + JobFixedEntrySize = PrjInfoFixedSizeW( JobLevel ); + } + + for (i=0; i<SharesRead; i++) { + + if (pShareInfo[i].shi1_type != STYPE_PRINTQ) { + continue; + } + + NetpAssert( pShareInfo[i].shi1_netname != NULL ); + NetpAssert( (*pShareInfo[i].shi1_netname) != L'\0' ); + if (STRLEN( pShareInfo[i].shi1_netname ) > LM20_QNLEN) { + IF_DEBUG( DOSPRTW ) { + NetpKdPrint(( PREFIX_DOSPRINT + "DosPrintQEnumW: ignoring long share name of '" + FORMAT_LPTSTR "'.\n", + pShareInfo[i].shi1_netname )); + } + continue; + } + + if ( !MyOpenPrinterW(pShareInfo[i].shi1_netname, &hPrinter, NULL)) { + rc = (NET_API_STATUS) GetLastError(); + NetpKdPrint(( PREFIX_DOSPRINT + "DosPrintQEnumW: MyOpenPrinter failed, status " + FORMAT_API_STATUS ".\n", rc )); + NetpAssert( rc != NO_ERROR ); + goto Cleanup; + } + NetpAssert( hPrinter != INVALID_HANDLE_VALUE ); + + if (!MyGetPrinter(hPrinter, 2, NULL, 0, &cbPrinter)) { + + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + rc = (NET_API_STATUS) GetLastError(); + NetpKdPrint(( PREFIX_DOSPRINT + "DosPrintQEnumW: MyGetPrinter(first) failed, status " + FORMAT_API_STATUS ".\n", rc )); + NetpAssert( rc != NO_ERROR ); + goto Cleanup; + } + } + NetpAssert( cbPrinter != 0 ); + + pPrinter = (LPVOID) GlobalAlloc(GMEM_FIXED, cbPrinter); + if (pPrinter == NULL) { + rc = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + if ( !MyGetPrinter(hPrinter, 2, (LPBYTE)pPrinter, + cbPrinter, &cbPrinter)) { + rc = (NET_API_STATUS) GetLastError(); + NetpKdPrint(( PREFIX_DOSPRINT + "DosPrintQEnumW: MyGetPrinter(second) failed, status " + FORMAT_API_STATUS ".\n", rc )); + NetpAssert( rc != NO_ERROR ); + goto Cleanup; + } + + cbNeeded=GetPrqInfoSizeW(uLevel, + pShareInfo[i].shi1_netname, // Q nam + pPrinter); + NetpAssert( cbNeeded > 0 ); + NetpAssert( cbNeeded <= (DWORD) MAX_WORD ); + + if ( (!BufferTooSmall) && ((DWORD)cbBuf >= cbNeeded) ) { + + LPVOID pbQueue = pbBuf; + // + // Handle queue structure itself. + // + pEnd = CopyPrinterToPrqInfoW(pPrinter, + uLevel, + pbBuf, + pShareInfo[i].shi1_netname, + pEnd); + + pbBuf += PrqInfoFixedSizeW( uLevel ); + cbBuf -= (WORD) cbNeeded; + + // + // Append job structures if needed. + // + if ( (uLevel==2) || (uLevel==4) ) { // info level includes jobs + + NetpAssert( pbBuf < (LPBYTE) pEnd ); + rc = AppendJobsToPrqW( + pShareInfo[i].shi1_netname, + uLevel, // Q info level + hPrinter, + pPrinter, + pbBuf, // first job here + cbBuf, // bytes avail + pEnd, // str area + & pEnd, // set new end ptr + & cbNeeded, + & cJobsReturned ); + if (rc == NERR_BufTooSmall) { + BufferTooSmall = TRUE; // continue, as we need pcTotal... + } else if (rc != NO_ERROR) { + goto Cleanup; + } else { // Must be NO_ERROR. + NetpAssert( cbNeeded <= (DWORD) MAX_WORD ); + NetpAssert( pbBuf < (LPBYTE) pEnd ); + NetpAssert( JobFixedEntrySize !=0 ); + + pbBuf += (JobFixedEntrySize * cJobsReturned); + cbBuf -= (WORD) cbNeeded; + (*pcReturned)++; + + // Correct possible out of date + // job count in queue structure. + NetpSetJobCountForQueue( + uLevel, + pbQueue, + TRUE, // yes, UNICODE strs + cJobsReturned ); + } + + } else { // info level does not include jobs + + (*pcReturned)++; + } + + } else { // not enough mem for Q struct + + BufferTooSmall = TRUE; + // Continue, as we want to compute pcTotal for subsequent queues. + } + + (*pcTotal)++; + + NetpAssert( pPrinter != NULL ); + (VOID) GlobalFree(pPrinter); + pPrinter = NULL; + + NetpAssert( hPrinter != INVALID_HANDLE_VALUE ); + (VOID) MyClosePrinter(hPrinter); + hPrinter = INVALID_HANDLE_VALUE; + + } // for each share + +Cleanup: + +#if DBG + IF_DEBUG( DOSPRTW ) { + if (rc == NO_ERROR) { + NetpKdPrint((PREFIX_DOSPRINT + "DosPrintQEnumW: returning array:\n" )); + NetpDbgDisplayPrintQArray( uLevel, + OutputBufferStart, + *pcReturned, TRUE ); + } + } +#endif + + if (hPrinter != INVALID_HANDLE_VALUE) { + (VOID) MyClosePrinter( hPrinter ); + } + if (pPrinter != NULL) { + (VOID) GlobalFree( pPrinter ); + } + if (pShareInfo != NULL) { + (VOID) NetApiBufferFree(pShareInfo); + } + + if (BufferTooSmall) { + rc = NERR_BufTooSmall; + } + + return (rc); +} + +SPLERR SPLENTRY DosPrintQSetInfoW( + LPWSTR pszServer, + LPWSTR pszQueueName, + WORD uLevel, + PBYTE pbBuf, + WORD cbBuf, + WORD uParmNum +) +{ + if (pszServer && *pszServer) + return RxPrintQSetInfo(pszServer, pszQueueName, uLevel, pbBuf, + cbBuf, uParmNum); + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintQSetInfoW(NULL, " FORMAT_LPWSTR + ", " FORMAT_DWORD ", " FORMAT_LPVOID ", " FORMAT_DWORD ", " + FORMAT_DWORD ")\n", + pszQueueName, uLevel, pbBuf, cbBuf, uParmNum)); + } + + return ERROR_NOT_SUPPORTED; +} + +SPLERR SPLENTRY DosPrintQPauseW( + LPWSTR pszServer, + LPWSTR pszQueueName +) +{ + if (pszServer && *pszServer) + return RxPrintQPause(pszServer, pszQueueName); + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintQPauseW(NULL, " + FORMAT_LPWSTR ")\n", + pszQueueName)); + } + + return (CommandALocalPrinterW( pszQueueName, PRINTER_CONTROL_PAUSE ) ); +} + +SPLERR SPLENTRY DosPrintQContinueW( + LPWSTR pszServer, + LPWSTR pszQueueName +) +{ + if (pszServer && *pszServer) + return RxPrintQContinue(pszServer, pszQueueName); + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintQContinueW(NULL, " + FORMAT_LPWSTR ")\n", pszQueueName)); + } + + return (CommandALocalPrinterW( pszQueueName, PRINTER_CONTROL_RESUME ) ); +} + +SPLERR SPLENTRY DosPrintQPurgeW( + LPWSTR pszServer, + LPWSTR pszQueueName +) +{ + if (pszServer && *pszServer) + return RxPrintQPurge(pszServer, pszQueueName); + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintQPurgeW(NULL, " + FORMAT_LPWSTR ")\n", + pszQueueName)); + } + + return (CommandALocalPrinterW( pszQueueName, PRINTER_CONTROL_PURGE ) ); +} + +SPLERR SPLENTRY DosPrintQAddW( + LPWSTR pszServer, + WORD uLevel, + PBYTE pbBuf, + WORD cbBuf +) +{ + if (pszServer && *pszServer) + return RxPrintQAdd(pszServer, uLevel, pbBuf, cbBuf); + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintQAddW(NULL, " FORMAT_DWORD ", " + FORMAT_LPVOID ", " FORMAT_DWORD ")\n", + uLevel, pbBuf, cbBuf)); + } + + return ERROR_NOT_SUPPORTED; +} + +SPLERR SPLENTRY DosPrintQDelW( + LPWSTR pszServer, + LPWSTR pszQueueName +) +{ + if (pszServer && *pszServer) + return RxPrintQDel(pszServer, pszQueueName); + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintQDelW(NULL, " FORMAT_LPWSTR ")\n", + pszQueueName)); + } + + return ERROR_NOT_SUPPORTED; +} + +SPLERR SPLENTRY DosPrintJobSetInfoW( + LPWSTR pszServer, + WORD uJobId, + WORD uLevel, + PBYTE pbBuf, + WORD cbBuf, + WORD uParmNum +) +{ + if (pszServer && *pszServer) + return RxPrintJobSetInfo(pszServer, uJobId, uLevel, pbBuf, + cbBuf, uParmNum); + + IF_DEBUG( DOSPRTW ) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintJobSetInfoW(NULL, " FORMAT_DWORD + ", " FORMAT_DWORD ", " FORMAT_LPVOID ", " FORMAT_DWORD + ", " FORMAT_DWORD ")\n", + uJobId, uLevel, pbBuf, cbBuf, uParmNum)); + } + + // + // Hack for Chicago: support Level 1, ParmNum 0xb so that jobs + // are set with the comment field. + // + if (uLevel == 1 && uParmNum == PRJ_COMMENT_PARMNUM) { + + HANDLE hPrinter = INVALID_HANDLE_VALUE; + CHAR szDocument[MAX_PATH]; + PJOB_INFO_1 pJob = NULL; + DWORD cbJob; + SPLERR rc; + + // + // Allocate maximum size of JOB_INFO_1A. Later, this + // should be moved into the spooler's header file. + // + cbJob = sizeof(JOB_INFO_1) + 6 * MAX_PATH; + + pJob = (PJOB_INFO_1) GlobalAlloc(GMEM_FIXED, cbJob); + + if (pJob == NULL) { + rc = GetLastError(); + goto Cleanup; + } + + // + // The 3.51 spooler has been changed to accept Get/SetJobs on the + // local server handle. We will still do security checks against + // the Job's security descriptor. This also avoids the costly + // FindLocalJob() call. + // + if (!MyOpenPrinter( NULL, &hPrinter, NULL)) { + rc = GetLastError(); + NetpKdPrint((PREFIX_DOSPRINT "DosPrintJobSetInfoW: " + "MyOpenPrinter( NULL, &hPrinter, NULL ) failed" + FORMAT_API_STATUS "\n", rc )); + + hPrinter = INVALID_HANDLE_VALUE; + goto Cleanup; + } + NetpAssert( hPrinter != INVALID_HANDLE_VALUE ); + + // + // We need to get a copy of the old job info. Later, the + // spooler should be changed to allow "don't change" values. + // + if (!MyGetJob( hPrinter, uJobId, 1, (PBYTE)pJob, cbJob, &cbJob )) { + rc = GetLastError(); + NetpKdPrint((PREFIX_DOSPRINT "DosPrintJobSetInfoW: " + "MyGetJob failed" FORMAT_API_STATUS "\n", rc )); + + goto Cleanup; + } + + // + // Put in new document name. + // + NetpNCopyWStrToStr( szDocument, + (LPWSTR)pbBuf, + sizeof( szDocument ) / sizeof( szDocument[0] )); + + pJob->pDocument = szDocument; + + // + // Don't try and change the position, since this requires + // admin access (and isn't necessary). + // + pJob->Position = JOB_POSITION_UNSPECIFIED; + + rc = CommandALocalJob( hPrinter, uJobId, 1, (PBYTE)pJob, 0 ); + + if (rc) { + NetpKdPrint((PREFIX_DOSPRINT "DosPrintJobSetInfoW: " + "CommandALocalJob failed " FORMAT_API_STATUS "\n", rc )); + } + +Cleanup: + if (pJob) { + GlobalFree( pJob ); + } + if (hPrinter != INVALID_HANDLE_VALUE) { + MyClosePrinter( hPrinter ); + } + return rc; + } + + return ERROR_NOT_SUPPORTED; +} + diff --git a/private/net/dosprint/dosspool.c b/private/net/dosprint/dosspool.c new file mode 100644 index 000000000..a161a4684 --- /dev/null +++ b/private/net/dosprint/dosspool.c @@ -0,0 +1,614 @@ +/*++ + +Copyright (c) 1993 Microsoft Corporation + +Module Name: + + dosspool.c + +Abstract: + + Contains the entry points for the functions that live in a + separate DLL. The entry points are made available here, but + will not load the WINSPOOL.DRV until it is needed. + + Contains: + +Author: + + Congpa You (CongpaY) 22-Jan-1993 + +Environment: + +Notes: + +Revision History: + +--*/ +#include <windows.h> +#include <netdebug.h> // NetpAssert() +#include "dosspool.h" + +/* + * global defines. + */ + +#define WINSPOOL_DLL_NAME TEXT("WINSPOOL.DRV") + +/* + * global data. + * + * here we store handles to the MPRUI dll and pointers to the function + * all of below is protect in multi threaded case with MprLoadLibSemaphore. + */ + +HINSTANCE vhWinspoolDll = NULL ; + +PF_ClosePrinter pfClosePrinter = NULL ; +PF_EnumJobsA pfEnumJobsA = NULL ; +PF_EnumPrintersA pfEnumPrintersA = NULL ; +PF_GetJobA pfGetJobA = NULL ; +PF_GetPrinterA pfGetPrinterA = NULL ; +PF_OpenPrinterA pfOpenPrinterA = NULL ; +PF_OpenPrinterW pfOpenPrinterW = NULL ; +PF_SetJobA pfSetJobA = NULL ; +PF_SetPrinterW pfSetPrinterW = NULL ; +PF_GetPrinterDriverA pfGetPrinterDriverA = NULL; + +/* + * global functions + */ +BOOL MakeSureDllIsLoaded(void) ; + +/******************************************************************* + + NAME: GetFileNameA + + SYNOPSIS: Gets the filename part from a fully qualified path + + + HISTORY: + MuhuntS 06-Feb-1996 Created + +********************************************************************/ +LPSTR +GetFileNameA( + LPSTR pPathName + ) +{ + LPSTR pSlash = pPathName, pTemp; + + if ( pSlash ) { + + while ( pTemp = strchr(pSlash, '\\') ) + pSlash = pTemp+1; + + if ( !*pSlash ) + pSlash = NULL; + + NetpAssert(pSlash != NULL); + } + + return pSlash; +} + + +/******************************************************************* + + NAME: MyClosePrinter + + SYNOPSIS: calls thru to the superset function + + HISTORY: + CongpaY 22-Jan-1993 Created + +********************************************************************/ + +BOOL MyClosePrinter (HANDLE hPrinter) +{ + PF_ClosePrinter pfTemp; + + // if function has not been used before, get its address. + if (pfClosePrinter == NULL) + { + // make sure DLL Is loaded + if (!MakeSureDllIsLoaded()) + { + return(FALSE) ; + } + + pfTemp = (PF_ClosePrinter) + GetProcAddress(vhWinspoolDll, + "ClosePrinter") ; + + if (pfTemp == NULL) + { + return(FALSE); + } + else + { + pfClosePrinter = pfTemp; + } + + } + + return ((*pfClosePrinter)(hPrinter)); +} + +/******************************************************************* + + NAME: MyEnumJobs + + SYNOPSIS: calls thru to the superset function + + NOTES: This is defined ANSI version. If change to UNICODE version + in the future, you should change the code to make it call + UNICODE version!!! + + HISTORY: + CongpaY 22-Jan-1993 Created + +********************************************************************/ + +BOOL MyEnumJobs (HANDLE hPrinter, + DWORD FirstJob, + DWORD NoJobs, + DWORD Level, + LPBYTE pJob, + DWORD cbBuf, + LPDWORD pcbNeeded, + LPDWORD pcReturned) +{ + PF_EnumJobsA pfTemp; + + // if function has not been used before, get its address. + if (pfEnumJobsA == NULL) + { + // make sure DLL Is loaded + if (!MakeSureDllIsLoaded()) + { + return(FALSE) ; + } + + pfTemp = (PF_EnumJobsA) + GetProcAddress(vhWinspoolDll, + "EnumJobsA") ; + + if (pfTemp == NULL) + { + return(FALSE); + } + else + { + pfEnumJobsA = pfTemp; + } + } + + return ((*pfEnumJobsA)(hPrinter, + FirstJob, + NoJobs, + Level, + pJob, + cbBuf, + pcbNeeded, + pcReturned)); +} + +/******************************************************************* + + NAME: MyEnumPrinters + + SYNOPSIS: calls thru to the superset function + + HISTORY: + CongpaY 22-Jan-1993 Created + +********************************************************************/ + +BOOL MyEnumPrinters(DWORD Flags, + LPSTR Name, + DWORD Level, + LPBYTE pPrinterEnum, + DWORD cbBuf, + LPDWORD pcbNeeded, + LPDWORD pcReturned) + +{ + PF_EnumPrintersA pfTemp; + + // if function has not been used before, get its address. + if (pfEnumPrintersA == NULL) + { + // make sure DLL Is loaded + if (!MakeSureDllIsLoaded()) + { + return(FALSE) ; + } + + pfTemp = (PF_EnumPrintersA) + GetProcAddress(vhWinspoolDll, + "EnumPrintersA") ; + + if (pfTemp == NULL) + { + return(TRUE); + } + else + pfEnumPrintersA = pfTemp; + } + + return ((*pfEnumPrintersA)(Flags, + Name, + Level, + pPrinterEnum, + cbBuf, + pcbNeeded, + pcReturned)); +} + +/******************************************************************* + + NAME: MyGetJob + + SYNOPSIS: calls thru to the superset function + + HISTORY: + CongpaY 22-Jan-1993 Created + +********************************************************************/ + +BOOL MyGetJob (HANDLE hPrinter, + DWORD JobId, + DWORD Level, + LPBYTE pJob, + DWORD cbBuf, + LPDWORD pcbNeeded) +{ + PF_GetJobA pfTemp; + + // if function has not been used before, get its address. + if (pfGetJobA == NULL) + { + // make sure DLL Is loaded + if (!MakeSureDllIsLoaded()) + { + return(FALSE) ; + } + + pfTemp = (PF_GetJobA) + GetProcAddress(vhWinspoolDll, + "GetJobA") ; + + if (pfTemp == NULL) + { + return(FALSE); + } + else + pfGetJobA = pfTemp; + } + + return ((*pfGetJobA)(hPrinter, + JobId, + Level, + pJob, + cbBuf, + pcbNeeded)); +} + +/******************************************************************* + + NAME: MyGetPrinter + + SYNOPSIS: calls thru to the superset function + + HISTORY: + CongpaY 22-Jan-1993 Created + +********************************************************************/ + +BOOL MyGetPrinter (HANDLE hPrinter, + DWORD Level, + LPBYTE pPrinter, + DWORD cbBuf, + LPDWORD pcbNeeded) +{ + PF_GetPrinterA pfTemp; + + // if function has not been used before, get its address. + if (pfGetPrinterA == NULL) + { + // make sure DLL Is loaded + if (!MakeSureDllIsLoaded()) + { + return(FALSE) ; + } + + pfTemp = (PF_GetPrinterA) + GetProcAddress(vhWinspoolDll, + "GetPrinterA") ; + + if (pfTemp == NULL) + { + return(FALSE); + } + else + pfGetPrinterA = pfTemp; + } + + return ((*pfGetPrinterA)(hPrinter, + Level, + pPrinter, + cbBuf, + pcbNeeded)); +} + + +/******************************************************************* + + NAME: MyOpenPrinter + + SYNOPSIS: calls thru to the superset function + + HISTORY: + CongpaY 22-Jan-1993 Created + +********************************************************************/ + +BOOL MyOpenPrinter (LPSTR pPrinterName, + LPHANDLE phPrinter, + LPPRINTER_DEFAULTSA pDefault) + +{ + PF_OpenPrinterA pfTemp; + + // if function has not been used before, get its address. + if (pfOpenPrinterA == NULL) + { + // make sure DLL Is loaded + if (!MakeSureDllIsLoaded()) + { + return(FALSE) ; + } + + pfTemp = (PF_OpenPrinterA) + GetProcAddress(vhWinspoolDll, + "OpenPrinterA") ; + + if (pfTemp == NULL) + { + return(FALSE); + } + else + pfOpenPrinterA = pfTemp; + } + + return ((*pfOpenPrinterA)(pPrinterName, + phPrinter, + pDefault)); +} + + +/******************************************************************* + + NAME: MyOpenPrinterW + + SYNOPSIS: calls thru to the superset function + + HISTORY: + CongpaY 22-Jan-1993 Created + +********************************************************************/ + +BOOL MyOpenPrinterW (LPWSTR pPrinterName, + LPHANDLE phPrinter, + LPPRINTER_DEFAULTSW pDefault) + +{ + PF_OpenPrinterW pfTemp; + + // if function has not been used before, get its address. + if (pfOpenPrinterW == NULL) + { + // make sure DLL Is loaded + if (!MakeSureDllIsLoaded()) + { + return(FALSE) ; + } + + pfTemp = (PF_OpenPrinterW) + GetProcAddress(vhWinspoolDll, + "OpenPrinterW") ; + + if (pfTemp == NULL) + { + return(FALSE); + } + else + pfOpenPrinterW = pfTemp; + } + + return ((*pfOpenPrinterW)(pPrinterName, + phPrinter, + pDefault)); +} +/******************************************************************* + + NAME: MySetJobA + + SYNOPSIS: calls thru to the superset function + + HISTORY: + CongpaY 22-Jan-1993 Created + AlbertT 24-Mar-1995 AddedLevel and pJob + +********************************************************************/ + +BOOL MySetJobA (HANDLE hPrinter, + DWORD JobId, + DWORD Level, + LPBYTE pJob, + DWORD Command) + +{ + PF_SetJobA pfTemp; + + // if function has not been used before, get its address. + if (pfSetJobA == NULL) + { + // make sure DLL Is loaded + if (!MakeSureDllIsLoaded()) + { + return(FALSE) ; + } + + pfTemp = (PF_SetJobA) + GetProcAddress(vhWinspoolDll, + "SetJobA") ; + + if (pfTemp == NULL) + { + return(FALSE); + } + else + pfSetJobA = pfTemp; + } + + return ((*pfSetJobA)(hPrinter, + JobId, + Level, + pJob, + Command)); +} + +/******************************************************************* + + NAME: MySetPrinterW + + SYNOPSIS: calls thru to the superset function + + HISTORY: + AlbertT 23-Mar-1995 Created + +********************************************************************/ + +BOOL MySetPrinterW(HANDLE hPrinter, + DWORD Level, + LPBYTE pPrinter, + DWORD Command) + +{ + PF_SetPrinterW pfTemp; + + // if function has not been used before, get its address. + if (pfSetPrinterW == NULL) + { + // make sure DLL Is loaded + if (!MakeSureDllIsLoaded()) + { + return(FALSE) ; + } + + pfTemp = (PF_SetPrinterW) + GetProcAddress(vhWinspoolDll, + "SetPrinterW") ; + + if (pfTemp == NULL) + { + return(FALSE); + } + else + pfSetPrinterW = pfTemp; + } + + return ((*pfSetPrinterW)(hPrinter, + Level, + pPrinter, + Command)); +} + +/******************************************************************* + + NAME: MyGetPrinterDriver + + SYNOPSIS: calls thru to the superset function + + HISTORY: + MuhuntS 06-Feb-1996 Created + +********************************************************************/ + +BOOL +MyGetPrinterDriver( + HANDLE hPrinter, + LPSTR pEnvironment, + DWORD Level, + LPBYTE pDriver, + DWORD cbBuf, + LPDWORD pcbNeeded + ) +{ + // + // if function has not been used before, get its address. + // + if ( !pfGetPrinterDriverA ) { + + // + // If dll is not loaded yet load it + // + if ( !MakeSureDllIsLoaded() ) { + + return FALSE; + } + + (FARPROC) pfGetPrinterDriverA = GetProcAddress(vhWinspoolDll, + "GetPrinterDriverA"); + + if ( !pfGetPrinterDriverA ) + return FALSE; + } + + return ((*pfGetPrinterDriverA)(hPrinter, + pEnvironment, + Level, + pDriver, + cbBuf, + pcbNeeded)); +} + +/******************************************************************* + + NAME: MakeSureDllIsLoaded + + SYNOPSIS: loads the WINSPOOL dll if need. + + EXIT: returns TRUE if dll already loaded, or loads + successfully. Returns false otherwise. Caller + should call GetLastError() to determine error. + + NOTES: it is up to the caller to call EnterLoadLibCritSect + before he calls this. + + HISTORY: + chuckc 29-Jul-1992 Created + congpay 22-Jan-1993 Modified. + +********************************************************************/ + +BOOL MakeSureDllIsLoaded(void) +{ + HINSTANCE handle ; + + // if already load, just return TRUE + if (vhWinspoolDll != NULL) + return TRUE ; + + // load the library. if it fails, it would have done a SetLastError. + handle = LoadLibrary(WINSPOOL_DLL_NAME); + if (handle == NULL) + return FALSE ; + + // we are cool. + vhWinspoolDll = handle ; + return TRUE ; +} + diff --git a/private/net/dosprint/dosspool.h b/private/net/dosprint/dosspool.h new file mode 100644 index 000000000..c42b91e69 --- /dev/null +++ b/private/net/dosprint/dosspool.h @@ -0,0 +1,125 @@ +/*++ + +Copyright (c) 1993 Microsoft Corporation + +Module Name: + + dosspool.h + +Abstract: + + Prototypes and manifests to support dosspool.C. + +Author: + + congpay 22-Jan-1993 + +Environment: + +Notes: + +Revision History: + + 22-Jan-1993 congpay Created + +--*/ +#include <winspool.h> + +typedef +BOOL +(*PF_ClosePrinter)( + HANDLE hPrinter +); + +typedef +BOOL +(*PF_EnumJobsA)( + HANDLE hPrinter, + DWORD FirstJob, + DWORD NoJobs, + DWORD Level, + LPBYTE pJob, + DWORD cbBuf, + LPDWORD pcbNeeded, + LPDWORD pcReturned +); + +typedef +BOOL +(*PF_EnumPrintersA)( + DWORD Flags, + LPSTR Name, + DWORD Level, + LPBYTE pPrinterEnum, + DWORD cbBuf, + LPDWORD pcbNeeded, + LPDWORD pcReturned +); + +typedef +BOOL +(*PF_GetJobA)( + HANDLE hPrinter, + DWORD JobId, + DWORD Level, + LPBYTE pJob, + DWORD cbBuf, + LPDWORD pcbNeeded +); + +typedef +BOOL +(*PF_GetPrinterA)( + HANDLE hPrinter, + DWORD Level, + LPBYTE pPrinter, + DWORD cbBuf, + LPDWORD pcbNeeded +); + +typedef +BOOL +(*PF_OpenPrinterA)( + LPSTR pPrinterName, + LPHANDLE phPrinter, + LPPRINTER_DEFAULTSA pDefault +); + +typedef +BOOL +(*PF_OpenPrinterW)( + LPWSTR pPrinterName, + LPHANDLE phPrinter, + LPPRINTER_DEFAULTSW pDefault +); + +typedef +BOOL +(*PF_SetJobA)( + HANDLE hPrinter, + DWORD JobId, + DWORD Level, + LPBYTE pJob, + DWORD Command +); + +typedef +BOOL +(*PF_SetPrinterW)( + HANDLE hPrinter, + DWORD Level, + LPBYTE pPrinter, + DWORD Command +); + +typedef +BOOL +(*PF_GetPrinterDriverA)( + HANDLE hPrinter, + LPSTR pEnvironment, + DWORD Level, + LPBYTE pDriver, + DWORD cbBuf, + LPDWORD pcbNeeded +); + diff --git a/private/net/dosprint/makefile b/private/net/dosprint/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/net/dosprint/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/net/dosprint/myspool.h b/private/net/dosprint/myspool.h new file mode 100644 index 000000000..c7d1e26e3 --- /dev/null +++ b/private/net/dosprint/myspool.h @@ -0,0 +1,125 @@ +/*++ + +Copyright (c) 1993 Microsoft Corporation + +Module Name: + + myspool.h + +Abstract: + + Prototypes and manifests for the functions used in dosprint.c, dosprtw.c + and dosprtp.c. + +Author: + + congpay 25-Jan-1993 + +Environment: + +Notes: + +Revision History: + + 25-Jan-1993 congpay Created + +--*/ + + +BOOL +MyClosePrinter( + HANDLE hPrinter +); + + +BOOL +MyEnumJobs( + HANDLE hPrinter, + DWORD FirstJob, + DWORD NoJobs, + DWORD Level, + LPBYTE pJob, + DWORD cbBuf, + LPDWORD pcbNeeded, + LPDWORD pcReturned +); + + +BOOL +MyEnumPrinters( + DWORD Flags, + LPSTR Name, + DWORD Level, + LPBYTE pPrinterEnum, + DWORD cbBuf, + LPDWORD pcbNeeded, + LPDWORD pcReturned +); + +BOOL +MyGetJob( + HANDLE hPrinter, + DWORD JobId, + DWORD Level, + LPBYTE pJob, + DWORD cbBuf, + LPDWORD pcbNeeded +); + + +BOOL +MyGetPrinter( + HANDLE hPrinter, + DWORD Level, + LPBYTE pPrinter, + DWORD cbBuf, + LPDWORD pcbNeeded +); + +BOOL +MyOpenPrinter( + LPSTR pPrinterName, + LPHANDLE phPrinter, + LPPRINTER_DEFAULTSA pDefault +); + + +BOOL +MyOpenPrinterW( + LPWSTR pPrinterName, + LPHANDLE phPrinter, + LPPRINTER_DEFAULTSW pDefault +); + +BOOL +MySetJobA( + HANDLE hPrinter, + DWORD JobId, + DWORD Level, + LPBYTE pJob, + DWORD Command +); + +BOOL +MySetPrinterW( + HANDLE hPrinter, + DWORD Level, + LPBYTE pPrinter, + DWORD Command +); + +BOOL +MyGetPrinterDriver( + HANDLE hPrinter, + LPSTR pEnvironment, + DWORD Level, + LPBYTE pDriver, + DWORD cbBuf, + LPDWORD pcbNeeded + ); + +LPSTR +GetFileNameA( + LPSTR pPathName + ); + diff --git a/private/net/dosprint/sources b/private/net/dosprint/sources new file mode 100644 index 000000000..e05053738 --- /dev/null +++ b/private/net/dosprint/sources @@ -0,0 +1,47 @@ +!IF 0 + +Copyright (c) 1989-1992 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=windows +MINORCOMP=dosprint + +TARGETNAME=dosprint +TARGETPATH=\nt\public\sdk\lib +TARGETTYPE=LIBRARY +TARGETLIBS=\nt\public\sdk\lib\*\winspool.lib + +INCLUDES=..\inc;..\..\inc +C_DEFINES=-DNO_WINSPOOLH + +!IFNDEF DISABLE_NET_UNICODE +UNICODE=1 +NET_C_DEFINES=-DUNICODE +!ENDIF + +MSC_WARNING_LEVEL=/W3 /WX + +SOURCES=\ + dosspool.c \ + DosPrint.c \ + DosPrtP.c \ + DosPrtW.c |