/*++ Copyright (c) 1990-1994 Microsoft Corporation All rights reserved Module Name: winspla.c Abstract: Ansi end to winspool.drv Author: Environment: User Mode -Win32 Revision History: --*/ #include #include #include #include "winspl.h" #include #include #include "client.h" #include "browse.h" #include typedef int (FAR WINAPI *INT_FARPROC)(); extern LPSTR InterfaceAddress; extern LPWSTR szEnvironment; WCHAR *szCurDevMode = L"Printers\\DevModes2"; /* Make sure we have a prototype (in winspool.h): */ BOOL KickoffThread( LPWSTR pName, HWND hWnd, LPWSTR pPortName, INT_FARPROC pfn ); VOID RegUnicodeToAnsiString( LPBYTE pData, DWORD cbData, DWORD dwType ); #define NULL_TERMINATED 0 /* AnsiToUnicodeString * * Parameters: * * pAnsi - A valid source ANSI string. * * pUnicode - A pointer to a buffer large enough to accommodate * the converted string. * * StringLength - The length of the source ANSI string. * If 0 (NULL_TERMINATED), the string is assumed to be * null-terminated. * * Return: * * The return value from MultiByteToWideChar, the number of * wide characters returned. * * * andrewbe, 11 Jan 1993 */ INT AnsiToUnicodeString( LPSTR pAnsi, LPWSTR pUnicode, DWORD StringLength ) { INT iReturn; if( StringLength == NULL_TERMINATED ) StringLength = strlen( pAnsi ); iReturn = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pAnsi, StringLength + 1, pUnicode, StringLength + 1 ); // // Ensure NULL termination. // pUnicode[StringLength] = 0; return iReturn; } /* UnicodeToAnsiString * * Parameters: * * pUnicode - A valid source Unicode string. * * pANSI - A pointer to a buffer large enough to accommodate * the converted string. * * StringLength - The length of the source Unicode string. * If 0 (NULL_TERMINATED), the string is assumed to be * null-terminated. * * * Notes: * Added the #ifdef DBCS directive for MS-KK, if compiled * with DBCS enabled, we will allocate twice the size of the * buffer including the null terminator to take care of double * byte character strings - KrishnaG * * pUnicode is truncated to StringLength characters. * * Return: * * The return value from WideCharToMultiByte, the number of * multi-byte characters returned. * * * andrewbe, 11 Jan 1993 */ INT UnicodeToAnsiString( LPWSTR pUnicode, LPSTR pAnsi, DWORD StringLength) { LPSTR pTempBuf = NULL; INT rc = 0; if( StringLength == NULL_TERMINATED ) { // // StringLength is just the // number of characters in the string // StringLength = wcslen( pUnicode ); } // // WideCharToMultiByte doesn't NULL terminate if we're copying // just part of the string, so terminate here. // pUnicode[StringLength] = 0; // // Include one for the NULL // StringLength++; // // Unfortunately, WideCharToMultiByte doesn't do conversion in place, // so allocate a temporary buffer, which we can then copy: // if( pAnsi == (LPSTR)pUnicode ) { #ifdef DBCS pTempBuf = LocalAlloc( LPTR, StringLength * 2 ); #else pTempBuf = LocalAlloc( LPTR, StringLength ); #endif pAnsi = pTempBuf; } if( pAnsi ) { rc = WideCharToMultiByte( CP_ACP, 0, pUnicode, StringLength, pAnsi, #ifdef DBCS StringLength*2, #else StringLength, #endif NULL, NULL ); } /* If pTempBuf is non-null, we must copy the resulting string * so that it looks as if we did it in place: */ if( pTempBuf && ( rc > 0 ) ) { pAnsi = (LPSTR)pUnicode; strcpy( pAnsi, pTempBuf ); LocalFree( pTempBuf ); } return rc; } void ConvertUnicodeToAnsiStrings( LPBYTE pStructure, LPDWORD pOffsets ) { register DWORD i=0; LPWSTR pUnicode; LPSTR pAnsi; while (pOffsets[i] != -1) { pUnicode = *(LPWSTR *)(pStructure+pOffsets[i]); pAnsi = (LPSTR)pUnicode; if (pUnicode) { UnicodeToAnsiString(pUnicode, pAnsi, NULL_TERMINATED); } i++; } } LPWSTR AllocateUnicodeString( LPSTR pPrinterName ) { LPWSTR pUnicodeString; if (!pPrinterName) return NULL; pUnicodeString = LocalAlloc(LPTR, strlen(pPrinterName)*sizeof(WCHAR) + sizeof(WCHAR)); if (pUnicodeString) AnsiToUnicodeString(pPrinterName, pUnicodeString, NULL_TERMINATED); return pUnicodeString; } LPWSTR FreeUnicodeString( LPWSTR pUnicodeString ) { if (!pUnicodeString) return NULL; return LocalFree(pUnicodeString); } LPBYTE AllocateUnicodeStructure( LPBYTE pAnsiStructure, DWORD cbStruct, LPDWORD pOffsets ) { DWORD i, j; LPWSTR *ppUnicodeString; LPSTR *ppAnsiString; LPBYTE pUnicodeStructure; if (!pAnsiStructure) { return NULL; } pUnicodeStructure = LocalAlloc(LPTR, cbStruct); if (pUnicodeStructure) { memcpy(pUnicodeStructure, pAnsiStructure, cbStruct); for (i = 0 ; pOffsets[i] != -1 ; ++i) { ppAnsiString = (LPSTR *)(pAnsiStructure+pOffsets[i]); ppUnicodeString = (LPWSTR *)(pUnicodeStructure+pOffsets[i]); *ppUnicodeString = AllocateUnicodeString(*ppAnsiString); if (*ppAnsiString && !*ppUnicodeString) { for( j = 0 ; j < i ; ++j) { ppUnicodeString = (LPWSTR *)(pUnicodeStructure+pOffsets[j]); FreeUnicodeString(*ppUnicodeString); } LocalFree(pUnicodeStructure); pUnicodeStructure = NULL; break; } } } return pUnicodeStructure; } VOID RegUnicodeToAnsiString( LPBYTE pData, DWORD cbData, DWORD dwType) { DWORD i; if (dwType == REG_MULTI_SZ) { for (i = 0 ; ((LPWSTR)pData)[i] && (i<<1) < cbData ; i += strlen((LPSTR)pData + i) + 1) { UnicodeToAnsiString((LPWSTR) pData + i, (LPSTR) pData + i, NULL_TERMINATED); } SPLASSERT((i<<1) < cbData); // There's an extra NULL Character at the end for REG_MULTI_SZ: be sure we add it! ((LPSTR) pData)[i] = '\0'; } else if (dwType == REG_SZ || dwType == REG_EXPAND_SZ) { UnicodeToAnsiString((LPWSTR) pData, (LPSTR) pData, NULL_TERMINATED); } } DWORD ComputeMaxStrlenW( LPWSTR pString, DWORD cchBufMax) /*++ Routine Description: Returns the length of the Unicode string, EXCLUDING the NULL. If the string (plus NULL) won't fit into the cchBufMax, then the string len is decreased. Arguments: Return Value: --*/ { DWORD cchLen; // // Include space for the NULL. // cchBufMax--; cchLen = wcslen(pString); if (cchLen > cchBufMax) return cchBufMax; return cchLen; } DWORD ComputeMaxStrlenA( LPSTR pString, DWORD cchBufMax) /*++ Routine Description: Returns the length of the Ansi string, EXCLUDING the NULL. If the string (plus NULL) won't fit into the cchBufMax, then the string len is decreased. Arguments: Return Value: --*/ { DWORD cchLen; // // Include space for the NULL. // cchBufMax--; cchLen = lstrlenA(pString); if (cchLen > cchBufMax) return cchBufMax; return cchLen; } /***************************** Function Header ****************************** * AllocateUnicodeDevMode * Allocate a UNICODE version of the DEVMODE structure, and optionally * copy the contents of the ANSI version passed in. * * RETURNS: * Address of newly allocated structure, 0 if storage not available. * * HISTORY: * 09:23 on 10-Aug-92 -by- Lindsay Harris [lindsayh] * Made it usable. * * Originally "written" by DaveSn. * ***************************************************************************/ LPDEVMODEW AllocateUnicodeDevMode( LPDEVMODEA pANSIDevMode ) { LPDEVMODEW pUnicodeDevMode; LPBYTE p1, p2; DWORD dwSize; // // If the devmode is NULL, then return NULL -- KrishnaG // if ( !pANSIDevMode || !pANSIDevMode->dmSize ) { return NULL; } SPLASSERT( bValidDevModeA( pANSIDevMode )); // // Determine output structure size. This has two components: the // DEVMODEW structure size, plus any private data area. The latter // is only meaningful when a structure is passed in. // dwSize = pANSIDevMode->dmSize + pANSIDevMode->dmDriverExtra + sizeof(DEVMODEW) - sizeof(DEVMODEA); pUnicodeDevMode = (LPDEVMODEW) LocalAlloc(LPTR, dwSize); if( !pUnicodeDevMode ) { return NULL; /* This is bad news */ } // // Copy dmDeviceName which is a string // AnsiToUnicodeString(pANSIDevMode->dmDeviceName, pUnicodeDevMode->dmDeviceName, ComputeMaxStrlenA(pANSIDevMode->dmDeviceName, sizeof pANSIDevMode->dmDeviceName)); // // Does the devmode we got have a dmFormName? (Windows 3.1 had // DevMode of size 40 and did not have dmFormName) // if ( (LPBYTE)pANSIDevMode + pANSIDevMode->dmSize > (LPBYTE) pANSIDevMode->dmFormName ) { // // Copy everything between dmDeviceName and dmFormName // p1 = (LPBYTE) pANSIDevMode->dmDeviceName + sizeof(pANSIDevMode->dmDeviceName); p2 = (LPBYTE) pANSIDevMode->dmFormName; CopyMemory((LPBYTE) pUnicodeDevMode->dmDeviceName + sizeof(pUnicodeDevMode->dmDeviceName), p1, p2 - p1); // // Copy dmFormName which is a string // AnsiToUnicodeString(pANSIDevMode->dmFormName, pUnicodeDevMode->dmFormName, ComputeMaxStrlenA(pANSIDevMode->dmFormName, sizeof pANSIDevMode->dmFormName)); // // Copy everything after dmFormName // p1 = (LPBYTE) pANSIDevMode->dmFormName + sizeof(pANSIDevMode->dmFormName); p2 = (LPBYTE) pANSIDevMode + pANSIDevMode->dmSize + pANSIDevMode->dmDriverExtra; CopyMemory((LPBYTE) pUnicodeDevMode->dmFormName + sizeof(pUnicodeDevMode->dmFormName), p1, p2 - p1); pUnicodeDevMode->dmSize = pANSIDevMode->dmSize + sizeof(DEVMODEW) - sizeof(DEVMODEA); } else { // // Copy everything after dmDeviceName // p1 = (LPBYTE) pANSIDevMode->dmDeviceName + sizeof(pANSIDevMode->dmDeviceName); p2 = (LPBYTE) pANSIDevMode + pANSIDevMode->dmSize + pANSIDevMode->dmDriverExtra; CopyMemory((LPBYTE) pUnicodeDevMode->dmDeviceName + sizeof(pUnicodeDevMode->dmDeviceName), p1, p2-p1); pUnicodeDevMode->dmSize = pANSIDevMode->dmSize + sizeof(pUnicodeDevMode->dmDeviceName) - sizeof(pANSIDevMode->dmDeviceName); } SPLASSERT(pUnicodeDevMode->dmDriverExtra == pANSIDevMode->dmDriverExtra); return pUnicodeDevMode; } /************************** Function Header ****************************** * CopyAnsiDevModeFromUnicodeDevMode * Converts the UNICODE version of the DEVMODE to the ANSI version. * * RETURNS: * Nothing. * * HISTORY: * 09:57 on 10-Aug-92 -by- Lindsay Harris [lindsayh] * This one actually works! * * Originally dreamed up by DaveSn. * **************************************************************************/ void CopyAnsiDevModeFromUnicodeDevMode( LPDEVMODEA pANSIDevMode, /* Filled in by us */ LPDEVMODEW pUnicodeDevMode /* Source of data to fill above */ ) { LPBYTE p1, p2, pExtra; WORD dmSize, dmDriverExtra; // // NOTE: THE TWO INPUT STRUCTURES MAY BE THE SAME. // dmSize = pUnicodeDevMode->dmSize; dmDriverExtra = pUnicodeDevMode->dmDriverExtra; pExtra = (LPBYTE) pUnicodeDevMode + pUnicodeDevMode->dmSize; // // Copy dmDeviceName which is a string // UnicodeToAnsiString(pUnicodeDevMode->dmDeviceName, pANSIDevMode->dmDeviceName, ComputeMaxStrlenW(pUnicodeDevMode->dmDeviceName, sizeof pANSIDevMode->dmDeviceName)); // // Does the devmode we got have a dmFormName? (Windows 3.1 had // DevMode of size 40 and did not have dmFormName) // if ( (LPBYTE)pUnicodeDevMode + dmSize > (LPBYTE) pUnicodeDevMode->dmFormName ) { // // Copy everything between dmDeviceName and dmFormName // p1 = (LPBYTE) pUnicodeDevMode->dmDeviceName + sizeof(pUnicodeDevMode->dmDeviceName); p2 = (LPBYTE) pUnicodeDevMode->dmFormName; MoveMemory((LPBYTE) pANSIDevMode->dmDeviceName + sizeof(pANSIDevMode->dmDeviceName), p1, p2 - p1); // // Copy dmFormName which is a string // UnicodeToAnsiString(pUnicodeDevMode->dmFormName, pANSIDevMode->dmFormName, ComputeMaxStrlenW(pUnicodeDevMode->dmFormName, sizeof pANSIDevMode->dmFormName)); // // Copy everything after dmFormName // p1 = (LPBYTE) pUnicodeDevMode->dmFormName + sizeof(pUnicodeDevMode->dmFormName); p2 = (LPBYTE) pUnicodeDevMode + dmSize + dmDriverExtra; MoveMemory((LPBYTE) pANSIDevMode->dmFormName + sizeof(pANSIDevMode->dmFormName), p1, p2 - p1); pANSIDevMode->dmSize = dmSize + sizeof(DEVMODEA) - sizeof(DEVMODEW); } else { // // Copy everything after dmDeviceName // p1 = (LPBYTE) pUnicodeDevMode->dmDeviceName + sizeof(pUnicodeDevMode->dmDeviceName); p2 = (LPBYTE) pUnicodeDevMode + dmSize + dmDriverExtra; MoveMemory((LPBYTE) pANSIDevMode->dmDeviceName + sizeof(pANSIDevMode->dmDeviceName), p1, p2 - p1); pANSIDevMode->dmSize = dmSize + sizeof(pANSIDevMode->dmDeviceName) - sizeof(pUnicodeDevMode->dmDeviceName); } SPLASSERT(pANSIDevMode->dmDriverExtra == dmDriverExtra); return; } BOOL ConvertAnsiDevModeToUnicodeDevmode( PDEVMODEA pAnsiDevMode, PDEVMODEW pUnicodeDevMode, DWORD dwUnicodeDevModeSize, PDWORD pcbNeeded ) { PDEVMODEW pDevModeW = NULL; BOOL bRet = FALSE; if ( !pAnsiDevMode ) { SetLastError(ERROR_INVALID_PARAMETER); goto Cleanup; } SPLASSERT( bValidDevModeA( pAnsiDevMode )); pDevModeW = AllocateUnicodeDevMode(pAnsiDevMode); if ( !pDevModeW ) { goto Cleanup; } *pcbNeeded = pDevModeW->dmSize + pDevModeW->dmDriverExtra; if ( *pcbNeeded > dwUnicodeDevModeSize ) { SetLastError(ERROR_INSUFFICIENT_BUFFER); goto Cleanup; } CopyMemory((LPBYTE)pUnicodeDevMode, (LPBYTE)pDevModeW, *pcbNeeded); bRet = TRUE; Cleanup: if ( pDevModeW ) LocalFree(pDevModeW); return bRet; } BOOL ConvertUnicodeDevModeToAnsiDevmode( PDEVMODEW pUnicodeDevMode, PDEVMODEA pAnsiDevMode, DWORD dwAnsiDevModeSize, PDWORD pcbNeeded ) { LPBYTE pDevMode = NULL; BOOL bRet = FALSE; DWORD dwSize; if ( !pUnicodeDevMode ) { SetLastError(ERROR_INVALID_PARAMETER); goto Cleanup; } dwSize = pUnicodeDevMode->dmSize + pUnicodeDevMode->dmDriverExtra; pDevMode = LocalAlloc(LPTR, dwSize); if ( !pDevMode ) { goto Cleanup; } CopyMemory(pDevMode, (LPBYTE)pUnicodeDevMode, dwSize); CopyAnsiDevModeFromUnicodeDevMode((PDEVMODEA) pDevMode, (PDEVMODEW) pDevMode); *pcbNeeded = ((PDEVMODEA)pDevMode)->dmSize + ((PDEVMODEA)pDevMode)->dmDriverExtra; if ( *pcbNeeded > dwAnsiDevModeSize ) { SetLastError(ERROR_INSUFFICIENT_BUFFER); goto Cleanup; } CopyMemory((LPBYTE)pAnsiDevMode, pDevMode, *pcbNeeded); bRet = TRUE; Cleanup: if ( pDevMode ) LocalFree(pDevMode); return bRet; } void FreeUnicodeStructure( LPBYTE pUnicodeStructure, LPDWORD pOffsets ) { DWORD i=0; if ( pUnicodeStructure == NULL ) { return; } while (pOffsets[i] != -1) { FreeUnicodeString(*(LPWSTR *)(pUnicodeStructure+pOffsets[i])); i++; } LocalFree( pUnicodeStructure ); } BOOL EnumPrintersA( DWORD Flags, LPSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned ) { BOOL ReturnValue; DWORD cbStruct; DWORD *pOffsets; LPWSTR pUnicodeName; switch (Level) { case STRESSINFOLEVEL: pOffsets = PrinterInfoStressStrings; cbStruct = sizeof(PRINTER_INFO_STRESS); break; case 4: pOffsets = PrinterInfo4Strings; cbStruct = sizeof(PRINTER_INFO_4); break; case 1: pOffsets = PrinterInfo1Strings; cbStruct = sizeof(PRINTER_INFO_1); break; case 2: pOffsets = PrinterInfo2Strings; cbStruct = sizeof(PRINTER_INFO_2); break; case 5: pOffsets = PrinterInfo5Strings; cbStruct = sizeof(PRINTER_INFO_5); break; default: SetLastError(ERROR_INVALID_LEVEL); return FALSE; } pUnicodeName = AllocateUnicodeString(Name); if (Name && !pUnicodeName) return FALSE; ReturnValue = EnumPrintersW(Flags, pUnicodeName, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned); if (ReturnValue && pPrinterEnum) { DWORD i=*pcReturned; while (i--) { ConvertUnicodeToAnsiStrings(pPrinterEnum, pOffsets); if ((Level == 2) && pPrinterEnum) { PRINTER_INFO_2 *pPrinterInfo2 = (PRINTER_INFO_2 *)pPrinterEnum; if (pPrinterInfo2->pDevMode) CopyAnsiDevModeFromUnicodeDevMode( (LPDEVMODEA)pPrinterInfo2->pDevMode, (LPDEVMODEW)pPrinterInfo2->pDevMode); } pPrinterEnum+=cbStruct; } } FreeUnicodeString(pUnicodeName); return ReturnValue; } BOOL OpenPrinterA( LPSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSA pDefault ) { BOOL ReturnValue = FALSE; LPWSTR pUnicodePrinterName = NULL; PRINTER_DEFAULTSW UnicodeDefaults={NULL, NULL, 0}; pUnicodePrinterName = AllocateUnicodeString(pPrinterName); if (pPrinterName && !pUnicodePrinterName) goto Cleanup; if (pDefault) { UnicodeDefaults.pDatatype = AllocateUnicodeString(pDefault->pDatatype); if (pDefault->pDatatype && !UnicodeDefaults.pDatatype) goto Cleanup; // // Milestones etc. 4.5 passes in a bogus devmode in pDefaults. // Be sure to validate here. // if( bValidDevModeA( pDefault->pDevMode )){ UnicodeDefaults.pDevMode = AllocateUnicodeDevMode( pDefault->pDevMode ); if( !UnicodeDefaults.pDevMode ){ goto Cleanup; } } UnicodeDefaults.DesiredAccess = pDefault->DesiredAccess; } ReturnValue = OpenPrinterW(pUnicodePrinterName, phPrinter, &UnicodeDefaults); if (ReturnValue) { ((PSPOOL)*phPrinter)->Status |= SPOOL_STATUS_ANSI; } Cleanup: if (UnicodeDefaults.pDevMode) LocalFree(UnicodeDefaults.pDevMode); FreeUnicodeString(UnicodeDefaults.pDatatype); FreeUnicodeString(pUnicodePrinterName); return ReturnValue; } BOOL ResetPrinterA( HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault ) { BOOL ReturnValue = FALSE; PRINTER_DEFAULTSW UnicodeDefaults={NULL, NULL, 0}; if (pDefault) { if (pDefault->pDatatype == (LPSTR)-1) { UnicodeDefaults.pDatatype = (LPWSTR)-1; } else { UnicodeDefaults.pDatatype = AllocateUnicodeString(pDefault->pDatatype); if (pDefault->pDatatype && !UnicodeDefaults.pDatatype) return FALSE; } if (pDefault->pDevMode == (LPDEVMODEA)-1) { UnicodeDefaults.pDevMode = (LPDEVMODEW)-1; } else { if( bValidDevModeA( pDefault->pDevMode )){ UnicodeDefaults.pDevMode = AllocateUnicodeDevMode( pDefault->pDevMode ); if( !UnicodeDefaults.pDevMode ){ goto Cleanup; } } } } ReturnValue = ResetPrinterW(hPrinter, &UnicodeDefaults); if (UnicodeDefaults.pDevMode && (UnicodeDefaults.pDevMode != (LPDEVMODEW)-1)){ LocalFree(UnicodeDefaults.pDevMode); } Cleanup: if (UnicodeDefaults.pDatatype && (UnicodeDefaults.pDatatype != (LPWSTR)-1)) { FreeUnicodeString(UnicodeDefaults.pDatatype); } return ReturnValue; } BOOL SetJobA( HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pJob, DWORD Command ) { BOOL ReturnValue=FALSE; LPBYTE pUnicodeStructure=NULL; LPDEVMODEW pDevModeW = NULL; DWORD cbStruct; DWORD *pOffsets; switch (Level) { case 0: break; case 1: pOffsets = JobInfo1Strings; cbStruct = sizeof(JOB_INFO_1); break; case 2: pOffsets = JobInfo2Strings; cbStruct = sizeof(JOB_INFO_2); break; case 3: return SetJobW( hPrinter, JobId, Level, pJob, Command ); default: SetLastError(ERROR_INVALID_LEVEL); return FALSE; } if (Level) { pUnicodeStructure = AllocateUnicodeStructure(pJob, cbStruct, pOffsets); if (pJob && !pUnicodeStructure) return FALSE; } if ( Level == 2 && pUnicodeStructure && pJob ) { if( bValidDevModeA( ((LPJOB_INFO_2A)pJob)->pDevMode )){ pDevModeW = AllocateUnicodeDevMode(((LPJOB_INFO_2A)pJob)->pDevMode); if( !pDevModeW ){ ReturnValue = FALSE; goto Cleanup; } ((LPJOB_INFO_2W) pUnicodeStructure)->pDevMode = pDevModeW; } } ReturnValue = SetJobW(hPrinter, JobId, Level, pUnicodeStructure, Command); if ( pDevModeW ) { LocalFree(pDevModeW); } Cleanup: FreeUnicodeStructure(pUnicodeStructure, pOffsets); return ReturnValue; } BOOL GetJobA( HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded ) { DWORD *pOffsets; switch (Level) { case 1: pOffsets = JobInfo1Strings; break; case 2: pOffsets = JobInfo2Strings; break; case 3: return GetJobW( hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded ); default: SetLastError(ERROR_INVALID_LEVEL); return FALSE; } if (GetJob(hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded)) { ConvertUnicodeToAnsiStrings(pJob, pOffsets); // // Convert the devmode in place for INFO_2. // if( Level == 2 ){ PJOB_INFO_2A pJobInfo2 = (PJOB_INFO_2A)pJob; if( pJobInfo2->pDevMode ){ CopyAnsiDevModeFromUnicodeDevMode( (LPDEVMODEA)pJobInfo2->pDevMode, (LPDEVMODEW)pJobInfo2->pDevMode); } } return TRUE; } else return FALSE; } BOOL EnumJobsA( HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned ) { DWORD i, cbStruct, *pOffsets; switch (Level) { case 1: pOffsets = JobInfo1Strings; cbStruct = sizeof(JOB_INFO_1); break; case 2: pOffsets = JobInfo2Strings; cbStruct = sizeof(JOB_INFO_2); break; case 3: return EnumJobsW( hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned ); default: SetLastError(ERROR_INVALID_LEVEL); return FALSE; } if (EnumJobsW(hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned)) { i=*pcReturned; while (i--) { ConvertUnicodeToAnsiStrings(pJob, pOffsets); // // Convert the devmode in place for INFO_2. // if( Level == 2 ){ PJOB_INFO_2A pJobInfo2 = (PJOB_INFO_2A)pJob; if( pJobInfo2->pDevMode ){ CopyAnsiDevModeFromUnicodeDevMode( (LPDEVMODEA)pJobInfo2->pDevMode, (LPDEVMODEW)pJobInfo2->pDevMode); } } pJob += cbStruct; } return TRUE; } else return FALSE; } HANDLE AddPrinterA( LPSTR pName, DWORD Level, LPBYTE pPrinter ) { HANDLE hPrinter = NULL; LPBYTE pUnicodeStructure = NULL; LPDEVMODEW pDevModeW = NULL; LPWSTR pUnicodeName = NULL; DWORD cbStruct; DWORD *pOffsets; switch (Level) { case 2: pOffsets = PrinterInfo2Strings; cbStruct = sizeof(PRINTER_INFO_2); break; default: SetLastError(ERROR_INVALID_LEVEL); return NULL; } pUnicodeStructure = AllocateUnicodeStructure(pPrinter, cbStruct, pOffsets); if (pPrinter && !pUnicodeStructure) goto Cleanup; pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; if ( pUnicodeStructure ) { if( bValidDevModeA( ((LPPRINTER_INFO_2A)pPrinter)->pDevMode )){ pDevModeW = AllocateUnicodeDevMode( ((LPPRINTER_INFO_2A)pPrinter)->pDevMode); if( !pDevModeW ){ goto Cleanup; } } ((LPPRINTER_INFO_2W)pUnicodeStructure)->pDevMode = pDevModeW; hPrinter = AddPrinterW(pUnicodeName, Level, pUnicodeStructure); } Cleanup: FreeUnicodeString( pUnicodeName ); if ( pDevModeW ) { LocalFree(pDevModeW); } FreeUnicodeStructure( pUnicodeStructure, pOffsets ); return hPrinter; } BOOL AddPrinterConnectionA( LPSTR pName ) { BOOL rc; LPWSTR pUnicodeName; pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) return FALSE; rc = AddPrinterConnectionW(pUnicodeName); FreeUnicodeString(pUnicodeName); return rc; } BOOL DeletePrinterConnectionA( LPSTR pName ) { BOOL rc; LPWSTR pUnicodeName; pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) return FALSE; rc = DeletePrinterConnectionW(pUnicodeName); FreeUnicodeString(pUnicodeName); return rc; } BOOL SetPrinterA( HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD Command ) { LPBYTE pUnicodeStructure; /* Unicode version of input data */ DWORD cbStruct; /* Size of the output structure */ DWORD *pOffsets; /* -1 terminated list of addresses */ DWORD ReturnValue=FALSE; switch (Level) { case 0: // // This could be 2 cases. STRESSINFOLEVEL, or the real 0 level. // If Command is 0 then it is STRESSINFOLEVEL, else real 0 level // if ( !Command ) { pOffsets = PrinterInfoStressStrings; cbStruct = sizeof( PRINTER_INFO_STRESS ); } break; case 1: pOffsets = PrinterInfo1Strings; cbStruct = sizeof( PRINTER_INFO_1 ); break; case 2: pOffsets = PrinterInfo2Strings; cbStruct = sizeof( PRINTER_INFO_2 ); break; case 3: pOffsets = PrinterInfo3Strings; cbStruct = sizeof( PRINTER_INFO_3 ); break; case 4: pOffsets = PrinterInfo4Strings; cbStruct = sizeof( PRINTER_INFO_4 ); break; case 5: pOffsets = PrinterInfo5Strings; cbStruct = sizeof( PRINTER_INFO_5 ); break; case 6: break; default: SetLastError( ERROR_INVALID_LEVEL ); return FALSE; } // // The structure needs to have its CONTENTS converted from // ANSI to Unicode. The above switch() statement filled in // the two important pieces of information needed to accomplish // this goal. First is the size of the structure, second is // a list of the offset within the structure to UNICODE // string pointers. The AllocateUnicodeStructure() call will // allocate a wide version of the structure, copy its contents // and convert the strings to Unicode as it goes. That leaves // us to deal with any other pieces needing conversion. // // // If Level == 0 and Command != 0 then pPrintert is a DWORD // if ( Level == 6 || (!Level && Command) ) { if ( Level == 6 || Command == PRINTER_CONTROL_SET_STATUS ) pUnicodeStructure = pPrinter; else pUnicodeStructure = NULL; } else { pUnicodeStructure = AllocateUnicodeStructure(pPrinter, cbStruct, pOffsets); if (pPrinter && !pUnicodeStructure) return FALSE; } #define pPrinterInfo2W ((LPPRINTER_INFO_2W)pUnicodeStructure) #define pPrinterInfo2A ((LPPRINTER_INFO_2A)pPrinter) // The Level 2 structure has a DEVMODE struct in it: convert now if ( Level == 2 && pUnicodeStructure && pPrinterInfo2A->pDevMode ) { if( bValidDevModeA( pPrinterInfo2A->pDevMode )){ pPrinterInfo2W->pDevMode = AllocateUnicodeDevMode( pPrinterInfo2A->pDevMode ); if( !pPrinterInfo2W->pDevMode) { FreeUnicodeStructure(pUnicodeStructure, pOffsets); return FALSE; } } } ReturnValue = SetPrinterW( hPrinter, Level, pUnicodeStructure, Command ); // Free the DEVMODE we allocated (if we did!), then the // the Unicode structure and its contents. if (Level == 2 && pUnicodeStructure && pPrinterInfo2W->pDevMode ) { LocalFree( pPrinterInfo2W->pDevMode ); } // // STRESS_INFO and Levels 1-5 // if ( Level != 6 && (Level || !Command) ) FreeUnicodeStructure( pUnicodeStructure, pOffsets ); #undef pPrinterInfo2W #undef pPrinterInfo2A return ReturnValue; } BOOL GetPrinterA( HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded ) { DWORD *pOffsets; switch (Level) { case STRESSINFOLEVEL: pOffsets = PrinterInfoStressOffsets; break; case 1: pOffsets = PrinterInfo1Strings; break; case 2: pOffsets = PrinterInfo2Strings; break; case 3: pOffsets = PrinterInfo3Strings; break; case 4: pOffsets = PrinterInfo4Strings; break; case 5: pOffsets = PrinterInfo5Strings; break; default: SetLastError(ERROR_INVALID_LEVEL); return FALSE; } if (GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded)) { if (pPrinter) { ConvertUnicodeToAnsiStrings(pPrinter, pOffsets); if ((Level == 2) && pPrinter) { PRINTER_INFO_2 *pPrinterInfo2 = (PRINTER_INFO_2 *)pPrinter; if (pPrinterInfo2->pDevMode) CopyAnsiDevModeFromUnicodeDevMode( (LPDEVMODEA)pPrinterInfo2->pDevMode, (LPDEVMODEW)pPrinterInfo2->pDevMode); } } return TRUE; } return FALSE; } // // Conversion in place // BOOL UnicodeToAnsiDependentFiles( LPWSTR pUnicodeDependentFiles ) { LPWSTR pUnicodeStr; LPSTR pAnsiStr; DWORD len, rc; if ( ! (pUnicodeStr = pUnicodeDependentFiles) || !*pUnicodeStr ) return TRUE; while ( *pUnicodeStr ) pUnicodeStr += wcslen(pUnicodeStr) + 1; len = pUnicodeStr - pUnicodeDependentFiles + 1; #ifdef DBCS if ( !(pAnsiStr = LocalAlloc(LPTR, len * sizeof(char) * 2)) ) { #else if ( !(pAnsiStr = LocalAlloc(LPTR, len * sizeof(char))) ) { #endif return FALSE; } rc = WideCharToMultiByte(CP_ACP, 0, pUnicodeDependentFiles, len, pAnsiStr, #ifdef DBCS len*2, #else len, #endif NULL, NULL ); if( rc > 0 ) { memcpy( (LPSTR) pUnicodeDependentFiles, pAnsiStr, len*sizeof(char) ); LocalFree( pAnsiStr ); return TRUE; } LocalFree( pAnsiStr ); return FALSE; } BOOL AnsiToUnicodeDependentFiles( LPSTR pAnsiDependentFiles, LPWSTR *pUnicodeDependentFiles ) { LPWSTR pUnicodeStr; LPSTR pAnsiStr; DWORD len, rc; if ( ! (pAnsiStr = pAnsiDependentFiles) || !*pAnsiStr ) { *pUnicodeDependentFiles = NULL; return TRUE; } while ( *pAnsiStr ) pAnsiStr += strlen(pAnsiStr) + 1; len = pAnsiStr - pAnsiDependentFiles + 1; if ( !(*pUnicodeDependentFiles = LocalAlloc(LPTR, len * sizeof(WCHAR))) ) { return FALSE; } AnsiToUnicodeString(pAnsiDependentFiles, *pUnicodeDependentFiles, len-1); return TRUE; } BOOL AddPrinterDriverA( LPSTR pName, DWORD Level, PBYTE pPrinter ) { BOOL ReturnValue=FALSE; DWORD cbStruct; LPWSTR pUnicodeName = NULL; LPBYTE pUnicodeStructure = NULL; LPDWORD pOffsets; switch (Level) { case 2: pOffsets = DriverInfo2Strings; cbStruct = sizeof(DRIVER_INFO_2); break; case 3: pOffsets = DriverInfo3Strings; cbStruct = sizeof(DRIVER_INFO_3); break; default: SetLastError(ERROR_INVALID_LEVEL); return FALSE; } if (!pPrinter) { SetLastError (ERROR_INVALID_PARAMETER); return FALSE; } pUnicodeStructure = AllocateUnicodeStructure(pPrinter, cbStruct, pOffsets); if (pPrinter && !pUnicodeStructure) goto Error; pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Error; // Handle dependent files which is upto \0\0 if ( Level == 3 && !AnsiToUnicodeDependentFiles( (LPSTR) ((PDRIVER_INFO_3)pPrinter)->pDependentFiles, &(((PDRIVER_INFO_3)pUnicodeStructure)->pDependentFiles)) ) { goto Error; } ReturnValue = AddPrinterDriverW(pUnicodeName, Level, pUnicodeStructure); if ( Level == 3 && ((PDRIVER_INFO_3)pUnicodeStructure)->pDependentFiles ) { LocalFree(((PDRIVER_INFO_3)pUnicodeStructure)->pDependentFiles); } Error: FreeUnicodeStructure( pUnicodeStructure, pOffsets ); FreeUnicodeString(pUnicodeName); return ReturnValue; } BOOL EnumPrinterDriversA( LPSTR pName, LPSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned ) { BOOL ReturnValue=FALSE; DWORD cbStruct; DWORD *pOffsets; LPWSTR pUnicodeName = NULL; LPWSTR pUnicodeEnvironment = NULL; switch (Level) { case 1: pOffsets = DriverInfo1Strings; cbStruct = sizeof(DRIVER_INFO_1); break; case 2: pOffsets = DriverInfo2Strings; cbStruct = sizeof(DRIVER_INFO_2); break; case 3: pOffsets = DriverInfo3Strings; cbStruct = sizeof(DRIVER_INFO_3); break; default: SetLastError(ERROR_INVALID_LEVEL); return FALSE; } pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; pUnicodeEnvironment = AllocateUnicodeString(pEnvironment); if (pEnvironment && !pUnicodeEnvironment) goto Cleanup; if (ReturnValue = EnumPrinterDriversW(pUnicodeName, pUnicodeEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned)) { if (pDriverInfo) { DWORD i=*pcReturned; while (i--) { ConvertUnicodeToAnsiStrings(pDriverInfo, pOffsets); if ( Level == 3 && !UnicodeToAnsiDependentFiles( ((PDRIVER_INFO_3) pDriverInfo)->pDependentFiles) ) { ReturnValue = FALSE; } pDriverInfo+=cbStruct; } } } Cleanup: FreeUnicodeString(pUnicodeEnvironment); FreeUnicodeString(pUnicodeName); return ReturnValue; } BOOL GetPrinterDriverA( HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded ) { DWORD *pOffsets; LPWSTR pUnicodeEnvironment = NULL; BOOL ReturnValue; switch (Level) { case 1: pOffsets = DriverInfo1Strings; break; case 2: pOffsets = DriverInfo2Strings; break; case 3: pOffsets = DriverInfo3Strings; break; default: SetLastError(ERROR_INVALID_LEVEL); return FALSE; } pUnicodeEnvironment = AllocateUnicodeString(pEnvironment); if (pEnvironment && !pUnicodeEnvironment) return FALSE; if (ReturnValue = GetPrinterDriverW(hPrinter, pUnicodeEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded)) { if (pDriverInfo) { ConvertUnicodeToAnsiStrings(pDriverInfo, pOffsets); if ( Level == 3 && !UnicodeToAnsiDependentFiles( ((PDRIVER_INFO_3) pDriverInfo)->pDependentFiles) ) { ReturnValue = FALSE; } } } // BUGBUG if called to get the size of buffer it will return the size of a W structure and strings // rather than the A version. also see enum FreeUnicodeString(pUnicodeEnvironment); return ReturnValue; } BOOL GetPrinterDriverDirectoryA( LPSTR pName, LPSTR pEnvironment, DWORD Level, LPBYTE pDriverDirectory, DWORD cbBuf, LPDWORD pcbNeeded ) { DWORD *pOffsets; LPWSTR pUnicodeEnvironment = NULL; LPWSTR pUnicodeName = NULL; LPWSTR pDriverDirectoryW = NULL; BOOL ReturnValue = FALSE; DWORD Offsets[]={0,(DWORD)-1}; switch (Level) { case 1: pOffsets = DriverInfo1Offsets; break; default: SetLastError(ERROR_INVALID_LEVEL); return FALSE; } pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; pUnicodeEnvironment = AllocateUnicodeString(pEnvironment); if (pEnvironment && !pUnicodeEnvironment) goto Cleanup; if (ReturnValue = GetPrinterDriverDirectoryW(pUnicodeName, pUnicodeEnvironment, Level, pDriverDirectory, cbBuf, pcbNeeded)) { if (pDriverDirectory) { pDriverDirectoryW = (LPWSTR)pDriverDirectory; while (*pDriverDirectory++ = (UCHAR)*pDriverDirectoryW++) ; // !!! Should call NLS API } } Cleanup: FreeUnicodeString(pUnicodeEnvironment); FreeUnicodeString(pUnicodeName); return ReturnValue; } BOOL DeletePrinterDriverA( LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName ) { LPWSTR pUnicodeName = NULL; LPWSTR pUnicodeEnvironment = NULL; LPWSTR pUnicodeDriverName = NULL; BOOL rc = FALSE; pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; pUnicodeEnvironment = AllocateUnicodeString(pEnvironment); if (pEnvironment && !pUnicodeEnvironment) goto Cleanup; pUnicodeDriverName = AllocateUnicodeString(pDriverName); if (pDriverName && !pUnicodeDriverName) goto Cleanup; rc = DeletePrinterDriverW(pUnicodeName, pUnicodeEnvironment, pUnicodeDriverName); Cleanup: FreeUnicodeString(pUnicodeName); FreeUnicodeString(pUnicodeEnvironment); FreeUnicodeString(pUnicodeDriverName); return rc; } BOOL AddPrintProcessorA( LPSTR pName, LPSTR pEnvironment, LPSTR pPathName, LPSTR pPrintProcessorName ) { BOOL ReturnValue=FALSE; LPWSTR pUnicodeName = NULL; LPWSTR pUnicodeEnvironment = NULL; LPWSTR pUnicodePathName = NULL; LPWSTR pUnicodePrintProcessorName = NULL; if (!pPathName || !*pPathName) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } if (!pPrintProcessorName || !*pPrintProcessorName) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; pUnicodeEnvironment = AllocateUnicodeString(pEnvironment); if (pEnvironment && !pUnicodeEnvironment) goto Cleanup; pUnicodePathName = AllocateUnicodeString(pPathName); if (pPathName && !pUnicodePathName) goto Cleanup; pUnicodePrintProcessorName = AllocateUnicodeString(pPrintProcessorName); if (pPrintProcessorName && !pUnicodePrintProcessorName) goto Cleanup; if (pUnicodePathName && pUnicodePrintProcessorName) { ReturnValue = AddPrintProcessorW(pUnicodeName, pUnicodeEnvironment, pUnicodePathName, pUnicodePrintProcessorName); } Cleanup: FreeUnicodeString(pUnicodeName); FreeUnicodeString(pUnicodeEnvironment); FreeUnicodeString(pUnicodePathName); FreeUnicodeString(pUnicodePrintProcessorName); return ReturnValue; } BOOL EnumPrintProcessorsA( LPSTR pName, LPSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned ) { BOOL ReturnValue=FALSE; DWORD cbStruct; DWORD *pOffsets; LPWSTR pUnicodeName = NULL; LPWSTR pUnicodeEnvironment = NULL; switch (Level) { case 1: pOffsets = PrintProcessorInfo1Strings; cbStruct = sizeof(PRINTPROCESSOR_INFO_1); break; default: SetLastError(ERROR_INVALID_LEVEL); return FALSE; } pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; pUnicodeEnvironment = AllocateUnicodeString(pEnvironment); if (pEnvironment && !pUnicodeEnvironment) goto Cleanup; if (ReturnValue = EnumPrintProcessorsW(pUnicodeName, pUnicodeEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned)) { if (pPrintProcessorInfo) { DWORD i=*pcReturned; while (i--) { ConvertUnicodeToAnsiStrings(pPrintProcessorInfo, pOffsets); pPrintProcessorInfo+=cbStruct; } } } Cleanup: FreeUnicodeString(pUnicodeName); FreeUnicodeString(pUnicodeEnvironment); return ReturnValue; } BOOL GetPrintProcessorDirectoryA( LPSTR pName, LPSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded ) { BOOL ReturnValue = FALSE; LPWSTR pUnicodeName = NULL; LPWSTR pUnicodeEnvironment = NULL; LPWSTR pPrintProcessorInfoW; pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; pUnicodeEnvironment = AllocateUnicodeString(pEnvironment); if (pEnvironment && !pUnicodeEnvironment) goto Cleanup; ReturnValue = GetPrintProcessorDirectoryW(pUnicodeName, pUnicodeEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded); if (pPrintProcessorInfo) { pPrintProcessorInfoW = (LPWSTR)pPrintProcessorInfo; while (*pPrintProcessorInfo++ = (UCHAR)*pPrintProcessorInfoW++) ; // !!! Should call NLS API } Cleanup: FreeUnicodeString(pUnicodeName); FreeUnicodeString(pUnicodeEnvironment); return ReturnValue; } BOOL EnumPrintProcessorDatatypesA( LPSTR pName, LPSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatype, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned ) { BOOL ReturnValue=FALSE; DWORD cbStruct; DWORD *pOffsets; LPWSTR pUnicodeName = NULL; LPWSTR pUnicodePrintProcessorName = NULL; switch (Level) { case 1: pOffsets = DatatypeInfo1Strings; cbStruct = sizeof(DATATYPES_INFO_1); break; default: SetLastError(ERROR_INVALID_LEVEL); return FALSE; } pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; pUnicodePrintProcessorName = AllocateUnicodeString(pPrintProcessorName); if (pPrintProcessorName && !pUnicodePrintProcessorName) goto Cleanup; if (ReturnValue = EnumPrintProcessorDatatypesW(pUnicodeName, pUnicodePrintProcessorName, Level, pDatatype, cbBuf, pcbNeeded, pcReturned)) { if (pDatatype) { DWORD i=*pcReturned; while (i--) { ConvertUnicodeToAnsiStrings(pDatatype, pOffsets); pDatatype += cbStruct; } } } Cleanup: FreeUnicodeString(pUnicodeName); FreeUnicodeString(pUnicodePrintProcessorName); return ReturnValue; } DWORD StartDocPrinterA( HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo ) { BOOL ReturnValue = FALSE; LPBYTE pUnicodeStructure = NULL; pUnicodeStructure = AllocateUnicodeStructure(pDocInfo, sizeof(DOC_INFO_1A), DocInfo1Offsets); if (pDocInfo && !pUnicodeStructure) goto Cleanup; ReturnValue = StartDocPrinterW(hPrinter, Level, pUnicodeStructure); Cleanup: FreeUnicodeStructure(pUnicodeStructure, DocInfo1Offsets); return ReturnValue; } BOOL AddJobA( HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcbNeeded ) { BOOL ReturnValue; if (ReturnValue = AddJobW(hPrinter, Level, pData, cbBuf, pcbNeeded)) ConvertUnicodeToAnsiStrings(pData, AddJobStrings); return ReturnValue; } DWORD GetPrinterDataA( HANDLE hPrinter, LPSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded ) { DWORD ReturnValue = 0; DWORD ReturnType = 0; LPWSTR pUnicodeValueName = NULL; pUnicodeValueName = AllocateUnicodeString(pValueName); if (pValueName && !pUnicodeValueName) goto Cleanup; if (!pType) { pType = (PDWORD) &ReturnType; } ReturnValue = GetPrinterDataW(hPrinter, pUnicodeValueName, pType, pData, nSize, pcbNeeded); if ( ReturnValue == ERROR_SUCCESS && pData) RegUnicodeToAnsiString(pData, *pcbNeeded, *pType); Cleanup: FreeUnicodeString(pUnicodeValueName); return ReturnValue; } DWORD EnumPrinterDataA( HANDLE hPrinter, DWORD dwIndex, // index of value to query LPSTR pValueName, // address of buffer for value string DWORD cbValueName, // size of pValueName LPDWORD pcbValueName, // address for size of value buffer LPDWORD pType, // address of buffer for type code LPBYTE pData, // address of buffer for value data DWORD cbData, // size of pData LPDWORD pcbData // address for size of data buffer ) { DWORD ReturnValue = 0; DWORD i; ReturnValue = EnumPrinterDataW(hPrinter, dwIndex, (LPWSTR) pValueName, cbValueName, pcbValueName, pType, pData, cbData, pcbData); if (ReturnValue == ERROR_SUCCESS && (cbValueName || cbData)) { if (pData && pType) { RegUnicodeToAnsiString(pData, *pcbData, *pType); } UnicodeToAnsiString((LPWSTR) pValueName, (LPSTR) pValueName, NULL_TERMINATED); } return ReturnValue; } DWORD DeletePrinterDataA( HANDLE hPrinter, LPSTR pValueName ) { DWORD ReturnValue = 0; LPWSTR pUnicodeValueName = NULL; pUnicodeValueName = AllocateUnicodeString(pValueName); if (pValueName && !pUnicodeValueName) goto Cleanup; ReturnValue = DeletePrinterDataW(hPrinter, (LPWSTR) pUnicodeValueName); Cleanup: FreeUnicodeString(pUnicodeValueName); return ReturnValue; } DWORD SetPrinterDataA( HANDLE hPrinter, LPSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData ) { DWORD ReturnValue = 0; LPWSTR pUnicodeValueName = NULL; LPWSTR pUnicodeData = NULL; DWORD cbDataString; pUnicodeValueName = AllocateUnicodeString(pValueName); if (pValueName && !pUnicodeValueName) goto Cleanup; if (Type == REG_SZ || Type == REG_EXPAND_SZ) { // First verify that we have a valid string & cbData cbDataString = strlen(pData) + sizeof(CHAR); if (cbDataString != cbData) { ReturnValue = ERROR_INVALID_PARAMETER; SetLastError(ReturnValue); } else { // Now convert ANSI pData string to Unicode pUnicodeData = AllocateUnicodeString(pData); if ( !pUnicodeData ) goto Cleanup; cbData = wcslen(pUnicodeData)*sizeof(WCHAR) + sizeof(WCHAR); ReturnValue = SetPrinterDataW(hPrinter, pUnicodeValueName, Type, (LPBYTE) pUnicodeData, cbData); FreeUnicodeString(pUnicodeData); } } else ReturnValue = SetPrinterDataW(hPrinter, pUnicodeValueName, Type, pData, cbData); Cleanup: FreeUnicodeString(pUnicodeValueName); return ReturnValue; } /**************************** Function Header ******************************* * DocumentPropertiesA * The ANSI version of the DocumentProperties function. Basically * converts the input parameters to UNICODE versions and calls * the DocumentPropertiesW function. * * CAVEATS: PRESUMES THAT IF pDevModeOutput IS SUPPLIED, IT HAS THE SIZE * OF THE UNICODE VERSION. THIS WILL USUALLY HAPPEN IF THE CALLER * FIRST CALLS TO FIND THE SIZE REQUIRED> * * RETURNS: * Somesort of LONG. * * HISTORY: * 10:12 on 11-Aug-92 -by- Lindsay Harris [lindsayh] * Changed to call DocumentPropertiesW * * Created by DaveSn * ****************************************************************************/ LONG DocumentPropertiesA( HWND hWnd, HANDLE hPrinter, LPSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput, DWORD fMode ) { LPWSTR pUnicodeDeviceName = NULL; LPDEVMODEW pUnicodeDevModeInput = NULL; LPDEVMODEW pUnicodeDevModeOutput = NULL; LONG ReturnValue = -1; pUnicodeDeviceName = AllocateUnicodeString(pDeviceName); if (pDeviceName && !pUnicodeDeviceName) goto Cleanup; ReturnValue = DocumentPropertiesW(hWnd, hPrinter, pUnicodeDeviceName, NULL, NULL, 0); if (ReturnValue > 0) { if (fMode) { if (pUnicodeDevModeOutput = LocalAlloc(LMEM_FIXED, ReturnValue)) { // // Only convert the input buffer if one is specified // and fMode indicates it's valid. WinNT 3.51 used // pDevModeInput regardless of DM_IN_BUFFER, but this // broke Borland Delphi for win95 + Corel Flow for win95. // if( pDevModeInput && ( fMode & DM_IN_BUFFER )){ // // If the devmode is invalid, then don't pass one in. // This fixes MS Imager32 (which passes dmSize == 0) and // Milestones etc. 4.5. // // Note: this assumes that pDevModeOutput is still the // correct size! // if( !bValidDevModeA( pDevModeInput )){ fMode &= ~DM_IN_BUFFER; } else { pUnicodeDevModeInput = AllocateUnicodeDevMode( pDevModeInput ); if( !pUnicodeDevModeInput ){ ReturnValue = -1; goto Cleanup; } } } ReturnValue = DocumentPropertiesW(hWnd, hPrinter, pUnicodeDeviceName, pUnicodeDevModeOutput, pUnicodeDevModeInput, fMode ); // // The printer driver has filled in the DEVMODEW // structure - if one was passed in. Now convert it // back to a DEVMODEA structure. // if (pDevModeOutput && (ReturnValue == IDOK)) { CopyAnsiDevModeFromUnicodeDevMode(pDevModeOutput, pUnicodeDevModeOutput); } } else ReturnValue = -1; } else ReturnValue-=sizeof(DEVMODEW)-sizeof(DEVMODEA); } Cleanup: if (pUnicodeDevModeInput) LocalFree(pUnicodeDevModeInput); if (pUnicodeDevModeOutput) LocalFree(pUnicodeDevModeOutput); FreeUnicodeString(pUnicodeDeviceName); return ReturnValue; } BOOL WriteCurDevModeToRegistry( LPWSTR pPrinterName, LPDEVMODEW pDevMode ) { DWORD Status; HKEY hDevMode; SPLASSERT(pDevMode); Status = RegCreateKeyEx(HKEY_CURRENT_USER, szCurDevMode, 0, NULL, 0, KEY_WRITE, NULL, &hDevMode, NULL); if ( Status == ERROR_SUCCESS ) { Status = RegSetValueExW(hDevMode, pPrinterName, 0, REG_BINARY, (LPBYTE)pDevMode, pDevMode->dmSize + pDevMode->dmDriverExtra); RegCloseKey(hDevMode); } return Status == ERROR_SUCCESS; } LPDEVMODEW AllocateCurDevMode( HANDLE hPrinter, LPWSTR pDeviceName, LONG cbDevMode ) { LPDEVMODEW pDevMode=NULL; HANDLE hKeyDevMode; DWORD Status, Type; Status = RegCreateKeyEx(HKEY_CURRENT_USER, szCurDevMode, 0, NULL, 0, KEY_READ, NULL, &hKeyDevMode, NULL); if( Status == ERROR_SUCCESS ){ pDevMode = (PDEVMODEW)LocalAlloc(LMEM_FIXED, cbDevMode); if( pDevMode ){ Status = RegQueryValueExW(hKeyDevMode, pDeviceName, 0, &Type, (LPBYTE)pDevMode, &cbDevMode); if ( Status == ERROR_FILE_NOT_FOUND ) { if ( IDOK != DocumentPropertiesW(NULL, hPrinter, pDeviceName, pDevMode, NULL, DM_COPY) || !WriteCurDevModeToRegistry(pDeviceName, pDevMode) ) { LocalFree( pDevMode ); pDevMode = NULL; } } else if ( Status != ERROR_SUCCESS ) { LocalFree( pDevMode ); pDevMode = NULL; } } RegCloseKey(hKeyDevMode); } return pDevMode; } VOID MergeDevMode( LPDEVMODEW pDMOut, LPDEVMODEW pDMIn ) { // // Simply check each bit in the dmFields entry. If set, then copy // the input data to the output data. // if ( pDMIn->dmFields & DM_ORIENTATION ) { pDMOut->dmOrientation = pDMIn->dmOrientation; pDMOut->dmFields |= DM_ORIENTATION; } if( (pDMIn->dmFields & (DM_FORMNAME | DM_PAPERSIZE)) || (pDMIn->dmFields & (DM_PAPERLENGTH | DM_PAPERWIDTH)) == (DM_PAPERLENGTH | DM_PAPERWIDTH) ) { /* Value user fields, so use them. And delete ALL ours! */ pDMOut->dmFields &= ~(DM_FORMNAME | DM_PAPERSIZE | DM_PAPERLENGTH | DM_PAPERWIDTH); if( pDMIn->dmFields & DM_PAPERSIZE ) { pDMOut->dmPaperSize = pDMIn->dmPaperSize; pDMOut->dmFields |= DM_PAPERSIZE; } if( pDMIn->dmFields & DM_PAPERLENGTH ) { pDMOut->dmPaperLength = pDMIn->dmPaperLength; pDMOut->dmFields |= DM_PAPERLENGTH; } if( pDMIn->dmFields & DM_PAPERWIDTH ) { pDMOut->dmPaperWidth = pDMIn->dmPaperWidth; pDMOut->dmFields |= DM_PAPERWIDTH; } if( pDMIn->dmFields & DM_FORMNAME ) { CopyMemory( pDMOut->dmFormName, pDMIn->dmFormName, sizeof( pDMOut->dmFormName ) ); pDMOut->dmFields |= DM_FORMNAME; } } if( pDMIn->dmFields & DM_SCALE ) { pDMOut->dmScale = pDMIn->dmScale; pDMOut->dmFields |= DM_SCALE; } if ( pDMIn->dmFields & DM_COPIES ) { pDMOut->dmCopies = pDMIn->dmCopies; pDMOut->dmFields |= DM_COPIES; } if ( pDMIn->dmFields & DM_DEFAULTSOURCE ) { pDMOut->dmDefaultSource = pDMIn->dmDefaultSource; pDMOut->dmFields |= DM_DEFAULTSOURCE; } if ( pDMIn->dmFields & DM_PRINTQUALITY ) { pDMOut->dmPrintQuality = pDMIn->dmPrintQuality; pDMOut->dmFields |= DM_PRINTQUALITY; } if ( pDMIn->dmFields & DM_COLOR ) { pDMOut->dmColor = pDMIn->dmColor; pDMOut->dmFields |= DM_COLOR; } if ( pDMIn->dmFields & DM_DUPLEX ) { pDMOut->dmDuplex = pDMIn->dmDuplex; pDMOut->dmFields |= DM_DUPLEX; } if ( pDMIn->dmFields & DM_YRESOLUTION ) { /* * Note that DM_YRESOLUTION implies there is data in dmPrintQuality. * This latter field is used to specify the desired X resolution, * which is only required for dot matrix printers. */ pDMOut->dmYResolution = pDMIn->dmYResolution; pDMOut->dmPrintQuality = pDMIn->dmPrintQuality; pDMOut->dmFields |= DM_YRESOLUTION; } if ( pDMIn->dmFields & DM_TTOPTION ) { pDMOut->dmTTOption = pDMIn->dmTTOption; pDMOut->dmFields |= DM_TTOPTION; } if ( pDMIn->dmFields & DM_COLLATE ) { pDMOut->dmCollate = pDMIn->dmCollate; pDMOut->dmFields |= DM_COLLATE; } if ( pDMIn->dmFields & DM_ICMMETHOD ) { pDMOut->dmICMMethod = pDMIn->dmICMMethod; pDMOut->dmFields |= DM_ICMMETHOD; } if ( pDMIn->dmFields & DM_ICMINTENT ) { pDMOut->dmICMIntent = pDMIn->dmICMIntent; pDMOut->dmFields |= DM_ICMINTENT; } if ( pDMIn->dmFields & DM_MEDIATYPE ) { pDMOut->dmMediaType = pDMIn->dmMediaType; pDMOut->dmFields |= DM_MEDIATYPE; } if ( pDMIn->dmFields & DM_DITHERTYPE ) { pDMOut->dmDitherType = pDMIn->dmDitherType; pDMOut->dmFields |= DM_DITHERTYPE; } } LONG ExtDeviceMode( HWND hWnd, HANDLE hInst, LPDEVMODEA pDevModeOutput, LPSTR pDeviceName, LPSTR pPort, LPDEVMODEA pDevModeInput, LPSTR pProfile, DWORD fMode ) { HANDLE hPrinter = NULL; LONG cbDevMode; DWORD NewfMode; LPDEVMODEW pNewDevModeIn = NULL; LPDEVMODEW pNewDevModeOut = NULL, pTempDevMode = NULL; LONG ReturnValue = -1; PRINTER_DEFAULTSW PrinterDefaults={NULL, NULL, PRINTER_READ}; LPWSTR pUnicodeDeviceName; pUnicodeDeviceName = AllocateUnicodeString(pDeviceName); if (pDeviceName && !pUnicodeDeviceName) return ReturnValue; if (OpenPrinterW(pUnicodeDeviceName, &hPrinter, &PrinterDefaults)) { cbDevMode = DocumentPropertiesW(hWnd, hPrinter, pUnicodeDeviceName, NULL, NULL, 0); if (!fMode || cbDevMode <= 0) { ClosePrinter(hPrinter); FreeUnicodeString(pUnicodeDeviceName); if (!fMode) cbDevMode -= sizeof(DEVMODEW) - sizeof(DEVMODEA); return cbDevMode; } pNewDevModeOut = (PDEVMODEW)LocalAlloc( LMEM_FIXED, cbDevMode ); if( !pNewDevModeOut ){ ClosePrinter(hPrinter); FreeUnicodeString(pUnicodeDeviceName); return -1; } // // If our flags specify an input DevMode, and we have // an input devmode, use it. // if(( fMode & DM_IN_BUFFER ) && pDevModeInput ){ // // App may speicfy one or two fields in dmFields and expect us // to merge it with the global 16-bit devmode // pNewDevModeIn = AllocateCurDevMode(hPrinter, pUnicodeDeviceName, cbDevMode); pTempDevMode = AllocateUnicodeDevMode(pDevModeInput); if ( !pNewDevModeIn || !pTempDevMode ) { if ( pNewDevModeIn ) LocalFree(pNewDevModeIn); if ( pTempDevMode ) LocalFree(pTempDevMode); ClosePrinter(hPrinter); FreeUnicodeString(pUnicodeDeviceName); return -1; } // // Some apps will just set the public fields they want to be changed // from global devmode, so we need to merge input devmode with global // devmode // MergeDevMode(pNewDevModeIn, pTempDevMode); // // Copy input devmode's private section if present else send the // the private section from global devmode // if ( pTempDevMode->dmDriverExtra && pTempDevMode->dmDriverExtra == pNewDevModeIn->dmDriverExtra ) { CopyMemory((LPBYTE)pNewDevModeIn + pNewDevModeIn->dmSize, (LPBYTE)pTempDevMode + pTempDevMode->dmSize, pTempDevMode->dmDriverExtra); } LocalFree(pTempDevMode); pTempDevMode = NULL; } else { // // Get the win16 global devmode. // pNewDevModeIn = AllocateCurDevMode( hPrinter, pUnicodeDeviceName, cbDevMode ); if (!pNewDevModeIn) { ClosePrinter(hPrinter); FreeUnicodeString(pUnicodeDeviceName); return -1; } fMode |= DM_IN_BUFFER; } NewfMode = fMode; // // If DM_UPDATE is set, turn on DM_COPY so that we can update // the win16 devmode. // if (fMode & DM_UPDATE) NewfMode |= DM_COPY; ReturnValue = DocumentPropertiesW(hWnd, hPrinter, pUnicodeDeviceName, pNewDevModeOut, pNewDevModeIn, NewfMode); if ( ReturnValue == IDOK && (fMode & DM_UPDATE) ) { if ( WriteCurDevModeToRegistry(pUnicodeDeviceName, pNewDevModeOut) ) { SendNotifyMessageW(HWND_BROADCAST, WM_DEVMODECHANGE, 0, (LPARAM)pUnicodeDeviceName); } else { ReturnValue = -1; } } if (pNewDevModeIn) LocalFree(pNewDevModeIn); if ((ReturnValue == IDOK) && (fMode & DM_COPY) && pDevModeOutput) CopyAnsiDevModeFromUnicodeDevMode(pDevModeOutput, pNewDevModeOut); if (pNewDevModeOut) LocalFree(pNewDevModeOut); ClosePrinter(hPrinter); } FreeUnicodeString(pUnicodeDeviceName); return ReturnValue; } void DeviceMode( HWND hWnd, HANDLE hModule, LPSTR pDevice, LPSTR pPort ) { HANDLE hPrinter, hDevMode; DWORD cbDevMode; LPDEVMODEW pNewDevMode, pDevMode=NULL; PRINTER_DEFAULTSW PrinterDefaults={NULL, NULL, PRINTER_READ}; DWORD Status, Type, cb; LPWSTR pUnicodeDevice; pUnicodeDevice = AllocateUnicodeString(pDevice); if (pDevice && !pUnicodeDevice) return; if (OpenPrinterW(pUnicodeDevice, &hPrinter, &PrinterDefaults)) { Status = RegCreateKeyExW(HKEY_CURRENT_USER, szCurDevMode, 0, NULL, 0, KEY_WRITE | KEY_READ, NULL, &hDevMode, NULL); if (Status == ERROR_SUCCESS) { Status = RegQueryValueExW(hDevMode, pUnicodeDevice, 0, &Type, NULL, &cb); if (Status == ERROR_SUCCESS) { pDevMode = LocalAlloc(LMEM_FIXED, cb); if (pDevMode) { Status = RegQueryValueExW(hDevMode, pUnicodeDevice, 0, &Type, (LPBYTE)pDevMode, &cb); if (Status != ERROR_SUCCESS) { LocalFree(pDevMode); pDevMode = NULL; } } else { goto Cleanup; } } cbDevMode = DocumentPropertiesW(hWnd, hPrinter, pUnicodeDevice, NULL, pDevMode, 0); if (cbDevMode > 0) { if (pNewDevMode = (PDEVMODEW)LocalAlloc(LMEM_FIXED, cbDevMode)) { if (DocumentPropertiesW(hWnd, hPrinter, pUnicodeDevice, pNewDevMode, pDevMode, DM_COPY | DM_PROMPT | DM_MODIFY) == IDOK) { Status = RegSetValueExW(hDevMode, pUnicodeDevice, 0, REG_BINARY, (LPBYTE)pNewDevMode, pNewDevMode->dmSize + pNewDevMode->dmDriverExtra); if (Status == ERROR_SUCCESS) { // Whew, we made it, simply fall out } } LocalFree(pNewDevMode); } } if (pDevMode) LocalFree(pDevMode); RegCloseKey(hDevMode); } ClosePrinter(hPrinter); } Cleanup: FreeUnicodeString(pUnicodeDevice); return; } LONG AdvancedDocumentPropertiesA( HWND hWnd, HANDLE hPrinter, LPSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput ) { LONG ReturnValue = FALSE; LPWSTR pUnicodeDeviceName = NULL; LPDEVMODEW pUnicodeDevModeInput = NULL; LPDEVMODEW pUnicodeDevModeOutput = NULL; pUnicodeDeviceName = AllocateUnicodeString(pDeviceName); if (pDeviceName && !pUnicodeDeviceName) goto Cleanup; if( bValidDevModeA( pDevModeInput )){ pUnicodeDevModeInput = AllocateUnicodeDevMode(pDevModeInput); if( !pUnicodeDevModeInput ){ goto Cleanup; } } pUnicodeDevModeOutput = AllocateUnicodeDevMode(pDevModeOutput); if (pDevModeOutput && !pUnicodeDevModeOutput) goto Cleanup; ReturnValue = AdvancedDocumentPropertiesW(hWnd, hPrinter, pUnicodeDeviceName, pUnicodeDevModeOutput, pUnicodeDevModeInput ); CopyAnsiDevModeFromUnicodeDevMode(pDevModeOutput, pUnicodeDevModeOutput); if ( !pDevModeOutput && ReturnValue > 0 ) ReturnValue -= sizeof(DEVMODEW) - sizeof(DEVMODEA); Cleanup: if (pUnicodeDevModeOutput) LocalFree(pUnicodeDevModeOutput); if (pUnicodeDevModeInput) LocalFree(pUnicodeDevModeInput); FreeUnicodeString(pUnicodeDeviceName); return ReturnValue; } LONG AdvancedSetupDialog( HWND hWnd, HANDLE hInst, LPDEVMODEA pDevModeInput, LPDEVMODEA pDevModeOutput ) { HANDLE hPrinter; LONG ReturnValue = -1; if (OpenPrinterA(pDevModeInput->dmDeviceName, &hPrinter, NULL)) { ReturnValue = AdvancedDocumentPropertiesA(hWnd, hPrinter, pDevModeInput->dmDeviceName, pDevModeOutput, pDevModeInput); ClosePrinter(hPrinter); } return ReturnValue; } BOOL AddFormA( HANDLE hPrinter, DWORD Level, LPBYTE pForm ) { BOOL ReturnValue; LPBYTE pUnicodeForm; pUnicodeForm = AllocateUnicodeStructure(pForm, sizeof(FORM_INFO_1A), FormInfo1Strings); if (pForm && !pUnicodeForm) return FALSE; ReturnValue = AddFormW(hPrinter, Level, pUnicodeForm); FreeUnicodeStructure(pUnicodeForm, FormInfo1Offsets); return ReturnValue; } BOOL DeleteFormA( HANDLE hPrinter, LPSTR pFormName ) { BOOL ReturnValue; LPWSTR pUnicodeFormName; pUnicodeFormName = AllocateUnicodeString(pFormName); if (pFormName && !pUnicodeFormName) return FALSE; ReturnValue = DeleteFormW(hPrinter, pUnicodeFormName); FreeUnicodeString(pUnicodeFormName); return ReturnValue; } BOOL GetFormA( HANDLE hPrinter, LPSTR pFormName, DWORD Level, LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded ) { BOOL ReturnValue; DWORD *pOffsets; LPWSTR pUnicodeFormName; switch (Level) { case 1: pOffsets = FormInfo1Strings; break; default: SetLastError(ERROR_INVALID_LEVEL); return FALSE; } pUnicodeFormName = AllocateUnicodeString(pFormName); if (pFormName && !pUnicodeFormName) return FALSE; ReturnValue = GetFormW(hPrinter, pUnicodeFormName, Level, pForm, cbBuf, pcbNeeded); if (ReturnValue && pForm) ConvertUnicodeToAnsiStrings(pForm, pOffsets); FreeUnicodeString(pUnicodeFormName); return ReturnValue; } BOOL SetFormA( HANDLE hPrinter, LPSTR pFormName, DWORD Level, LPBYTE pForm ) { BOOL ReturnValue = FALSE; LPWSTR pUnicodeFormName = NULL; LPBYTE pUnicodeForm = NULL; pUnicodeFormName = AllocateUnicodeString(pFormName); if (pFormName && !pUnicodeFormName) goto Cleanup; pUnicodeForm = AllocateUnicodeStructure(pForm, sizeof(FORM_INFO_1A), FormInfo1Strings); if (pForm && !pUnicodeForm) goto Cleanup; ReturnValue = SetFormW(hPrinter, pUnicodeFormName, Level, pUnicodeForm); Cleanup: FreeUnicodeString(pUnicodeFormName); FreeUnicodeStructure(pUnicodeForm, FormInfo1Offsets); return ReturnValue; } BOOL EnumFormsA( HANDLE hPrinter, DWORD Level, LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned ) { BOOL ReturnValue; DWORD cbStruct; DWORD *pOffsets; switch (Level) { case 1: pOffsets = FormInfo1Strings; cbStruct = sizeof(FORM_INFO_1); break; default: SetLastError(ERROR_INVALID_LEVEL); return FALSE; } ReturnValue = EnumFormsW(hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned); if (ReturnValue && pForm) { DWORD i=*pcReturned; while (i--) { ConvertUnicodeToAnsiStrings(pForm, pOffsets); pForm+=cbStruct; } } return ReturnValue; } BOOL EnumPortsA( LPSTR pName, DWORD Level, LPBYTE pPort, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned ) { BOOL ReturnValue = FALSE; DWORD cbStruct; DWORD *pOffsets; LPWSTR pUnicodeName = NULL; switch (Level) { case 1: pOffsets = PortInfo1Strings; cbStruct = sizeof(PORT_INFO_1); break; case 2: pOffsets = PortInfo2Strings; cbStruct = sizeof(PORT_INFO_2); break; default: SetLastError(ERROR_INVALID_LEVEL); return FALSE; } pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; ReturnValue = EnumPortsW(pUnicodeName, Level, pPort, cbBuf, pcbNeeded, pcReturned); if (ReturnValue && pPort) { DWORD i=*pcReturned; while (i--) { ConvertUnicodeToAnsiStrings(pPort, pOffsets); pPort+=cbStruct; } } Cleanup: FreeUnicodeString(pUnicodeName); return ReturnValue; } BOOL EnumMonitorsA( LPSTR pName, DWORD Level, LPBYTE pMonitor, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned ) { BOOL ReturnValue = FALSE; DWORD cbStruct; DWORD *pOffsets; LPWSTR pUnicodeName = NULL; switch (Level) { case 1: pOffsets = MonitorInfo1Strings; cbStruct = sizeof(MONITOR_INFO_1); break; case 2: pOffsets = MonitorInfo2Strings; cbStruct = sizeof(MONITOR_INFO_2); break; default: SetLastError(ERROR_INVALID_LEVEL); return FALSE; } pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; ReturnValue = EnumMonitorsW(pUnicodeName, Level, pMonitor, cbBuf, pcbNeeded, pcReturned); if (ReturnValue && pMonitor) { DWORD i=*pcReturned; while (i--) { ConvertUnicodeToAnsiStrings(pMonitor, pOffsets); pMonitor+=cbStruct; } } Cleanup: FreeUnicodeString(pUnicodeName); return ReturnValue; } BOOL AddPortA( LPSTR pName, HWND hWnd, LPSTR pMonitorName ) { LPWSTR pUnicodeName = NULL; LPWSTR pUnicodeMonitorName = NULL; DWORD ReturnValue = FALSE; pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; pUnicodeMonitorName = AllocateUnicodeString(pMonitorName); if (pMonitorName && !pUnicodeMonitorName) goto Cleanup; ReturnValue = KickoffThread(pUnicodeName, hWnd, pUnicodeMonitorName, (INT_FARPROC)RpcAddPort); Cleanup: FreeUnicodeString(pUnicodeName); FreeUnicodeString(pUnicodeMonitorName); return ReturnValue; } BOOL ConfigurePortA( LPSTR pName, HWND hWnd, LPSTR pPortName ) { LPWSTR pUnicodeName = NULL; LPWSTR pUnicodePortName = NULL; DWORD ReturnValue = FALSE; pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; pUnicodePortName = AllocateUnicodeString(pPortName); if (pPortName && !pUnicodePortName) goto Cleanup; ReturnValue = KickoffThread(pUnicodeName, hWnd, pUnicodePortName, (INT_FARPROC)RpcConfigurePort); Cleanup: FreeUnicodeString(pUnicodeName); FreeUnicodeString(pUnicodePortName); return ReturnValue; } BOOL DeletePortA( LPSTR pName, HWND hWnd, LPSTR pPortName ) { LPWSTR pUnicodeName = NULL; LPWSTR pUnicodePortName = NULL; DWORD ReturnValue = FALSE; pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; pUnicodePortName = AllocateUnicodeString(pPortName); if (pPortName && !pUnicodePortName) goto Cleanup; ReturnValue = KickoffThread(pUnicodeName, hWnd, pUnicodePortName, (INT_FARPROC)RpcDeletePort); Cleanup: FreeUnicodeString(pUnicodeName); FreeUnicodeString(pUnicodePortName); return ReturnValue; } DWORD PrinterMessageBoxA( HANDLE hPrinter, DWORD Error, HWND hWnd, LPSTR pText, LPSTR pCaption, DWORD dwType ) { DWORD ReturnValue=FALSE; LPWSTR pTextW = NULL; LPWSTR pCaptionW = NULL; pTextW = AllocateUnicodeString(pText); if (pText && !pTextW) goto Cleanup; pCaptionW = AllocateUnicodeString(pCaption); if (pCaption && !pCaptionW) goto Cleanup; ReturnValue = PrinterMessageBoxW(hPrinter, Error, hWnd, pTextW, pCaptionW, dwType); Cleanup: FreeUnicodeString(pTextW); FreeUnicodeString(pCaptionW); return ReturnValue; } int DeviceCapabilitiesA( LPCSTR pDevice, LPCSTR pPort, WORD fwCapability, LPSTR pOutput, CONST DEVMODEA *pDevMode ) { LPWSTR pDeviceW = NULL; LPWSTR pPortW = NULL; LPWSTR pOutputW = NULL; LPWSTR pKeepW = NULL; LPDEVMODEW pDevModeW = NULL; DWORD c, Size, cb; DWORD rc = (DWORD) -1; pDeviceW = AllocateUnicodeString((LPSTR)pDevice); if (pDevice && !pDeviceW) goto Cleanup; pPortW = AllocateUnicodeString((LPSTR)pPort); if (pPort && !pPortW) goto Cleanup; if( bValidDevModeA( pDevMode )){ pDevModeW = AllocateUnicodeDevMode((LPDEVMODEA)pDevMode); if( !pDevModeW ){ goto Cleanup; } } switch (fwCapability) { // These will require Unicode to Ansi conversion case DC_BINNAMES: case DC_FILEDEPENDENCIES: case DC_PAPERNAMES: if (pOutput) { cb = DeviceCapabilitiesW(pDeviceW, pPortW, fwCapability, NULL, pDevModeW); if (cb >= 0) { switch (fwCapability) { case DC_BINNAMES: cb *= 48; break; case DC_FILEDEPENDENCIES: case DC_PAPERNAMES: cb *= 128; break; } pOutputW = pKeepW = LocalAlloc(LPTR, cb); if (pKeepW) { c = rc = DeviceCapabilitiesW(pDeviceW, pPortW, fwCapability, pOutputW, pDevModeW); switch (fwCapability) { case DC_BINNAMES: Size = 24; break; case DC_FILEDEPENDENCIES: case DC_PAPERNAMES: Size = 64; break; } for (; c; c--) { UnicodeToAnsiString(pOutputW, pOutput, NULL_TERMINATED); pOutputW += Size; pOutput += Size; } LocalFree(pKeepW); } } } else { rc = DeviceCapabilitiesW(pDeviceW, pPortW, fwCapability, NULL, pDevModeW); } break; default: rc = DeviceCapabilitiesW(pDeviceW, pPortW, fwCapability, (LPWSTR)pOutput, pDevModeW); // // If the call to find size of public portion of devmode and // it was succesful adjust the size for UNICODE->ANSI conversion // if ( fwCapability == DC_SIZE && rc > 0 ) { rc -= sizeof(DEVMODEW) - sizeof(DEVMODEA); } } Cleanup: FreeUnicodeString(pDeviceW); FreeUnicodeString(pPortW); if (pDevModeW) LocalFree(pDevModeW); return rc; } BOOL AddMonitorA( LPSTR pName, DWORD Level, LPBYTE pMonitorInfo ) { BOOL ReturnValue=FALSE; DWORD cbStruct; LPWSTR pUnicodeName = NULL; LPBYTE pUnicodeStructure = NULL; LPDWORD pOffsets; switch (Level) { case 2: pOffsets = MonitorInfo2Strings; cbStruct = sizeof(MONITOR_INFO_2); break; default: SetLastError(ERROR_INVALID_LEVEL); return FALSE; } pUnicodeStructure = AllocateUnicodeStructure(pMonitorInfo, cbStruct, pOffsets); if (pMonitorInfo && !pUnicodeStructure) goto Cleanup; pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; if (pUnicodeStructure) { ReturnValue = AddMonitorW(pUnicodeName, Level, pUnicodeStructure); } Cleanup: FreeUnicodeStructure(pUnicodeStructure, pOffsets); FreeUnicodeString(pUnicodeName); return ReturnValue; } BOOL DeleteMonitorA( LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName ) { LPWSTR pUnicodeName = NULL; LPWSTR pUnicodeEnvironment = NULL; LPWSTR pUnicodeMonitorName = NULL; BOOL rc = FALSE; pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; pUnicodeEnvironment = AllocateUnicodeString(pEnvironment); if (pEnvironment && !pUnicodeEnvironment) goto Cleanup; pUnicodeMonitorName = AllocateUnicodeString(pMonitorName); if (pMonitorName && !pUnicodeMonitorName) goto Cleanup; rc = DeleteMonitorW(pUnicodeName, pUnicodeEnvironment, pUnicodeMonitorName); Cleanup: FreeUnicodeString(pUnicodeName); FreeUnicodeString(pUnicodeEnvironment); FreeUnicodeString(pUnicodeMonitorName); return rc; } BOOL DeletePrintProcessorA( LPSTR pName, LPSTR pEnvironment, LPSTR pPrintProcessorName ) { LPWSTR pUnicodeName = NULL; LPWSTR pUnicodeEnvironment = NULL; LPWSTR pUnicodePrintProcessorName = NULL; BOOL rc = FALSE; if (!pPrintProcessorName || !*pPrintProcessorName) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; pUnicodeEnvironment = AllocateUnicodeString(pEnvironment); if (pEnvironment && !pUnicodeEnvironment) goto Cleanup; pUnicodePrintProcessorName = AllocateUnicodeString(pPrintProcessorName); if (pPrintProcessorName && !pUnicodePrintProcessorName) goto Cleanup; rc = DeletePrintProcessorW(pUnicodeName, pUnicodeEnvironment, pUnicodePrintProcessorName); Cleanup: FreeUnicodeString(pUnicodeName); FreeUnicodeString(pUnicodeEnvironment); FreeUnicodeString(pUnicodePrintProcessorName); return rc; } BOOL AddPrintProvidorA( LPSTR pName, DWORD Level, LPBYTE pProvidorInfo ) { BOOL ReturnValue=FALSE; DWORD cbStruct; LPWSTR pUnicodeName = NULL; LPBYTE pUnicodeStructure = NULL; LPDWORD pOffsets; switch (Level) { case 1: pOffsets = ProvidorInfo1Strings; cbStruct = sizeof(PROVIDOR_INFO_1); break; default: SetLastError(ERROR_INVALID_LEVEL); return FALSE; } pUnicodeStructure = AllocateUnicodeStructure(pProvidorInfo, cbStruct, pOffsets); if (pProvidorInfo && !pUnicodeStructure) goto Cleanup; pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; if (pUnicodeStructure) { ReturnValue = AddPrintProvidorW(pUnicodeName, Level, pUnicodeStructure); } Cleanup: FreeUnicodeStructure(pUnicodeStructure, pOffsets); FreeUnicodeString(pUnicodeName); return ReturnValue; } BOOL DeletePrintProvidorA( LPSTR pName, LPSTR pEnvironment, LPSTR pPrintProvidorName ) { LPWSTR pUnicodeName = NULL; LPWSTR pUnicodeEnvironment = NULL; LPWSTR pUnicodePrintProvidorName = NULL; BOOL rc = FALSE; pUnicodeName = AllocateUnicodeString(pName); if (pName && !pUnicodeName) goto Cleanup; pUnicodeEnvironment = AllocateUnicodeString(pEnvironment); if (pEnvironment && !pUnicodeEnvironment) goto Cleanup; pUnicodePrintProvidorName = AllocateUnicodeString(pPrintProvidorName); if (pPrintProvidorName && !pUnicodePrintProvidorName) goto Cleanup; rc = DeletePrintProvidorW(pUnicodeName, pUnicodeEnvironment, pUnicodePrintProvidorName); Cleanup: FreeUnicodeString(pUnicodeName); FreeUnicodeString(pUnicodeEnvironment); FreeUnicodeString(pUnicodePrintProvidorName); return rc; } BOOL AddPortExA( IN LPSTR pName, OPTIONAL IN DWORD Level, IN LPBYTE pBuffer, IN LPSTR pMonitorName ) { PPORT_INFO_1A pPortInfo1; PPORT_INFO_FFA pPortInfoFF; LPWSTR pNameW = NULL; LPWSTR pMonitorNameW = NULL; LPWSTR pPortNameW = NULL; PORT_INFO_1W PortInfo1; PORT_INFO_FFW PortInfoFF; DWORD LastError = ERROR_SUCCESS; BOOL bReturnValue = FALSE; // // Initialize variables that will be freed in error cases. // pNameW = AllocateUnicodeString( pName); if (pName && !pNameW) { LastError = GetLastError(); goto Done; } pPortNameW = NULL; pMonitorNameW = AllocateUnicodeString( pMonitorName); if (pMonitorName && !pMonitorNameW) { LastError = GetLastError(); goto Done; } if( !pBuffer || !pMonitorName ){ LastError = ERROR_INVALID_PARAMETER; goto Done; } // // Catch out of memory conditions. // if( !pMonitorNameW || ( pName && !pNameW )){ LastError = GetLastError(); goto Done; } switch( Level ){ case (DWORD)-1: pPortInfoFF = (PPORT_INFO_FFA)pBuffer; if( !pPortInfoFF->pName || !pPortInfoFF->pName[0] ){ LastError = ERROR_INVALID_PARAMETER; goto Done; } pPortNameW = PortInfoFF.pName = AllocateUnicodeString( pPortInfoFF->pName); if( !pPortNameW ){ LastError = GetLastError(); goto Done; } PortInfoFF.cbMonitorData = pPortInfoFF->cbMonitorData; PortInfoFF.pMonitorData = pPortInfoFF->pMonitorData; bReturnValue = AddPortExW( pNameW, Level, (LPBYTE)&PortInfoFF, pMonitorNameW ); if( !bReturnValue ){ LastError = GetLastError(); } break; case 1: pPortInfo1 = (PPORT_INFO_1A)pBuffer; if( !pPortInfo1->pName || !pPortInfo1->pName[0] ){ LastError = ERROR_INVALID_PARAMETER; goto Done; } pPortNameW = PortInfo1.pName = AllocateUnicodeString( pPortInfo1->pName); if( !pPortNameW ){ LastError = GetLastError(); goto Done; } bReturnValue = AddPortExW( pNameW, Level, (LPBYTE)&PortInfo1, pMonitorNameW ); if( !bReturnValue ){ LastError = GetLastError(); } break; default: LastError = ERROR_INVALID_LEVEL; break; } Done: FreeUnicodeString( pNameW ); FreeUnicodeString( pPortNameW ); FreeUnicodeString( pMonitorNameW ); if( !bReturnValue ){ SetLastError( LastError ); return FALSE; } return TRUE; } LPSTR StartDocDlgA( HANDLE hPrinter, DOCINFOA *pDocInfo ) { DOCINFOW DocInfoW; LPSTR lpszAnsiOutput = NULL; LPSTR lpszAnsiString = NULL; LPWSTR lpszUnicodeString = NULL; DWORD dwLen = 0; if (!pDocInfo) { DBGMSG(DBG_WARNING, ("StartDocDlgA: Null pDocInfo passed in\n")); return NULL; } memset(&DocInfoW, 0, sizeof(DOCINFOW)); if (pDocInfo->lpszDocName) { DocInfoW.lpszDocName = (LPCWSTR)AllocateUnicodeString ((LPSTR)pDocInfo->lpszDocName); if (pDocInfo->lpszDocName && !DocInfoW.lpszDocName) return NULL; } if (pDocInfo->lpszOutput) { DocInfoW.lpszOutput = (LPCWSTR)AllocateUnicodeString((LPSTR)pDocInfo->lpszOutput); if (pDocInfo->lpszOutput && !DocInfoW.lpszOutput) { FreeUnicodeString((LPWSTR) DocInfoW.lpszDocName); return NULL; } } lpszUnicodeString = StartDocDlgW(hPrinter, &DocInfoW); if (lpszUnicodeString == (LPWSTR)-1) { lpszAnsiString = (LPSTR)-1; } else if (lpszUnicodeString == (LPWSTR)-2) { lpszAnsiString = (LPSTR)-2; } else if (lpszUnicodeString){ dwLen = wcslen(lpszUnicodeString); if (lpszAnsiString = LocalAlloc(LPTR, dwLen+1)){ UnicodeToAnsiString(lpszUnicodeString, lpszAnsiString, dwLen); LocalFree(lpszUnicodeString); } else { DBGMSG(DBG_WARNING, ("StartDocDlgA: LocalAlloc failed returning NULL\n")); } } if (DocInfoW.lpszDocName ) { FreeUnicodeString((LPWSTR)DocInfoW.lpszDocName); } if (DocInfoW.lpszOutput) { // // we might have changed the DocInfoW.lpszOutput as well // for pooled printing; so reconstruct pDocInfo->lpszOutput // dwLen = wcslen(DocInfoW.lpszOutput); UnicodeToAnsiString((LPWSTR)DocInfoW.lpszOutput, (LPSTR)pDocInfo->lpszOutput, dwLen); FreeUnicodeString((LPWSTR)DocInfoW.lpszOutput); } return lpszAnsiString; } BOOL SetPortA( LPSTR pszName, LPSTR pszPortName, DWORD dwLevel, LPBYTE pPorts ) { LPBYTE pUnicodeStructure = NULL; DWORD cbStruct; DWORD *pOffsets; LPWSTR pszUnicodeName = NULL; LPWSTR pszUnicodePortName = NULL; BOOL bRet = FALSE; pszUnicodeName = AllocateUnicodeString(pszName); if (pszName && !pszUnicodeName) goto Cleanup; pszUnicodePortName = AllocateUnicodeString(pszPortName); if (pszPortName && !pszUnicodePortName) goto Cleanup; switch (dwLevel) { case 3: pOffsets = PortInfo3Offsets; cbStruct = sizeof(PORT_INFO_3); break; default: SetLastError( ERROR_INVALID_LEVEL ); return FALSE; } pUnicodeStructure = AllocateUnicodeStructure(pPorts, cbStruct, pOffsets); if (pPorts && !pUnicodeStructure) goto Cleanup; bRet = SetPortW(pszUnicodeName, pszUnicodePortName, dwLevel, pUnicodeStructure); Cleanup: FreeUnicodeStructure(pUnicodeStructure, pOffsets); FreeUnicodeString(pszUnicodePortName); FreeUnicodeString(pszUnicodeName); return bRet; } BOOL bValidDevModeA( const DEVMODEA *pDevModeA ) /*++ Routine Description: Check whether a devmode is valid to be RPC'd across to the spooler. Arguments: pDevMode - DevMode to check. Return Value: TRUE - Devmode can be RPC'd to spooler. FALSE - Invalid Devmode. --*/ { if( !pDevModeA ){ return FALSE; } if( pDevModeA->dmSize < MIN_DEVMODE_SIZEA ){ // // The only valid case is if pDevModeA is NULL. If it's // not NULL, then a bad devmode was passed in and the // app should fix it's code. // SPLASSERT( pDevModeA->dmSize >= MIN_DEVMODE_SIZEA ); return FALSE; } return TRUE; }