1011 lines
33 KiB
C
1011 lines
33 KiB
C
/*++
|
|
|
|
Copyright (c) 1992-1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ConvPrt.c
|
|
|
|
Abstract:
|
|
|
|
This module contains:
|
|
|
|
NetpConvertPrintDestArrayCharSet
|
|
NetpConvertPrintDestCharSet
|
|
NetpConvertPrintJobArrayCharSet
|
|
NetpConvertPrintJobCharSet
|
|
NetpConvertPrintQArrayCharSet
|
|
NetpConvertPrintQCharSet
|
|
|
|
This routines may be used for UNICODE-to-ANSI conversion, or
|
|
ANSI-to-UNICODE conversion. The routines assume the structures are
|
|
in native format for both input and output.
|
|
|
|
Author:
|
|
|
|
John Rogers (JohnRo) 20-Jul-1992
|
|
|
|
Environment:
|
|
|
|
Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
|
|
Requires ANSI C extensions: slash-slash comments, long external names.
|
|
|
|
Notes:
|
|
|
|
Beware that many of the parameters to the functions in this file
|
|
are implicitly used by the various COPY_ and CONVERT_ macros:
|
|
|
|
IN LPVOID FromInfo
|
|
OUT LPVOID ToInfo
|
|
IN BOOL ToUnicode
|
|
IN OUT LPBYTE * ToStringAreaPtr
|
|
|
|
Revision History:
|
|
|
|
20-Jul-1992 JohnRo
|
|
Created for RAID 10324: net print vs. UNICODE.
|
|
16-Dec-1992 JohnRo
|
|
DosPrint API cleanup.
|
|
Allow use of these routines for setinfo APIs.
|
|
Added NetpConvertPrintQArrayCharSet.
|
|
07-Apr-1993 JohnRo
|
|
RAID 5670: "NET PRINT \\server\share" gives err 124 (bad level) on NT.
|
|
14-Apr-1993 JohnRo
|
|
RAID 6167: avoid _access violation or assert with WFW print server.
|
|
|
|
01-Feb-2001 JSchwart
|
|
Moved from netlib
|
|
|
|
--*/
|
|
|
|
// These must be included first:
|
|
|
|
#include <nt.h> // NTSTATUS
|
|
#include <ntrtl.h> // RtlUnicodeToOemN
|
|
#include <windef.h> // IN, DWORD, etc.
|
|
#include <lmcons.h> // NET_API_STATUS.
|
|
|
|
// These may be included in any order:
|
|
|
|
#include <align.h> // POINTER_IS_ALIGNED(), ALIGN_ equates.
|
|
#include <debuglib.h> // IF_DEBUG().
|
|
#include <netdebug.h> // NetpAssert(), NetpKdPrint(()), etc.
|
|
#include <prefix.h> // PREFIX_ equates.
|
|
#include <string.h> // memcpy().
|
|
#include <strucinf.h> // My prototypes.
|
|
#include <tstring.h> // NetpCopy{type}To{type}().
|
|
#include <rxprint.h> // Print structures
|
|
#include "convprt.h" // Prototypes
|
|
#include "dosprtp.h" // NetpIsPrintQLevelValid
|
|
|
|
|
|
VOID
|
|
NetpCopyWStrToStrDBCSN(
|
|
OUT LPSTR Dest, // string in default LAN codepage
|
|
IN LPWSTR Src,
|
|
IN DWORD MaxStringSize
|
|
);
|
|
|
|
|
|
#define COPY_DWORD( typedefRoot, fieldName ) \
|
|
{ \
|
|
if (ToUnicode) { \
|
|
P ## typedefRoot ## A srcStruct = FromInfo; \
|
|
P ## typedefRoot ## W destStruct = ToInfo; \
|
|
NetpAssert( sizeof( destStruct->fieldName ) == sizeof( DWORD ) ); \
|
|
NetpAssert( sizeof( srcStruct->fieldName ) == sizeof( DWORD ) ); \
|
|
destStruct->fieldName = srcStruct->fieldName; \
|
|
} else { \
|
|
P ## typedefRoot ## W srcStruct = FromInfo; \
|
|
P ## typedefRoot ## A destStruct = ToInfo; \
|
|
NetpAssert( sizeof( destStruct->fieldName ) == sizeof( DWORD ) ); \
|
|
NetpAssert( sizeof( srcStruct->fieldName ) == sizeof( DWORD ) ); \
|
|
destStruct->fieldName = srcStruct->fieldName; \
|
|
} \
|
|
}
|
|
|
|
#define COPY_WORD( typedefRoot, fieldName ) \
|
|
{ \
|
|
if (ToUnicode) { \
|
|
P ## typedefRoot ## A srcStruct = FromInfo; \
|
|
P ## typedefRoot ## W destStruct = ToInfo; \
|
|
NetpAssert( sizeof( destStruct->fieldName ) == sizeof( WORD ) ); \
|
|
NetpAssert( sizeof( srcStruct->fieldName ) == sizeof( WORD ) ); \
|
|
destStruct->fieldName = srcStruct->fieldName; \
|
|
} else { \
|
|
P ## typedefRoot ## W srcStruct = FromInfo; \
|
|
P ## typedefRoot ## A destStruct = ToInfo; \
|
|
NetpAssert( sizeof( destStruct->fieldName ) == sizeof( WORD ) ); \
|
|
NetpAssert( sizeof( srcStruct->fieldName ) == sizeof( WORD ) ); \
|
|
destStruct->fieldName = srcStruct->fieldName; \
|
|
} \
|
|
}
|
|
|
|
#define COPY_FIXED_PART_WITHOUT_STRUCT( dataType ) \
|
|
{ \
|
|
(VOID) memcpy( \
|
|
ToInfo, /* dest */ \
|
|
FromInfo, /* src */ \
|
|
sizeof( dataType ) ); /* size */ \
|
|
}
|
|
|
|
#define CONVERT_CHAR_ARRAY( typedefRoot, fieldName ) \
|
|
{ \
|
|
if (ToUnicode) { \
|
|
P ## typedefRoot ## A structA = FromInfo; \
|
|
P ## typedefRoot ## W structW = ToInfo; \
|
|
NetpCopyStrToWStr( \
|
|
structW->fieldName, /* dest */ \
|
|
structA->fieldName); /* src */ \
|
|
} else { \
|
|
P ## typedefRoot ## A structA = ToInfo; \
|
|
P ## typedefRoot ## W structW = FromInfo; \
|
|
NetpCopyWStrToStrDBCSN( \
|
|
structA->fieldName, /* dest */ \
|
|
structW->fieldName, /* src */ \
|
|
sizeof(structA->fieldName));/*max bytes to copy*/ \
|
|
} \
|
|
}
|
|
|
|
#define CONVERT_OPTIONAL_STRING( typedefRoot, fieldName ) \
|
|
{ \
|
|
NetpAssert( ToStringAreaPtr != NULL ); \
|
|
NetpAssert( (*ToStringAreaPtr) != NULL ); \
|
|
if (ToUnicode) { \
|
|
P ## typedefRoot ## A structA = FromInfo; \
|
|
P ## typedefRoot ## W structW = ToInfo; \
|
|
LPSTR Src = structA->fieldName; \
|
|
NetpAssert( POINTER_IS_ALIGNED(*ToStringAreaPtr, ALIGN_WCHAR) ); \
|
|
if (Src == NULL) { \
|
|
structW->fieldName = NULL; \
|
|
} else { \
|
|
LPWSTR Dest; \
|
|
DWORD DestSize; \
|
|
DestSize = (strlen(Src)+1) * sizeof(WCHAR); \
|
|
Dest = (LPVOID) ( (*ToStringAreaPtr) - DestSize ); \
|
|
*ToStringAreaPtr = (LPVOID) Dest; \
|
|
structW->fieldName = Dest; \
|
|
NetpCopyStrToWStr( Dest, Src ); \
|
|
} \
|
|
} else { \
|
|
P ## typedefRoot ## W structW = FromInfo; \
|
|
P ## typedefRoot ## A structA = ToInfo; \
|
|
LPWSTR Src = structW->fieldName; \
|
|
if (Src == NULL) { \
|
|
structA->fieldName = NULL; \
|
|
} else { \
|
|
LPSTR Dest; \
|
|
DWORD DestSize; \
|
|
DestSize = (NetpUnicodeToDBCSLen(Src)+1); \
|
|
Dest = (LPVOID) ( (*ToStringAreaPtr) - DestSize ); \
|
|
*ToStringAreaPtr = (LPVOID) Dest; \
|
|
structA->fieldName = Dest; \
|
|
NetpCopyWStrToStrDBCS( Dest, Src ); \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
#define CONVERT_OPTIONAL_STRING_TO_REQ( typedefRoot, fieldName ) \
|
|
{ \
|
|
NetpAssert( ToStringAreaPtr != NULL ); \
|
|
NetpAssert( (*ToStringAreaPtr) != NULL ); \
|
|
if (ToUnicode) { \
|
|
P ## typedefRoot ## A structA = FromInfo; \
|
|
P ## typedefRoot ## W structW = ToInfo; \
|
|
LPWSTR Dest; \
|
|
DWORD DestSize; \
|
|
LPSTR Src = structA->fieldName; \
|
|
NetpAssert( POINTER_IS_ALIGNED(*ToStringAreaPtr, ALIGN_WCHAR) ); \
|
|
if (Src == NULL) { \
|
|
Src = ""; \
|
|
} \
|
|
DestSize = (strlen(Src)+1) * sizeof(WCHAR); \
|
|
Dest = (LPVOID) ( (*ToStringAreaPtr) - DestSize ); \
|
|
*ToStringAreaPtr = (LPVOID) Dest; \
|
|
structW->fieldName = Dest; \
|
|
NetpCopyStrToWStr( Dest, Src ); \
|
|
} else { \
|
|
P ## typedefRoot ## A structA = ToInfo; \
|
|
P ## typedefRoot ## W structW = FromInfo; \
|
|
LPSTR Dest; \
|
|
DWORD DestSize; \
|
|
LPWSTR Src = structW->fieldName; \
|
|
if (Src == NULL) { \
|
|
Src = L""; \
|
|
} \
|
|
DestSize = (NetpUnicodeToDBCSLen(Src)+1); \
|
|
Dest = (LPVOID) ( (*ToStringAreaPtr) - DestSize ); \
|
|
*ToStringAreaPtr = (LPVOID) Dest; \
|
|
structA->fieldName = Dest; \
|
|
NetpCopyWStrToStrDBCS( Dest, Src ); \
|
|
} \
|
|
}
|
|
|
|
#define CONVERT_CHAR_ARRAY_WITHOUT_STRUCT( ) \
|
|
{ \
|
|
if (ToUnicode) { \
|
|
NetpCopyStrToWStr( ToInfo, FromInfo ); \
|
|
} else { \
|
|
NetpCopyWStrToStrDBCS( ToInfo, FromInfo ); \
|
|
} \
|
|
}
|
|
|
|
#define CONVERT_CHAR_PTR_WITHOUT_STRUCT( ) \
|
|
{ \
|
|
if (ToUnicode) { \
|
|
NetpCopyStrToWStr( ToInfo, FromInfo ); \
|
|
} else { \
|
|
NetpCopyWStrToStrDBCS( ToInfo, FromInfo ); \
|
|
} \
|
|
}
|
|
|
|
NET_API_STATUS
|
|
NetpConvertPrintDestCharSet(
|
|
IN DWORD Level,
|
|
IN BOOL AddOrSetInfoApi,
|
|
IN LPVOID FromInfo,
|
|
OUT LPVOID ToInfo,
|
|
IN BOOL ToUnicode,
|
|
IN OUT LPBYTE * ToStringAreaPtr OPTIONAL
|
|
)
|
|
{
|
|
IF_DEBUG( CONVPRT ) {
|
|
NetpKdPrint(( PREFIX_NETLIB "NetpConvertPrintDestCharSet: "
|
|
"level " FORMAT_DWORD ":\n", Level ));
|
|
}
|
|
|
|
if ( (FromInfo == NULL) || (ToInfo == NULL) ) {
|
|
return (ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
switch (Level) {
|
|
|
|
case 0 :
|
|
//
|
|
// No structure for this level.
|
|
// Only field is name, which is in the fixed part itself.
|
|
//
|
|
CONVERT_CHAR_ARRAY_WITHOUT_STRUCT( );
|
|
|
|
break;
|
|
|
|
case 1 :
|
|
CONVERT_CHAR_ARRAY( PRDINFO, szName );
|
|
CONVERT_CHAR_ARRAY( PRDINFO, szUserName );
|
|
COPY_WORD( PRDINFO, uJobId );
|
|
COPY_WORD( PRDINFO, fsStatus );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRDINFO, pszStatus );
|
|
COPY_WORD( PRDINFO, time );
|
|
|
|
break;
|
|
|
|
case 2 :
|
|
//
|
|
// No structure for this level.
|
|
// Only field is pointer to name.
|
|
//
|
|
CONVERT_CHAR_PTR_WITHOUT_STRUCT( );
|
|
|
|
break;
|
|
|
|
case 3 :
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRDINFO3, pszPrinterName );
|
|
CONVERT_OPTIONAL_STRING( PRDINFO3, pszUserName );
|
|
CONVERT_OPTIONAL_STRING( PRDINFO3, pszLogAddr );
|
|
COPY_WORD( PRDINFO3, uJobId );
|
|
COPY_WORD( PRDINFO3, fsStatus );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRDINFO3, pszStatus );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRDINFO3, pszComment );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRDINFO3, pszDrivers );
|
|
COPY_WORD( PRDINFO3, time );
|
|
// No need to copy pad1.
|
|
|
|
break;
|
|
|
|
default :
|
|
return (ERROR_INVALID_LEVEL);
|
|
}
|
|
|
|
return (NO_ERROR);
|
|
|
|
} // NetpConvertPrintDestCharSet
|
|
|
|
|
|
NET_API_STATUS
|
|
NetpConvertPrintDestArrayCharSet(
|
|
IN DWORD Level,
|
|
IN BOOL AddOrSetInfoApi,
|
|
IN LPVOID FromInfo,
|
|
OUT LPVOID ToInfo,
|
|
IN BOOL ToUnicode,
|
|
IN OUT LPBYTE * ToStringAreaPtr OPTIONAL,
|
|
IN DWORD DestCount
|
|
)
|
|
{
|
|
NET_API_STATUS ApiStatus;
|
|
DWORD DestsLeft;
|
|
DWORD FromEntrySize, ToEntrySize;
|
|
LPVOID FromDest = FromInfo;
|
|
LPVOID ToDest = ToInfo;
|
|
|
|
if ( (FromInfo == NULL) || (ToInfo == NULL) ) {
|
|
return (ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
ApiStatus = NetpPrintDestStructureInfo (
|
|
Level,
|
|
PARMNUM_ALL,
|
|
TRUE, // yes, we want native sizes.
|
|
AddOrSetInfoApi,
|
|
(ToUnicode ? sizeof(CHAR) : sizeof(WCHAR) ), // FROM char size
|
|
NULL, // don't need data desc 16
|
|
NULL, // don't need data desc 32
|
|
NULL, // don't need data desc SMB
|
|
NULL, // don't need max total size
|
|
& FromEntrySize, // yes, we want fixed entry size
|
|
NULL ); // don't need string size
|
|
if (ApiStatus != NO_ERROR) {
|
|
return (ApiStatus);
|
|
}
|
|
NetpAssert( FromEntrySize > 0 );
|
|
|
|
ApiStatus = NetpPrintDestStructureInfo (
|
|
Level,
|
|
PARMNUM_ALL,
|
|
TRUE, // yes, we want native sizes.
|
|
AddOrSetInfoApi,
|
|
(ToUnicode ? sizeof(WCHAR) : sizeof(CHAR) ), // TO char size
|
|
NULL, // don't need data desc 16
|
|
NULL, // don't need data desc 32
|
|
NULL, // don't need data desc SMB
|
|
NULL, // don't need max total size
|
|
& ToEntrySize, // yes, we want fixed entry size
|
|
NULL ); // don't need string size
|
|
NetpAssert( ApiStatus == NO_ERROR );
|
|
NetpAssert( ToEntrySize > 0 );
|
|
|
|
for (DestsLeft = DestCount; DestsLeft>0; --DestsLeft) {
|
|
|
|
ApiStatus = NetpConvertPrintDestCharSet(
|
|
Level, // info level (for print Dest APIs)
|
|
AddOrSetInfoApi,
|
|
FromDest,
|
|
ToDest,
|
|
ToUnicode,
|
|
ToStringAreaPtr ); // update and move string area
|
|
|
|
//
|
|
// This can only fail because of bad parameters. If that's
|
|
// the case, every call in this loop will fail so bail out.
|
|
//
|
|
if (ApiStatus != NO_ERROR)
|
|
{
|
|
NetpAssert( ApiStatus == NO_ERROR );
|
|
break;
|
|
}
|
|
|
|
FromDest = (((LPBYTE) FromDest) + FromEntrySize);
|
|
ToDest = (((LPBYTE) ToDest) + ToEntrySize );
|
|
}
|
|
|
|
return (NO_ERROR);
|
|
|
|
} // NetpConvertPrintDestArrayCharSet
|
|
|
|
|
|
NET_API_STATUS
|
|
NetpConvertPrintJobCharSet(
|
|
IN DWORD Level,
|
|
IN BOOL AddOrSetInfoApi,
|
|
IN LPVOID FromInfo,
|
|
OUT LPVOID ToInfo,
|
|
IN BOOL ToUnicode,
|
|
IN OUT LPBYTE * ToStringAreaPtr OPTIONAL
|
|
)
|
|
{
|
|
IF_DEBUG( CONVPRT ) {
|
|
NetpKdPrint(( PREFIX_NETLIB "NetpConvertPrintJobCharSet: "
|
|
"level " FORMAT_DWORD ":\n", Level ));
|
|
}
|
|
|
|
if ( (FromInfo == NULL) || (ToInfo == NULL) ) {
|
|
return (ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
switch (Level) {
|
|
case 0 :
|
|
COPY_FIXED_PART_WITHOUT_STRUCT( WORD );
|
|
|
|
break;
|
|
|
|
case 1 :
|
|
COPY_WORD( PRJINFO, uJobId );
|
|
CONVERT_CHAR_ARRAY( PRJINFO, szUserName );
|
|
CONVERT_CHAR_ARRAY( PRJINFO, szNotifyName );
|
|
CONVERT_CHAR_ARRAY( PRJINFO, szDataType );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO, pszParms );
|
|
COPY_WORD( PRJINFO, uPosition );
|
|
COPY_WORD( PRJINFO, fsStatus );
|
|
CONVERT_OPTIONAL_STRING( PRJINFO, pszStatus );
|
|
COPY_DWORD( PRJINFO, ulSubmitted );
|
|
COPY_DWORD( PRJINFO, ulSize );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO, pszComment );
|
|
|
|
break;
|
|
|
|
case 2 :
|
|
|
|
COPY_WORD( PRJINFO2, uJobId );
|
|
COPY_WORD( PRJINFO2, uPriority );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO2, pszUserName );
|
|
COPY_WORD( PRJINFO2, uPosition );
|
|
COPY_WORD( PRJINFO2, fsStatus );
|
|
COPY_DWORD( PRJINFO2, ulSubmitted );
|
|
COPY_DWORD( PRJINFO2, ulSize );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO2, pszComment );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO2, pszDocument );
|
|
|
|
break;
|
|
|
|
case 3 :
|
|
COPY_WORD( PRJINFO3, uJobId );
|
|
COPY_WORD( PRJINFO3, uPriority );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO3, pszUserName );
|
|
COPY_WORD( PRJINFO3, uPosition );
|
|
COPY_WORD( PRJINFO3, fsStatus );
|
|
COPY_DWORD( PRJINFO3, ulSubmitted );
|
|
COPY_DWORD( PRJINFO3, ulSize );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO3, pszComment );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO3, pszDocument );
|
|
CONVERT_OPTIONAL_STRING( PRJINFO3, pszNotifyName );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO3, pszDataType );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO3, pszParms );
|
|
CONVERT_OPTIONAL_STRING( PRJINFO3, pszStatus );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO3, pszQueue );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO3, pszQProcName );
|
|
CONVERT_OPTIONAL_STRING( PRJINFO3, pszDriverName );
|
|
|
|
#if DBG
|
|
{
|
|
if (ToUnicode) {
|
|
PPRJINFO3A p3 = FromInfo;
|
|
NetpAssert( p3->pDriverData == NULL );
|
|
} else {
|
|
PPRJINFO3W p3 = FromInfo;
|
|
NetpAssert( p3->pDriverData == NULL );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
CONVERT_OPTIONAL_STRING( PRJINFO3, pszPrinterName );
|
|
|
|
break;
|
|
|
|
default :
|
|
return (ERROR_INVALID_LEVEL);
|
|
}
|
|
|
|
return (NO_ERROR);
|
|
|
|
} // NetpConvertPrintJobCharSet
|
|
|
|
|
|
NET_API_STATUS
|
|
NetpConvertPrintJobArrayCharSet(
|
|
IN DWORD Level,
|
|
IN BOOL AddOrSetInfoApi,
|
|
IN LPVOID FromInfo,
|
|
OUT LPVOID ToInfo,
|
|
IN BOOL ToUnicode,
|
|
IN OUT LPBYTE * ToStringAreaPtr OPTIONAL,
|
|
IN DWORD JobCount
|
|
)
|
|
{
|
|
NET_API_STATUS ApiStatus;
|
|
DWORD FromEntrySize, ToEntrySize;
|
|
LPVOID FromJob = FromInfo; // job structure
|
|
DWORD JobsLeft;
|
|
LPVOID ToJob = ToInfo; // job structure
|
|
|
|
if ( (FromInfo == NULL) || (ToInfo == NULL) ) {
|
|
return (ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
ApiStatus = NetpPrintJobStructureInfo (
|
|
Level,
|
|
PARMNUM_ALL,
|
|
TRUE, // yes, we want native sizes.
|
|
AddOrSetInfoApi,
|
|
(ToUnicode ? sizeof(CHAR) : sizeof(WCHAR) ), // FROM char size
|
|
NULL, // don't need data desc 16
|
|
NULL, // don't need data desc 32
|
|
NULL, // don't need data desc SMB
|
|
NULL, // don't need max total size
|
|
& FromEntrySize, // yes, we want fixed entry size
|
|
NULL ); // don't need string size
|
|
if (ApiStatus != NO_ERROR) {
|
|
return (ApiStatus);
|
|
}
|
|
NetpAssert( FromEntrySize > 0 );
|
|
|
|
ApiStatus = NetpPrintJobStructureInfo (
|
|
Level,
|
|
PARMNUM_ALL,
|
|
TRUE, // yes, we want native sizes.
|
|
AddOrSetInfoApi,
|
|
(ToUnicode ? sizeof(WCHAR) : sizeof(CHAR) ), // TO char size
|
|
NULL, // don't need data desc 16
|
|
NULL, // don't need data desc 32
|
|
NULL, // don't need data desc SMB
|
|
NULL, // don't need max total size
|
|
& ToEntrySize, // yes, we want fixed entry size
|
|
NULL ); // don't need string size
|
|
NetpAssert( ApiStatus == NO_ERROR );
|
|
NetpAssert( ToEntrySize > 0 );
|
|
|
|
for (JobsLeft = JobCount; JobsLeft>0; --JobsLeft) {
|
|
|
|
ApiStatus = NetpConvertPrintJobCharSet(
|
|
Level, // info level (for print job APIs)
|
|
AddOrSetInfoApi,
|
|
FromJob,
|
|
ToJob,
|
|
ToUnicode,
|
|
ToStringAreaPtr ); // update and move string area
|
|
|
|
//
|
|
// This can only fail because of bad parameters. If that's
|
|
// the case, every call in this loop will fail so bail out.
|
|
//
|
|
if (ApiStatus != NO_ERROR)
|
|
{
|
|
NetpAssert( ApiStatus == NO_ERROR );
|
|
break;
|
|
}
|
|
|
|
FromJob = (((LPBYTE) FromJob) + FromEntrySize);
|
|
ToJob = (((LPBYTE) ToJob ) + ToEntrySize );
|
|
|
|
if ((LPBYTE)*ToStringAreaPtr < (LPBYTE)ToJob)
|
|
return (ERROR_MORE_DATA) ;
|
|
}
|
|
|
|
return (NO_ERROR);
|
|
|
|
} // NetpConvertPrintJobArrayCharSet
|
|
|
|
|
|
|
|
NET_API_STATUS
|
|
NetpConvertPrintQCharSet(
|
|
IN DWORD Level,
|
|
IN BOOL AddOrSetInfoApi,
|
|
IN LPVOID FromInfo,
|
|
OUT LPVOID ToInfo,
|
|
IN BOOL ToUnicode,
|
|
IN OUT LPBYTE * ToStringAreaPtr OPTIONAL
|
|
)
|
|
{
|
|
NET_API_STATUS ApiStatus;
|
|
DWORD FromEntrySize, ToEntrySize;
|
|
|
|
IF_DEBUG( CONVPRT ) {
|
|
NetpKdPrint(( PREFIX_NETLIB "NetpConvertPrintQCharSet: "
|
|
"level " FORMAT_DWORD ":\n", Level ));
|
|
}
|
|
|
|
if ( (FromInfo == NULL) || (ToInfo == NULL) ) {
|
|
return (ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
ApiStatus = NetpPrintQStructureInfo (
|
|
Level,
|
|
PARMNUM_ALL,
|
|
TRUE, // yes, we want native sizes.
|
|
AddOrSetInfoApi,
|
|
(ToUnicode ? sizeof(WCHAR) : sizeof(CHAR) ), // TO char size
|
|
NULL, // don't need data desc 16
|
|
NULL, // don't need data desc 32
|
|
NULL, // don't need data desc SMB
|
|
NULL, // don't need aux desc 16
|
|
NULL, // don't need aux desc 32
|
|
NULL, // don't need aux desc SMB
|
|
NULL, // don't need max total size
|
|
& ToEntrySize, // yes, we want fixed entry size
|
|
NULL ); // don't need string size
|
|
if (ApiStatus != NO_ERROR) {
|
|
return (ApiStatus);
|
|
}
|
|
NetpAssert( ToEntrySize > 0 );
|
|
|
|
ApiStatus = NetpPrintQStructureInfo (
|
|
Level,
|
|
PARMNUM_ALL,
|
|
TRUE, // yes, we want native sizes.
|
|
AddOrSetInfoApi,
|
|
(ToUnicode ? sizeof(CHAR) : sizeof(WCHAR) ), // FROM char size
|
|
NULL, // don't need data desc 16
|
|
NULL, // don't need data desc 32
|
|
NULL, // don't need data desc SMB
|
|
NULL, // don't need aux desc 16
|
|
NULL, // don't need aux desc 32
|
|
NULL, // don't need aux desc SMB
|
|
NULL, // don't need max total size
|
|
& FromEntrySize, // yes, we want fixed entry size
|
|
NULL ); // don't need string size
|
|
NetpAssert( ApiStatus == NO_ERROR );
|
|
NetpAssert( FromEntrySize > 0 );
|
|
|
|
switch (Level) {
|
|
|
|
case 0 :
|
|
//
|
|
// No structure for this level.
|
|
// Only field is queue name, which is in the fixed part itself.
|
|
//
|
|
CONVERT_CHAR_ARRAY_WITHOUT_STRUCT( );
|
|
|
|
break;
|
|
|
|
case 1 : /*FALLTHROUGH*/
|
|
case 2 :
|
|
|
|
CONVERT_CHAR_ARRAY( PRQINFO, szName );
|
|
// No need to copy pad1.
|
|
COPY_WORD( PRQINFO, uPriority );
|
|
COPY_WORD( PRQINFO, uStartTime );
|
|
COPY_WORD( PRQINFO, uUntilTime );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRQINFO, pszSepFile );
|
|
CONVERT_OPTIONAL_STRING( PRQINFO, pszPrProc );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRQINFO, pszDestinations );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRQINFO, pszParms );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRQINFO, pszComment );
|
|
COPY_WORD( PRQINFO, fsStatus );
|
|
COPY_WORD( PRQINFO, cJobs );
|
|
|
|
if (Level == 2) {
|
|
NET_API_STATUS ApiStatus;
|
|
LPVOID FromArray, ToArray; // job structures
|
|
DWORD JobCount;
|
|
|
|
if (ToUnicode) {
|
|
PPRQINFOA pq = FromInfo;
|
|
JobCount = pq->cJobs;
|
|
} else {
|
|
PPRQINFOW pq = FromInfo;
|
|
JobCount = pq->cJobs;
|
|
}
|
|
|
|
FromArray = ( ((LPBYTE) FromInfo) + FromEntrySize );
|
|
ToArray = ( ((LPBYTE) ToInfo ) + ToEntrySize );
|
|
|
|
ApiStatus = NetpConvertPrintJobArrayCharSet(
|
|
1, // job info level
|
|
AddOrSetInfoApi,
|
|
FromArray,
|
|
ToArray,
|
|
ToUnicode,
|
|
ToStringAreaPtr, // update and move string area
|
|
JobCount );
|
|
if ( ApiStatus != NO_ERROR )
|
|
return (ApiStatus) ;
|
|
}
|
|
|
|
break;
|
|
|
|
case 3 : /*FALLTHROUGH*/
|
|
case 4 :
|
|
|
|
{
|
|
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRQINFO3, pszName );
|
|
COPY_WORD( PRQINFO3, uPriority );
|
|
COPY_WORD( PRQINFO3, uStartTime );
|
|
COPY_WORD( PRQINFO3, uUntilTime );
|
|
// No need to copy pad3.
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRQINFO3, pszSepFile );
|
|
CONVERT_OPTIONAL_STRING( PRQINFO3, pszPrProc );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRQINFO3, pszParms );
|
|
CONVERT_OPTIONAL_STRING_TO_REQ( PRQINFO3, pszComment );
|
|
COPY_WORD( PRQINFO3, fsStatus );
|
|
COPY_WORD( PRQINFO3, cJobs );
|
|
CONVERT_OPTIONAL_STRING( PRQINFO3, pszPrinters );
|
|
CONVERT_OPTIONAL_STRING( PRQINFO3, pszDriverName );
|
|
|
|
#if DBG
|
|
if (ToUnicode) {
|
|
PPRQINFO3A pq = FromInfo;
|
|
NetpAssert( pq->pDriverData == NULL );
|
|
} else {
|
|
PPRQINFO3W pq = FromInfo;
|
|
NetpAssert( pq->pDriverData == NULL );
|
|
}
|
|
#endif
|
|
|
|
if (Level == 4) {
|
|
|
|
NET_API_STATUS ApiStatus;
|
|
LPVOID FromFirstJob,ToFirstJob; // job structures
|
|
DWORD JobCount;
|
|
|
|
FromFirstJob = ( ((LPBYTE) FromInfo) + FromEntrySize );
|
|
ToFirstJob = ( ((LPBYTE) ToInfo ) + ToEntrySize );
|
|
|
|
if (ToUnicode) {
|
|
PPRQINFO3A pq = FromInfo;
|
|
JobCount = pq->cJobs;
|
|
} else {
|
|
PPRQINFO3W pq = FromInfo;
|
|
JobCount = pq->cJobs;
|
|
}
|
|
|
|
ApiStatus = NetpConvertPrintJobArrayCharSet(
|
|
2, // job info level
|
|
AddOrSetInfoApi,
|
|
FromFirstJob,
|
|
ToFirstJob,
|
|
ToUnicode,
|
|
ToStringAreaPtr,
|
|
JobCount );
|
|
|
|
NetpAssert( ApiStatus == NO_ERROR );
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case 5 :
|
|
//
|
|
// No structure for this level.
|
|
// Only field is queue name, which is just a pointer in the fixed part.
|
|
//
|
|
CONVERT_CHAR_PTR_WITHOUT_STRUCT( );
|
|
|
|
break;
|
|
|
|
default :
|
|
return (ERROR_INVALID_LEVEL);
|
|
}
|
|
|
|
return (NO_ERROR);
|
|
|
|
} // NetpConvertPrintQCharSet
|
|
|
|
|
|
NET_API_STATUS
|
|
NetpConvertPrintQArrayCharSet(
|
|
IN DWORD QLevel,
|
|
IN BOOL AddOrSetInfoApi,
|
|
IN LPVOID FromInfo,
|
|
OUT LPVOID ToInfo,
|
|
IN BOOL ToUnicode,
|
|
IN OUT LPBYTE * ToStringAreaPtr OPTIONAL,
|
|
IN DWORD QCount
|
|
)
|
|
{
|
|
NET_API_STATUS ApiStatus;
|
|
DWORD FromQEntrySize, ToQEntrySize;
|
|
DWORD FromJobEntrySize, ToJobEntrySize;
|
|
LPVOID FromQ = FromInfo; // Q structure
|
|
DWORD JobLevel;
|
|
DWORD QsLeft;
|
|
LPVOID ToQ = ToInfo; // Q structure
|
|
|
|
if ( (FromInfo == NULL) || (ToInfo == NULL) ) {
|
|
return (ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
ApiStatus = NetpPrintQStructureInfo (
|
|
QLevel,
|
|
PARMNUM_ALL,
|
|
TRUE, // yes, we want native sizes.
|
|
AddOrSetInfoApi,
|
|
(ToUnicode ? sizeof(CHAR) : sizeof(WCHAR) ), // FROM char size
|
|
NULL, // don't need data desc 16
|
|
NULL, // don't need data desc 32
|
|
NULL, // don't need data desc SMB
|
|
NULL, // don't need aux desc 16
|
|
NULL, // don't need aux desc 32
|
|
NULL, // don't need aux desc SMB
|
|
NULL, // don't need max total size
|
|
& FromQEntrySize, // yes, we want fixed entry size
|
|
NULL ); // don't need string size
|
|
if (ApiStatus != NO_ERROR) {
|
|
return (ApiStatus);
|
|
}
|
|
NetpAssert( FromQEntrySize > 0 );
|
|
|
|
ApiStatus = NetpPrintQStructureInfo (
|
|
QLevel,
|
|
PARMNUM_ALL,
|
|
TRUE, // yes, we want native sizes.
|
|
AddOrSetInfoApi,
|
|
(ToUnicode ? sizeof(WCHAR) : sizeof(CHAR) ), // TO char size
|
|
NULL, // don't need data desc 16
|
|
NULL, // don't need data desc 32
|
|
NULL, // don't need data desc SMB
|
|
NULL, // don't need aux desc 16
|
|
NULL, // don't need aux desc 32
|
|
NULL, // don't need aux desc SMB
|
|
NULL, // don't need max total size
|
|
& ToQEntrySize, // yes, we want fixed entry size
|
|
NULL ); // don't need string size
|
|
NetpAssert( ApiStatus == NO_ERROR );
|
|
NetpAssert( ToQEntrySize > 0 );
|
|
|
|
// Figure-out job-level associated with this queue info level.
|
|
switch (QLevel) {
|
|
case 2:
|
|
JobLevel = 1;
|
|
break;
|
|
case 4:
|
|
JobLevel = 2;
|
|
break;
|
|
default:
|
|
// No jobs for this Q info level.
|
|
JobLevel = (DWORD)-1;
|
|
}
|
|
|
|
if (JobLevel != (DWORD)-1) {
|
|
ApiStatus = NetpPrintJobStructureInfo (
|
|
JobLevel,
|
|
PARMNUM_ALL,
|
|
TRUE, // yes, we want native sizes.
|
|
AddOrSetInfoApi,
|
|
(ToUnicode ? sizeof(CHAR) : sizeof(WCHAR) ), // FROM char size
|
|
NULL, // don't need data desc 16
|
|
NULL, // don't need data desc 32
|
|
NULL, // don't need data desc SMB
|
|
NULL, // don't need max total size
|
|
& FromJobEntrySize, // yes, we want fixed entry size
|
|
NULL ); // don't need string size
|
|
NetpAssert( ApiStatus == NO_ERROR );
|
|
NetpAssert( FromJobEntrySize > 0 );
|
|
|
|
ApiStatus = NetpPrintJobStructureInfo (
|
|
JobLevel,
|
|
PARMNUM_ALL,
|
|
TRUE, // yes, we want native sizes.
|
|
AddOrSetInfoApi,
|
|
(ToUnicode ? sizeof(WCHAR) : sizeof(CHAR) ), // TO char size
|
|
NULL, // don't need data desc 16
|
|
NULL, // don't need data desc 32
|
|
NULL, // don't need data desc SMB
|
|
NULL, // don't need max total size
|
|
& ToJobEntrySize, // yes, we want fixed entry size
|
|
NULL ); // don't need string size
|
|
NetpAssert( ApiStatus == NO_ERROR );
|
|
NetpAssert( ToJobEntrySize > 0 );
|
|
}
|
|
|
|
for (QsLeft = QCount; QsLeft>0; --QsLeft) {
|
|
|
|
DWORD JobCount;
|
|
|
|
// Convert 1 queue structure and 0 or more job structures.
|
|
ApiStatus = NetpConvertPrintQCharSet(
|
|
QLevel, // info level (for print Q APIs)
|
|
AddOrSetInfoApi,
|
|
FromQ,
|
|
ToQ,
|
|
ToUnicode,
|
|
ToStringAreaPtr ); // update and move string area
|
|
|
|
if (ApiStatus != NO_ERROR)
|
|
{
|
|
NetpAssert( ApiStatus == NO_ERROR);
|
|
break;
|
|
}
|
|
|
|
// Bump pointers to start of next fixed queue structure.
|
|
// To do this, we need to find out how many jobs there are.
|
|
JobCount = NetpJobCountForQueue(
|
|
QLevel, // Q info level
|
|
FromQ, // Q fixed structure
|
|
!ToUnicode ); // does input have UNICODE strings?
|
|
|
|
// Bump past this queue structure.
|
|
FromQ = (((LPBYTE) FromQ) + FromQEntrySize);
|
|
ToQ = (((LPBYTE) ToQ ) + ToQEntrySize );
|
|
|
|
// Bump past jobs (if any).
|
|
if (JobCount > 0) {
|
|
NetpAssert( JobLevel != (DWORD)-1 );
|
|
FromQ = ( ((LPBYTE) FromQ) + (FromJobEntrySize * JobCount) );
|
|
ToQ = ( ((LPBYTE) ToQ ) + (ToJobEntrySize * JobCount) );
|
|
}
|
|
|
|
}
|
|
|
|
return (NO_ERROR);
|
|
|
|
} // NetpConvertPrintQArrayCharSet
|
|
|
|
|
|
VOID
|
|
NetpCopyWStrToStrDBCSN(
|
|
OUT LPSTR Dest,
|
|
IN LPWSTR Src,
|
|
IN DWORD MaxBytesInString
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
NetpCopyWStrToStr copies characters from a source string
|
|
to a destination, converting as it copies them.
|
|
|
|
Arguments:
|
|
|
|
Dest - is an LPSTR indicating where the converted characters are to go.
|
|
This string will be in the default codepage for the LAN.
|
|
|
|
Src - is in LPWSTR indicating the source string.
|
|
|
|
MaxBytesInString - indicates the maximum number of bytes to copy
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS NtStatus;
|
|
LONG Index;
|
|
|
|
NetpAssert( Dest != NULL );
|
|
NetpAssert( Src != NULL );
|
|
NetpAssert( ((LPVOID)Dest) != ((LPVOID)Src) );
|
|
NetpAssert( ROUND_UP_POINTER( Src, ALIGN_WCHAR ) == Src );
|
|
|
|
NtStatus = RtlUnicodeToOemN(
|
|
Dest, // Destination string
|
|
MaxBytesInString-1, // Destination string length
|
|
&Index, // Last char in translated string
|
|
Src, // Source string
|
|
wcslen(Src)*sizeof(WCHAR) // Length of source string
|
|
);
|
|
|
|
Dest[Index] = '\0';
|
|
|
|
NetpAssert( NT_SUCCESS(NtStatus) );
|
|
|
|
} // NetpCopyWStrToStrDBCSN
|
|
|
|
|
|
DWORD
|
|
NetpJobCountForQueue(
|
|
IN DWORD QueueLevel,
|
|
IN LPVOID Queue,
|
|
IN BOOL HasUnicodeStrings
|
|
)
|
|
{
|
|
NetpAssert( NetpIsPrintQLevelValid( QueueLevel, FALSE ) );
|
|
NetpAssert( Queue != NULL );
|
|
|
|
if (QueueLevel == 2) {
|
|
if (HasUnicodeStrings) {
|
|
PPRQINFOW pq = Queue;
|
|
return (pq->cJobs);
|
|
} else {
|
|
PPRQINFOA pq = Queue;
|
|
return (pq->cJobs);
|
|
}
|
|
} else if (QueueLevel == 4) {
|
|
if (HasUnicodeStrings) {
|
|
PPRQINFO3W pq = Queue;
|
|
return (pq->cJobs);
|
|
} else {
|
|
PPRQINFO3A pq = Queue;
|
|
return (pq->cJobs);
|
|
}
|
|
} else {
|
|
return (0);
|
|
}
|
|
/*NOTREACHED*/
|
|
|
|
} // NetpJobCountForQueue
|