ReactOS 0.4.15-dev-8096-ga0eec98
printers.c File Reference
#include "precomp.h"
Include dependency graph for printers.c:

Go to the source code of this file.

Typedefs

typedef void(* PLocalGetPrinterLevelFunc) (PLOCAL_PRINTER, PVOID, PBYTE *, PDWORD, DWORD, PCWSTR)
 

Functions

_LocalEnumPrintersCheckName

Checks the Name parameter supplied to a call to EnumPrinters.

Parameters
FlagsFlags parameter of EnumPrinters.
NameName parameter of EnumPrinters to check.
pwszComputerNamePointer to a string able to hold 2 + MAX_COMPUTERNAME_LENGTH + 1 + 1 characters. On return, it may contain a computer name to prepend in EnumPrinters depending on the case.
pcchComputerNameIf a string to prepend is returned, this pointer receives its length in characters.
Returns
ERROR_SUCCESS if processing in EnumPrinters can be continued. ERROR_INVALID_NAME if the Name parameter is invalid for the given flags and this Print Provider. Any other error code if GetComputerNameW fails. Error codes indicating failure should then be returned by EnumPrinters.
static void _LocalGetPrinterLevel0 (PLOCAL_PRINTER pPrinter, PPRINTER_INFO_STRESS *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
 
static void _LocalGetPrinterLevel1 (PLOCAL_PRINTER pPrinter, PPRINTER_INFO_1W *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
 
static void _LocalGetPrinterLevel2 (PLOCAL_PRINTER pPrinter, PPRINTER_INFO_2W *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
 
static void _LocalGetPrinterLevel3 (PLOCAL_PRINTER pPrinter, PPRINTER_INFO_3 *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
 
static void _LocalGetPrinterLevel4 (PLOCAL_PRINTER pPrinter, PPRINTER_INFO_4W *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
 
static void _LocalGetPrinterLevel5 (PLOCAL_PRINTER pPrinter, PPRINTER_INFO_5W *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
 
static void _LocalGetPrinterLevel6 (PLOCAL_PRINTER pPrinter, PPRINTER_INFO_6 *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
 
static void _LocalGetPrinterLevel7 (PLOCAL_PRINTER pPrinter, PPRINTER_INFO_7W *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
 
static void _LocalGetPrinterLevel8 (PLOCAL_PRINTER pPrinter, PPRINTER_INFO_8W *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
 
static void _LocalGetPrinterLevel9 (PLOCAL_PRINTER pPrinter, PPRINTER_INFO_9W *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
 
static DWORD _LocalEnumPrintersCheckName (DWORD Flags, PCWSTR Name, PWSTR pwszComputerName, PDWORD pcchComputerName)
 
static DWORD _DumpLevel1PrintProviderInformation (PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
 
BOOL WINAPI LocalEnumPrinters (DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
 
BOOL WINAPI LocalGetPrinter (HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded)
 
static DWORD _LocalOpenPortHandle (PWSTR pwszPortName, PHANDLE phPrinter)
 
static DWORD _LocalOpenPrinterHandle (PWSTR pwszPrinterName, PWSTR pwszJobParameter, PHANDLE phPrinter, PPRINTER_DEFAULTSW pDefault)
 
static DWORD _LocalOpenPrintServerHandle (PHANDLE phPrinter)
 
static DWORD _LocalOpenXcvHandle (PWSTR pwszParameter, PHANDLE phPrinter)
 
DWORD WINAPI LocalPrinterMessageBox (HANDLE hPrinter, DWORD Error, HWND hWnd, LPWSTR pText, LPWSTR pCaption, DWORD dwType)
 
BOOL WINAPI LocalOpenPrinter (PWSTR lpPrinterName, HANDLE *phPrinter, PPRINTER_DEFAULTSW pDefault)
 
BOOL WINAPI LocalReadPrinter (HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
 
DWORD WINAPI LocalStartDocPrinter (HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
 
BOOL WINAPI LocalStartPagePrinter (HANDLE hPrinter)
 
BOOL WINAPI LocalWritePrinter (HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
 
BOOL WINAPI LocalEndPagePrinter (HANDLE hPrinter)
 
BOOL WINAPI LocalEndDocPrinter (HANDLE hPrinter)
 
static void _LocalClosePortHandle (PLOCAL_PORT_HANDLE pPortHandle)
 
static void _LocalClosePrinterHandle (PLOCAL_PRINTER_HANDLE pPrinterHandle)
 
static void _LocalCloseXcvHandle (PLOCAL_XCV_HANDLE pXcvHandle)
 
BOOL WINAPI LocalClosePrinter (HANDLE hPrinter)
 
_PrinterListCompareRoutine

SKIPLIST_COMPARE_ROUTINE for the Printer List. Does a case-insensitive comparison, because e.g. LocalOpenPrinter doesn't match the case when looking for Printers.

static int WINAPI _PrinterListCompareRoutine (PVOID FirstStruct, PVOID SecondStruct)
 
InitializePrinterList

Initializes a list of locally available Printers. The list is searchable by name and returns information about the printers, including their job queues. During this process, the job queues are also initialized.

BOOL InitializePrinterList (VOID)
 
VOID BroadcastChange (PLOCAL_HANDLE pHandle)
 

Variables

SKIPLIST PrinterList
 
static const PLocalGetPrinterLevelFunc pfnGetPrinterLevels []
 
static DWORD dwPrinterInfo0Offsets []
 
static DWORD dwPrinterInfo1Offsets []
 
static DWORD dwPrinterInfo2Offsets []
 
static DWORD dwPrinterInfo4Offsets []
 
static DWORD dwPrinterInfo5Offsets []
 
static const DWORD dwDeviceNotSelectedTimeout = 15000
 
static const DWORD dwTransmissionRetryTimeout = 45000
 

Typedef Documentation

◆ PLocalGetPrinterLevelFunc

typedef void(* PLocalGetPrinterLevelFunc) (PLOCAL_PRINTER, PVOID, PBYTE *, PDWORD, DWORD, PCWSTR)

Definition at line 26 of file printers.c.

Function Documentation

◆ _DumpLevel1PrintProviderInformation()

static DWORD _DumpLevel1PrintProviderInformation ( PBYTE  pPrinterEnum,
DWORD  cbBuf,
PDWORD  pcbNeeded,
PDWORD  pcReturned 
)
static

Definition at line 486 of file printers.c.

487{
488 int i;
489
490 // Count the needed bytes for Print Provider information.
491 *pcbNeeded = sizeof(PRINTER_INFO_1W);
492
493 for (i = 0; i < 3; i++)
494 *pcbNeeded += (wcslen(wszPrintProviderInfo[i]) + 1) * sizeof(WCHAR);
495
496 // Check if the supplied buffer is large enough.
497 if (cbBuf < *pcbNeeded)
499
500 // Copy over the Print Provider information.
501 ((PPRINTER_INFO_1W)pPrinterEnum)->Flags = 0;
502 PackStrings(wszPrintProviderInfo, pPrinterEnum, dwPrinterInfo1Offsets, &pPrinterEnum[*pcbNeeded]);
503 *pcReturned = 1;
504
505 return ERROR_SUCCESS;
506}
PBYTE WINAPI PackStrings(PCWSTR *pSource, PBYTE pDest, const DWORD *DestOffsets, PBYTE pEnd)
Definition: tools.c:39
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define ERROR_SUCCESS
Definition: deptool.c:10
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
static DWORD dwPrinterInfo1Offsets[]
Definition: printers.c:46
PCWSTR wszPrintProviderInfo[3]
Definition: main.c:27
_In_ DWORD _Out_ PDWORD pcbNeeded
Definition: winddi.h:3828
struct _PRINTER_INFO_1W PRINTER_INFO_1W
struct _PRINTER_INFO_1W * PPRINTER_INFO_1W
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by LocalEnumPrinters().

◆ _LocalClosePortHandle()

static void _LocalClosePortHandle ( PLOCAL_PORT_HANDLE  pPortHandle)
static

Definition at line 1926 of file printers.c.

1927{
1928 FIXME("LocalClosePortHandle\n");
1929 // Call the monitor's ClosePort function.
1930 if (pPortHandle->pPort->pPrintMonitor->bIsLevel2)
1931 ((PMONITOR2)pPortHandle->pPort->pPrintMonitor->pMonitor)->pfnClosePort(pPortHandle->hPort);
1932 else
1933 ((LPMONITOREX)pPortHandle->pPort->pPrintMonitor->pMonitor)->Monitor.pfnClosePort(pPortHandle->hPort);
1934}
#define FIXME(fmt,...)
Definition: debug.h:114
struct _MONITOR2 * PMONITOR2
@ Monitor
Definition: video.h:270
PLOCAL_PORT pPort
Definition: precomp.h:183
PLOCAL_PRINT_MONITOR pPrintMonitor
Definition: precomp.h:91

Referenced by LocalClosePrinter().

◆ _LocalClosePrinterHandle()

static void _LocalClosePrinterHandle ( PLOCAL_PRINTER_HANDLE  pPrinterHandle)
static

Definition at line 1937 of file printers.c.

1938{
1939 FIXME("LocalClosePrinterHandle\n");
1940 // Terminate any started job.
1941 if (pPrinterHandle->pJob)
1942 FreeJob(pPrinterHandle->pJob);
1943
1944 // Free memory for the fields.
1945 DllFreeSplMem(pPrinterHandle->pDevMode);
1946 DllFreeSplStr(pPrinterHandle->pwszDatatype);
1947}
void FreeJob(PLOCAL_JOB pJob)
Definition: jobs.c:1452
PLOCAL_JOB pJob
Definition: precomp.h:172
PDEVMODEW pDevMode
Definition: precomp.h:174
BOOL WINAPI DllFreeSplMem(PVOID pMem)
Definition: memory.c:112
BOOL WINAPI DllFreeSplStr(PWSTR pwszString)
Definition: memory.c:130

Referenced by LocalClosePrinter().

◆ _LocalCloseXcvHandle()

static void _LocalCloseXcvHandle ( PLOCAL_XCV_HANDLE  pXcvHandle)
static

Definition at line 1950 of file printers.c.

1951{
1952 // Call the monitor's XcvClosePort function.
1953 if (pXcvHandle->pPrintMonitor->bIsLevel2)
1954 ((PMONITOR2)pXcvHandle->pPrintMonitor->pMonitor)->pfnXcvClosePort(pXcvHandle->hXcv);
1955 else
1956 ((LPMONITOREX)pXcvHandle->pPrintMonitor->pMonitor)->Monitor.pfnXcvClosePort(pXcvHandle->hXcv);
1957}
PLOCAL_PRINT_MONITOR pPrintMonitor
Definition: precomp.h:192

Referenced by LocalClosePrinter().

◆ _LocalEnumPrintersCheckName()

static DWORD _LocalEnumPrintersCheckName ( DWORD  Flags,
PCWSTR  Name,
PWSTR  pwszComputerName,
PDWORD  pcchComputerName 
)
static

Definition at line 391 of file printers.c.

392{
394 PCWSTR pComputerName;
395
396 // If there is no Name parameter to check, we can just continue in EnumPrinters.
397 if (!Name)
398 return ERROR_SUCCESS;
399
400 // Check if Name does not begin with two backslashes (required for specifying Computer Names).
401 if (Name[0] != L'\\' || Name[1] != L'\\')
402 {
404 {
405 // If PRINTER_ENUM_NAME is specified, any given Name parameter may only contain the
406 // Print Provider Name or the local Computer Name.
407
408 // Compare with the Print Provider Name.
409 if (wcsicmp(Name, wszPrintProviderInfo[0]) == 0)
410 return ERROR_SUCCESS;
411
412 // Dismiss anything else.
413 return ERROR_INVALID_NAME;
414 }
415 else
416 {
417 // If PRINTER_ENUM_NAME is not specified, we just ignore anything that is not a Computer Name.
418 return ERROR_SUCCESS;
419 }
420 }
421
422 // Prepend the backslashes to the output computer name.
423 pwszComputerName[0] = L'\\';
424 pwszComputerName[1] = L'\\';
425
426 // Get the local computer name for comparison.
427 *pcchComputerName = MAX_COMPUTERNAME_LENGTH + 1;
428 if (!GetComputerNameW(&pwszComputerName[2], pcchComputerName))
429 {
430 ERR("GetComputerNameW failed with error %lu!\n", GetLastError());
431 return GetLastError();
432 }
433
434 // Add the leading slashes to the total length.
435 *pcchComputerName += 2;
436
437 // Compare both names.
438 pComputerName = &pwszComputerName[2];
439 pName = &Name[2];
440 for (;;)
441 {
442 // Are we at the end of the local Computer Name string?
443 if (!*pComputerName)
444 {
445 // Are we also at the end of the supplied Name parameter?
446 // A terminating NUL character and a backslash are both treated as the end, but they are treated differently.
447 if (!*pName)
448 {
449 // If both names match and Name ends with a NUL character, the computer name will be prepended in EnumPrinters.
450 // Add a trailing backslash for that.
451 pwszComputerName[(*pcchComputerName)++] = L'\\';
452 pwszComputerName[*pcchComputerName] = 0;
453 return ERROR_SUCCESS;
454 }
455 else if (*pName == L'\\')
456 {
458 {
459 // If PRINTER_ENUM_NAME is specified and a Name parameter is given, it must be exactly the local
460 // Computer Name with two backslashes prepended. Anything else (like "\\COMPUTERNAME\") is dismissed.
461 return ERROR_INVALID_NAME;
462 }
463 else
464 {
465 // If PRINTER_ENUM_NAME is not specified and a Name parameter is given, it may also end with a backslash.
466 // Only the Computer Name between the backslashes is checked then.
467 // This is largely undocumented, but verified by tests (see winspool_apitest).
468 // In this case, no computer name is prepended in EnumPrinters though.
469 *pwszComputerName = 0;
470 *pcchComputerName = 0;
471 return ERROR_SUCCESS;
472 }
473 }
474 }
475
476 // Compare both Computer Names case-insensitively and reject with ERROR_INVALID_NAME if they don't match.
477 if (towlower(*pName) != towlower(*pComputerName))
478 return ERROR_INVALID_NAME;
479
480 pName++;
481 pComputerName++;
482 }
483}
#define ERR(fmt,...)
Definition: debug.h:113
BOOL WINAPI GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
Definition: compname.c:446
#define ERROR_INVALID_NAME
Definition: compat.h:103
#define wcsicmp
Definition: compat.h:15
static LPSTR pName
Definition: security.c:75
#define L(x)
Definition: ntvdm.h:50
#define towlower(c)
Definition: wctype.h:97
const uint16_t * PCWSTR
Definition: typedefs.h:57
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define MAX_COMPUTERNAME_LENGTH
Definition: winbase.h:243
#define PRINTER_ENUM_NAME
Definition: winspool.h:899
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170

Referenced by LocalEnumPrinters().

◆ _LocalGetPrinterLevel0()

static void _LocalGetPrinterLevel0 ( PLOCAL_PRINTER  pPrinter,
PPRINTER_INFO_STRESS ppPrinterInfo,
PBYTE ppPrinterInfoEnd,
PDWORD  pcbNeeded,
DWORD  cchComputerName,
PCWSTR  wszComputerName 
)
static

Definition at line 509 of file printers.c.

510{
511 size_t cbName;
513 PCWSTR pwszStrings[1];
514 SYSTEM_INFO SystemInfo;
515
516 // Calculate the string lengths.
517 cbName = (cchComputerName + wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
518
519 if (!ppPrinterInfo)
520 {
521 *pcbNeeded += sizeof(PRINTER_INFO_STRESS) + cbName;
522 return;
523 }
524
525 // Set the general fields.
526 ZeroMemory(*ppPrinterInfo, sizeof(PRINTER_INFO_STRESS));
527 (*ppPrinterInfo)->cJobs = pPrinter->JobList.NodeCount;
528 (*ppPrinterInfo)->dwGetVersion = GetVersion();
529 (*ppPrinterInfo)->Status = pPrinter->dwStatus;
530
531#if !DBG
532 (*ppPrinterInfo)->fFreeBuild = 1;
533#endif
534
535 GetSystemInfo(&SystemInfo);
536 (*ppPrinterInfo)->dwNumberOfProcessors = SystemInfo.dwNumberOfProcessors;
537 (*ppPrinterInfo)->dwProcessorType = SystemInfo.dwProcessorType;
538 (*ppPrinterInfo)->wProcessorArchitecture = SystemInfo.wProcessorArchitecture;
539 (*ppPrinterInfo)->wProcessorLevel = SystemInfo.wProcessorLevel;
540
541 // Copy the Printer Name.
542 p = Allocation = DllAllocSplMem(cbName);
543 pwszStrings[0] = Allocation;
544 StringCbCopyExW(p, cbName, wszComputerName, &p, &cbName, 0);
545 StringCbCopyExW(p, cbName, pPrinter->pwszPrinterName, &p, &cbName, 0);
546
547 // Finally copy the structure and advance to the next one in the output buffer.
548 *ppPrinterInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppPrinterInfo), dwPrinterInfo0Offsets, *ppPrinterInfoEnd);
549 (*ppPrinterInfo)++;
550
551 // Free the memory for temporary strings.
553}
VOID WINAPI GetSystemInfo(IN LPSYSTEM_INFO lpSystemInfo)
Definition: sysinfo.c:143
GLfloat GLfloat p
Definition: glext.h:8902
BYTE * PBYTE
Definition: pedump.c:66
static DWORD dwPrinterInfo0Offsets[]
Definition: printers.c:41
DWORD WINAPI GetVersion()
Definition: redirtest.c:5
struct _PRINTER_INFO_STRESS PRINTER_INFO_STRESS
STRSAFEAPI StringCbCopyExW(STRSAFE_LPWSTR pszDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcbRemaining, STRSAFE_DWORD dwFlags)
Definition: strsafe.h:210
PWSTR pwszPrinterName
Definition: precomp.h:119
SKIPLIST JobList
Definition: precomp.h:130
DWORD dwStatus
Definition: precomp.h:122
DWORD NodeCount
Definition: skiplist.h:39
DWORD dwNumberOfProcessors
Definition: winbase.h:1177
WORD wProcessorLevel
Definition: winbase.h:1180
DWORD dwProcessorType
Definition: winbase.h:1178
WORD wProcessorArchitecture
Definition: winbase.h:1169
uint16_t * PWSTR
Definition: typedefs.h:56
PVOID WINAPI DllAllocSplMem(DWORD dwBytes)
Definition: memory.c:95
#define ZeroMemory
Definition: winbase.h:1712
Allocation
Definition: exfuncs.h:598

◆ _LocalGetPrinterLevel1()

static void _LocalGetPrinterLevel1 ( PLOCAL_PRINTER  pPrinter,
PPRINTER_INFO_1W ppPrinterInfo,
PBYTE ppPrinterInfoEnd,
PDWORD  pcbNeeded,
DWORD  cchComputerName,
PCWSTR  wszComputerName 
)
static

Definition at line 556 of file printers.c.

557{
558 const WCHAR wszComma[] = L",";
559
560 size_t cbName;
561 size_t cbComment;
562 size_t cbDescription;
563 PWSTR p, Allocation1, Allocation2;
564 PCWSTR pwszStrings[3];
565
566 // Calculate the string lengths.
567 // Attention: pComment equals the "Description" registry value while pDescription is concatenated out of several strings.
568 // On top of this, the computer name is prepended to the printer name if the user supplied the local computer name during the query.
569 cbName = (cchComputerName + wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
570 cbComment = (wcslen(pPrinter->pwszDescription) + 1) * sizeof(WCHAR);
571 cbDescription = cbName + (wcslen(pPrinter->pwszPrinterDriver) + 1 + wcslen(pPrinter->pwszLocation) + 1) * sizeof(WCHAR);
572
573 if (!ppPrinterInfo)
574 {
575 *pcbNeeded += sizeof(PRINTER_INFO_1W) + cbName + cbComment + cbDescription;
576 return;
577 }
578
579 // Indicate that this is a Printer.
580 (*ppPrinterInfo)->Flags = PRINTER_ENUM_ICON8;
581
582 // Copy the Printer Name.
583 p = Allocation1 = DllAllocSplMem(cbName);
584 pwszStrings[0] = Allocation1;
585 StringCbCopyExW(p, cbName, wszComputerName, &p, &cbName, 0);
586 StringCbCopyExW(p, cbName, pPrinter->pwszPrinterName, &p, &cbName, 0);
587
588 // Copy the Printer comment (equals the "Description" registry value).
589 pwszStrings[1] = pPrinter->pwszDescription;
590
591 // Copy the description, which for PRINTER_INFO_1W has the form "Name,Printer Driver,Location"
592 p = Allocation2 = DllAllocSplMem(cbDescription);
593 pwszStrings[2] = Allocation2;
594 StringCbCopyExW(p, cbDescription, wszComputerName, &p, &cbDescription, 0);
595 StringCbCopyExW(p, cbDescription, pPrinter->pwszPrinterName, &p, &cbDescription, 0);
596 StringCbCopyExW(p, cbDescription, wszComma, &p, &cbDescription, 0);
597 StringCbCopyExW(p, cbDescription, pPrinter->pwszPrinterDriver, &p, &cbDescription, 0);
598 StringCbCopyExW(p, cbDescription, wszComma, &p, &cbDescription, 0);
599 StringCbCopyExW(p, cbDescription, pPrinter->pwszLocation, &p, &cbDescription, 0);
600
601 // Finally copy the structure and advance to the next one in the output buffer.
602 *ppPrinterInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppPrinterInfo), dwPrinterInfo1Offsets, *ppPrinterInfoEnd);
603 (*ppPrinterInfo)++;
604
605 // Free the memory for temporary strings.
606 DllFreeSplMem(Allocation1);
607 DllFreeSplMem(Allocation2);
608}
PWSTR pwszPrinterDriver
Definition: precomp.h:124
PWSTR pwszLocation
Definition: precomp.h:123
PWSTR pwszDescription
Definition: precomp.h:125
#define PRINTER_ENUM_ICON8
Definition: winspool.h:915

◆ _LocalGetPrinterLevel2()

static void _LocalGetPrinterLevel2 ( PLOCAL_PRINTER  pPrinter,
PPRINTER_INFO_2W ppPrinterInfo,
PBYTE ppPrinterInfoEnd,
PDWORD  pcbNeeded,
DWORD  cchComputerName,
PCWSTR  wszComputerName 
)
static

Definition at line 611 of file printers.c.

612{
613 WCHAR wszEmpty[] = L"";
614
615 size_t cbDevMode;
616 size_t cbPrinterName;
617 size_t cbShareName;
618 size_t cbPortName;
619 size_t cbDriverName;
620 size_t cbComment;
621 size_t cbLocation;
622 size_t cbSepFile;
623 size_t cbPrintProcessor;
624 size_t cbDatatype;
625 size_t cbParameters;
627 PCWSTR pwszStrings[10];
628 FIXME("LocalGetPrinterLevel2\n");
629 // Calculate the string lengths.
630 cbDevMode = pPrinter->pDefaultDevMode->dmSize + pPrinter->pDefaultDevMode->dmDriverExtra;
631 cbPrinterName = (cchComputerName + wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
632
633 if (!ppPrinterInfo)
634 {
635 // Attention: pComment equals the "Description" registry value.
636 cbShareName = sizeof(wszEmpty);
637 cbPortName = (wcslen(pPrinter->pPort->pwszName) + 1) * sizeof(WCHAR);
638 cbDriverName = (wcslen(pPrinter->pwszPrinterDriver) + 1) * sizeof(WCHAR);
639 cbComment = (wcslen(pPrinter->pwszDescription) + 1) * sizeof(WCHAR);
640 cbLocation = (wcslen(pPrinter->pwszLocation) + 1) * sizeof(WCHAR);
641 cbSepFile = sizeof(wszEmpty);
642 cbPrintProcessor = (wcslen(pPrinter->pPrintProcessor->pwszName) + 1) * sizeof(WCHAR);
643 cbDatatype = (wcslen(pPrinter->pwszDefaultDatatype) + 1) * sizeof(WCHAR);
644 cbParameters = sizeof(wszEmpty);
645
646 *pcbNeeded += sizeof(PRINTER_INFO_2W) + cbDevMode + cbPrinterName + cbShareName + cbPortName + cbDriverName + cbComment + cbLocation + cbSepFile + cbPrintProcessor + cbDatatype + cbParameters;
647 FIXME("LocalGetPrinterLevel2 Needed %d\n",*pcbNeeded);
648 return;
649 }
650
651 // Set the general fields.
652 ZeroMemory(*ppPrinterInfo, sizeof(PRINTER_INFO_2W));
653 (*ppPrinterInfo)->Attributes = pPrinter->dwAttributes;
654 (*ppPrinterInfo)->cJobs = pPrinter->JobList.NodeCount;
655 (*ppPrinterInfo)->Status = pPrinter->dwStatus;
656
657 // Set the pDevMode field (and copy the DevMode).
658 *ppPrinterInfoEnd -= cbDevMode;
659 CopyMemory(*ppPrinterInfoEnd, pPrinter->pDefaultDevMode, cbDevMode);
660 (*ppPrinterInfo)->pDevMode = (PDEVMODEW)(*ppPrinterInfoEnd);
661
662 // Set the pPrinterName field.
663 p = Allocation = DllAllocSplMem(cbPrinterName);
664 pwszStrings[0] = Allocation;
665 StringCbCopyExW(p, cbPrinterName, wszComputerName, &p, &cbPrinterName, 0);
666 StringCbCopyExW(p, cbPrinterName, pPrinter->pwszPrinterName, &p, &cbPrinterName, 0);
667
668 // Set the pShareName field.
669 pwszStrings[1] = wszEmpty;
670
671 // Set the pPortName field.
672 pwszStrings[2] = pPrinter->pPort->pwszName;
673
674 // Set the pDriverName field.
675 pwszStrings[3] = pPrinter->pwszPrinterDriver;
676
677 // Set the pComment field ((equals the "Description" registry value).
678 pwszStrings[4] = pPrinter->pwszDescription;
679
680 // Set the pLocation field.
681 pwszStrings[5] = pPrinter->pwszLocation;
682
683 // Set the pSepFile field.
684 pwszStrings[6] = wszEmpty;
685
686 // Set the pPrintProcessor field.
687 pwszStrings[7] = pPrinter->pPrintProcessor->pwszName;
688
689 // Set the pDatatype field.
690 pwszStrings[8] = pPrinter->pwszDefaultDatatype;
691
692 // Set the pParameters field.
693 pwszStrings[9] = wszEmpty;
694
695 // Finally copy the structure and advance to the next one in the output buffer.
696 *ppPrinterInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppPrinterInfo), dwPrinterInfo2Offsets, *ppPrinterInfoEnd);
697 (*ppPrinterInfo)++;
698
699 // Free the memory for temporary strings.
701}
static const WCHAR wszEmpty[]
Definition: misc.c:327
static DWORD dwPrinterInfo2Offsets[]
Definition: printers.c:53
PWSTR pwszName
Definition: precomp.h:90
PWSTR pwszDefaultDatatype
Definition: precomp.h:126
PLOCAL_PORT pPort
Definition: precomp.h:129
DWORD dwAttributes
Definition: precomp.h:121
PLOCAL_PRINT_PROCESSOR pPrintProcessor
Definition: precomp.h:128
PDEVMODEW pDefaultDevMode
Definition: precomp.h:127
WORD dmDriverExtra
Definition: wingdi.h:1621
WORD dmSize
Definition: wingdi.h:1620
#define CopyMemory
Definition: winbase.h:1710
struct _devicemodeW * PDEVMODEW
struct _PRINTER_INFO_2W PRINTER_INFO_2W

◆ _LocalGetPrinterLevel3()

static void _LocalGetPrinterLevel3 ( PLOCAL_PRINTER  pPrinter,
PPRINTER_INFO_3 ppPrinterInfo,
PBYTE ppPrinterInfoEnd,
PDWORD  pcbNeeded,
DWORD  cchComputerName,
PCWSTR  wszComputerName 
)
static

Definition at line 704 of file printers.c.

705{
707
708 if (!ppPrinterInfo)
709 {
710 *pcbNeeded += sizeof(PRINTER_INFO_3) + sizeof(SECURITY_DESCRIPTOR);
711 return;
712 }
713
714 FIXME("Return a valid security descriptor for PRINTER_INFO_3\n");
715
716 // Set the pSecurityDescriptor field (and copy the Security Descriptor).
717 *ppPrinterInfoEnd -= sizeof(SECURITY_DESCRIPTOR);
718 CopyMemory(*ppPrinterInfoEnd, &SecurityDescriptor, sizeof(SECURITY_DESCRIPTOR));
719 (*ppPrinterInfo)->pSecurityDescriptor = (PSECURITY_DESCRIPTOR)(*ppPrinterInfoEnd);
720
721 // Advance to the next structure.
722 (*ppPrinterInfo)++;
723}
struct _SECURITY_DESCRIPTOR * PSECURITY_DESCRIPTOR
Definition: security.c:98
struct _SECURITY_DESCRIPTOR SECURITY_DESCRIPTOR
struct _PRINTER_INFO_3 PRINTER_INFO_3
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH _In_opt_ PEPROCESS _In_opt_ PETHREAD _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor
Definition: wsk.h:191

◆ _LocalGetPrinterLevel4()

static void _LocalGetPrinterLevel4 ( PLOCAL_PRINTER  pPrinter,
PPRINTER_INFO_4W ppPrinterInfo,
PBYTE ppPrinterInfoEnd,
PDWORD  pcbNeeded,
DWORD  cchComputerName,
PCWSTR  wszComputerName 
)
static

Definition at line 726 of file printers.c.

727{
728 size_t cbPrinterName;
730 PCWSTR pwszStrings[1];
731
732 // Calculate the string lengths.
733 cbPrinterName = (cchComputerName + wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
734
735 if (!ppPrinterInfo)
736 {
737 *pcbNeeded += sizeof(PRINTER_INFO_4W) + cbPrinterName;
738 return;
739 }
740
741 // Set the general fields.
742 (*ppPrinterInfo)->pServerName = NULL;
743 (*ppPrinterInfo)->Attributes = pPrinter->dwAttributes;
744
745 // Set the pPrinterName field.
746 p = Allocation = DllAllocSplMem(cbPrinterName);
747 pwszStrings[0] = Allocation;
748 StringCbCopyExW(p, cbPrinterName, wszComputerName, &p, &cbPrinterName, 0);
749 StringCbCopyExW(p, cbPrinterName, pPrinter->pwszPrinterName, &p, &cbPrinterName, 0);
750
751 // Finally copy the structure and advance to the next one in the output buffer.
752 *ppPrinterInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppPrinterInfo), dwPrinterInfo4Offsets, *ppPrinterInfoEnd);
753 (*ppPrinterInfo)++;
754
755 // Free the memory for temporary strings.
757}
#define NULL
Definition: types.h:112
static DWORD dwPrinterInfo4Offsets[]
Definition: printers.c:67
struct _PRINTER_INFO_4W PRINTER_INFO_4W

◆ _LocalGetPrinterLevel5()

static void _LocalGetPrinterLevel5 ( PLOCAL_PRINTER  pPrinter,
PPRINTER_INFO_5W ppPrinterInfo,
PBYTE ppPrinterInfoEnd,
PDWORD  pcbNeeded,
DWORD  cchComputerName,
PCWSTR  wszComputerName 
)
static

Definition at line 760 of file printers.c.

761{
762 size_t cbPrinterName;
763 size_t cbPortName;
765 PCWSTR pwszStrings[2];
766
767 // Calculate the string lengths.
768 cbPrinterName = (cchComputerName + wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
769
770 if (!ppPrinterInfo)
771 {
772 cbPortName = (wcslen(pPrinter->pPort->pwszName) + 1) * sizeof(WCHAR);
773
774 *pcbNeeded += sizeof(PRINTER_INFO_5W) + cbPrinterName + cbPortName;
775 return;
776 }
777
778 // Set the general fields.
779 (*ppPrinterInfo)->Attributes = pPrinter->dwAttributes;
780 (*ppPrinterInfo)->DeviceNotSelectedTimeout = dwDeviceNotSelectedTimeout;
781 (*ppPrinterInfo)->TransmissionRetryTimeout = dwTransmissionRetryTimeout;
782
783 // Set the pPrinterName field.
784 p = Allocation = DllAllocSplMem(cbPrinterName);
785 pwszStrings[0] = Allocation;
786 StringCbCopyExW(p, cbPrinterName, wszComputerName, &p, &cbPrinterName, 0);
787 StringCbCopyExW(p, cbPrinterName, pPrinter->pwszPrinterName, &p, &cbPrinterName, 0);
788
789 // Set the pPortName field.
790 pwszStrings[1] = pPrinter->pPort->pwszName;
791
792 // Finally copy the structure and advance to the next one in the output buffer.
793 *ppPrinterInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppPrinterInfo), dwPrinterInfo5Offsets, *ppPrinterInfoEnd);
794 (*ppPrinterInfo)++;
795
796 // Free the memory for temporary strings.
798}
static const DWORD dwTransmissionRetryTimeout
Definition: printers.c:81
static const DWORD dwDeviceNotSelectedTimeout
Definition: printers.c:80
static DWORD dwPrinterInfo5Offsets[]
Definition: printers.c:72
struct _PRINTER_INFO_5W PRINTER_INFO_5W

◆ _LocalGetPrinterLevel6()

static void _LocalGetPrinterLevel6 ( PLOCAL_PRINTER  pPrinter,
PPRINTER_INFO_6 ppPrinterInfo,
PBYTE ppPrinterInfoEnd,
PDWORD  pcbNeeded,
DWORD  cchComputerName,
PCWSTR  wszComputerName 
)
static

Definition at line 801 of file printers.c.

802{
803 if (!ppPrinterInfo)
804 {
805 *pcbNeeded += sizeof(PRINTER_INFO_6);
806 return;
807 }
808
809 // Set the general fields.
810 (*ppPrinterInfo)->dwStatus = pPrinter->dwStatus;
811
812 // Advance to the next structure.
813 (*ppPrinterInfo)++;
814}
struct _PRINTER_INFO_6 PRINTER_INFO_6

◆ _LocalGetPrinterLevel7()

static void _LocalGetPrinterLevel7 ( PLOCAL_PRINTER  pPrinter,
PPRINTER_INFO_7W ppPrinterInfo,
PBYTE ppPrinterInfoEnd,
PDWORD  pcbNeeded,
DWORD  cchComputerName,
PCWSTR  wszComputerName 
)
static

Definition at line 817 of file printers.c.

818{
819 if (!ppPrinterInfo)
820 {
821 *pcbNeeded += sizeof(PRINTER_INFO_7W);
822 return;
823 }
824
825 FIXME("No Directory Support, returning DSPRINT_UNPUBLISH for PRINTER_INFO_7 all the time!\n");
826
827 // Set the general fields.
828 (*ppPrinterInfo)->dwAction = DSPRINT_UNPUBLISH;
829 (*ppPrinterInfo)->pszObjectGUID = NULL;
830
831 // Advance to the next structure.
832 (*ppPrinterInfo)++;
833}
#define DSPRINT_UNPUBLISH
Definition: winspool.h:149
struct _PRINTER_INFO_7W PRINTER_INFO_7W

◆ _LocalGetPrinterLevel8()

static void _LocalGetPrinterLevel8 ( PLOCAL_PRINTER  pPrinter,
PPRINTER_INFO_8W ppPrinterInfo,
PBYTE ppPrinterInfoEnd,
PDWORD  pcbNeeded,
DWORD  cchComputerName,
PCWSTR  wszComputerName 
)
static

Definition at line 836 of file printers.c.

837{
838 DWORD cbDevMode;
839
840 // Calculate the string lengths.
841 cbDevMode = pPrinter->pDefaultDevMode->dmSize + pPrinter->pDefaultDevMode->dmDriverExtra;
842
843 if (!ppPrinterInfo)
844 {
845 *pcbNeeded += sizeof(PRINTER_INFO_8W) + cbDevMode;
846 return;
847 }
848
849 // Set the pDevMode field (and copy the DevMode).
850 *ppPrinterInfoEnd -= cbDevMode;
851 CopyMemory(*ppPrinterInfoEnd, pPrinter->pDefaultDevMode, cbDevMode);
852 (*ppPrinterInfo)->pDevMode = (PDEVMODEW)(*ppPrinterInfoEnd);
853
854 // Advance to the next structure.
855 (*ppPrinterInfo)++;
856}
unsigned long DWORD
Definition: ntddk_ex.h:95
struct _PRINTER_INFO_8W PRINTER_INFO_8W

◆ _LocalGetPrinterLevel9()

static void _LocalGetPrinterLevel9 ( PLOCAL_PRINTER  pPrinter,
PPRINTER_INFO_9W ppPrinterInfo,
PBYTE ppPrinterInfoEnd,
PDWORD  pcbNeeded,
DWORD  cchComputerName,
PCWSTR  wszComputerName 
)
static

Definition at line 859 of file printers.c.

860{
861 DWORD cbDevMode;
862
863 // Calculate the string lengths.
864 cbDevMode = pPrinter->pDefaultDevMode->dmSize + pPrinter->pDefaultDevMode->dmDriverExtra;
865
866 if (!ppPrinterInfo)
867 {
868 *pcbNeeded += sizeof(PRINTER_INFO_9W) + cbDevMode;
869 return;
870 }
871
872 FIXME("Per-user settings are not yet implemented, returning the global DevMode for PRINTER_INFO_9!\n");
873
874 // Set the pDevMode field (and copy the DevMode).
875 *ppPrinterInfoEnd -= cbDevMode;
876 CopyMemory(*ppPrinterInfoEnd, pPrinter->pDefaultDevMode, cbDevMode);
877 (*ppPrinterInfo)->pDevMode = (PDEVMODEW)(*ppPrinterInfoEnd);
878
879 // Advance to the next structure.
880 (*ppPrinterInfo)++;
881}
struct _PRINTER_INFO_9W PRINTER_INFO_9W

◆ _LocalOpenPortHandle()

static DWORD _LocalOpenPortHandle ( PWSTR  pwszPortName,
PHANDLE  phPrinter 
)
static

Definition at line 1043 of file printers.c.

1044{
1045 BOOL bReturnValue;
1046 DWORD dwErrorCode;
1047 HANDLE hPort;
1048 PLOCAL_HANDLE pHandle = NULL;
1049 PLOCAL_PORT pPort;
1050 PLOCAL_PORT_HANDLE pPortHandle = NULL;
1051 PLOCAL_PRINT_MONITOR pPrintMonitor;
1052
1053 // Look for this port in our Print Monitor Port list.
1054 pPort = FindPort(pwszPortName);
1055 if (!pPort)
1056 {
1057 // The supplied port is unknown to all our Print Monitors.
1058 dwErrorCode = ERROR_INVALID_NAME;
1059 goto Failure;
1060 }
1061
1062 pPrintMonitor = pPort->pPrintMonitor;
1063
1064 // Call the monitor's OpenPort function.
1065 if (pPrintMonitor->bIsLevel2)
1066 bReturnValue = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnOpenPort(pPrintMonitor->hMonitor, pwszPortName, &hPort);
1067 else
1068 bReturnValue = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnOpenPort(pwszPortName, &hPort);
1069
1070 if (!bReturnValue)
1071 {
1072 // The OpenPort function failed. Return its last error.
1073 dwErrorCode = GetLastError();
1074 goto Failure;
1075 }
1076
1077 // Create a new generic handle.
1078 pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE));
1079 if (!pHandle)
1080 {
1081 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1082 ERR("DllAllocSplMem failed!\n");
1083 goto Failure;
1084 }
1085
1086 // Create a new LOCAL_PORT_HANDLE.
1087 pPortHandle = DllAllocSplMem(sizeof(LOCAL_PORT_HANDLE));
1088 if (!pPortHandle)
1089 {
1090 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1091 ERR("DllAllocSplMem failed!\n");
1092 goto Failure;
1093 }
1094
1095 pPortHandle->hPort = hPort;
1096 pPortHandle->pPort = pPort;
1097
1098 // Make the generic handle a Port handle.
1099 pHandle->HandleType = HandleType_Port;
1100 pHandle->pSpecificHandle = pPortHandle;
1101
1102 // Return it.
1103 *phPrinter = (HANDLE)pHandle;
1104 return ERROR_SUCCESS;
1105
1106Failure:
1107 if (pHandle)
1108 DllFreeSplMem(pHandle);
1109
1110 if (pPortHandle)
1111 DllFreeSplMem(pPortHandle);
1112
1113 return dwErrorCode;
1114}
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
unsigned int BOOL
Definition: ntddk_ex.h:94
struct _MONITOREX * LPMONITOREX
enum _LOCAL_HANDLE::@5128 HandleType
PVOID pSpecificHandle
Definition: precomp.h:208
PVOID HANDLE
Definition: typedefs.h:73
PLOCAL_PORT FindPort(PCWSTR pwszName)
Definition: ports.c:15

Referenced by LocalOpenPrinter().

◆ _LocalOpenPrinterHandle()

static DWORD _LocalOpenPrinterHandle ( PWSTR  pwszPrinterName,
PWSTR  pwszJobParameter,
PHANDLE  phPrinter,
PPRINTER_DEFAULTSW  pDefault 
)
static

Definition at line 1117 of file printers.c.

1118{
1119 DWORD dwErrorCode;
1120 DWORD dwJobID;
1121 PLOCAL_HANDLE pHandle = NULL;
1122 PLOCAL_JOB pJob;
1123 PLOCAL_PRINTER pPrinter;
1124 PLOCAL_PRINTER_HANDLE pPrinterHandle = NULL;
1125 WCHAR wszFullPath[MAX_PATH];
1126
1127 // Retrieve the printer from the list.
1128 pPrinter = LookupElementSkiplist(&PrinterList, &pwszPrinterName, NULL);
1129 if (!pPrinter)
1130 {
1131 // The printer does not exist.
1132 dwErrorCode = ERROR_INVALID_NAME;
1133 goto Failure;
1134 }
1135
1136 // Create a new generic handle.
1137 pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE));
1138 if (!pHandle)
1139 {
1140 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1141 ERR("DllAllocSplMem failed!\n");
1142 goto Failure;
1143 }
1144
1145 // Create a new LOCAL_PRINTER_HANDLE.
1146 pPrinterHandle = DllAllocSplMem(sizeof(LOCAL_PRINTER_HANDLE));
1147 if (!pPrinterHandle)
1148 {
1149 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1150 ERR("DllAllocSplMem failed!\n");
1151 goto Failure;
1152 }
1153
1154 pPrinterHandle->hSPLFile = INVALID_HANDLE_VALUE;
1155 pPrinterHandle->pPrinter = pPrinter;
1156
1157 // Check if a datatype was given.
1158 if (pDefault && pDefault->pDatatype)
1159 {
1160 // Use the datatype if it's valid.
1161 if (!FindDatatype(pPrinter->pPrintProcessor, pDefault->pDatatype))
1162 {
1163 dwErrorCode = ERROR_INVALID_DATATYPE;
1164 goto Failure;
1165 }
1166
1167 pPrinterHandle->pwszDatatype = AllocSplStr(pDefault->pDatatype);
1168 }
1169 else
1170 {
1171 // Use the default datatype.
1172 pPrinterHandle->pwszDatatype = AllocSplStr(pPrinter->pwszDefaultDatatype);
1173 }
1174
1175 // Check if a DevMode was given, otherwise use the default.
1176 if (pDefault && pDefault->pDevMode)
1177 pPrinterHandle->pDevMode = DuplicateDevMode(pDefault->pDevMode);
1178 else
1179 pPrinterHandle->pDevMode = DuplicateDevMode(pPrinter->pDefaultDevMode);
1180
1181 // Check if the caller wants a handle to an existing Print Job.
1182 if (pwszJobParameter)
1183 {
1184 // The "Job " string has to follow now.
1185 if (wcsncmp(pwszJobParameter, L"Job ", 4) != 0)
1186 {
1187 dwErrorCode = ERROR_INVALID_NAME;
1188 goto Failure;
1189 }
1190
1191 // Skip the "Job " string.
1192 pwszJobParameter += 4;
1193
1194 // Skip even more whitespace.
1195 while (*pwszJobParameter == ' ')
1196 ++pwszJobParameter;
1197
1198 // Finally extract the desired Job ID.
1199 dwJobID = wcstoul(pwszJobParameter, NULL, 10);
1200 if (!IS_VALID_JOB_ID(dwJobID))
1201 {
1202 // The user supplied an invalid Job ID.
1203 dwErrorCode = ERROR_INVALID_NAME;
1204 goto Failure;
1205 }
1206
1207 // Look for this job in the Global Job List.
1208 pJob = LookupElementSkiplist(&GlobalJobList, &dwJobID, NULL);
1209 if (!pJob || pJob->pPrinter != pPrinter)
1210 {
1211 // The user supplied a non-existing Job ID or the Job ID does not belong to the supplied printer name.
1212 dwErrorCode = ERROR_INVALID_PRINTER_NAME;
1213 goto Failure;
1214 }
1215
1216 // Try to open its SPL file.
1217 GetJobFilePath(L"SPL", dwJobID, wszFullPath);
1219 if (pPrinterHandle->hSPLFile == INVALID_HANDLE_VALUE)
1220 {
1221 dwErrorCode = GetLastError();
1222 ERR("CreateFileW failed with error %lu for \"%S\"!\n", dwErrorCode, wszFullPath);
1223 goto Failure;
1224 }
1225
1226 // Associate the job to our Printer Handle, but don't set bStartedDoc.
1227 // This prevents the caller from doing further StartDocPrinter, WritePrinter, etc. calls on it.
1228 pPrinterHandle->pJob = pJob;
1229 }
1230
1231 // Make the generic handle a Printer handle.
1232 pHandle->HandleType = HandleType_Printer;
1233 pHandle->pSpecificHandle = pPrinterHandle;
1234
1235 // Return it.
1236 *phPrinter = (HANDLE)pHandle;
1237 return ERROR_SUCCESS;
1238
1239Failure:
1240 if (pHandle)
1241 DllFreeSplMem(pHandle);
1242
1243 if (pPrinterHandle)
1244 {
1245 if (pPrinterHandle->pwszDatatype)
1246 DllFreeSplStr(pPrinterHandle->pwszDatatype);
1247
1248 if (pPrinterHandle->pDevMode)
1249 DllFreeSplMem(pPrinterHandle->pDevMode);
1250
1251 DllFreeSplMem(pPrinterHandle);
1252 }
1253
1254 return dwErrorCode;
1255}
#define OPEN_EXISTING
Definition: compat.h:775
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define CreateFileW
Definition: compat.h:741
#define FILE_SHARE_READ
Definition: compat.h:136
_Check_return_ unsigned long __cdecl wcstoul(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define GENERIC_WRITE
Definition: nt_native.h:90
SKIPLIST GlobalJobList
Definition: jobs.c:11
DWORD GetJobFilePath(PCWSTR pwszExtension, DWORD dwJobID, PWSTR pwszOutput)
Definition: jobs.c:146
SKIPLIST PrinterList
Definition: printers.c:11
_Check_return_ _CRTIMP int __cdecl wcsncmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
PVOID LookupElementSkiplist(PSKIPLIST Skiplist, PVOID Element, PDWORD ElementIndex)
Definition: skiplist.c:357
PLOCAL_PRINTER pPrinter
Definition: precomp.h:144
PLOCAL_PRINTER pPrinter
Definition: precomp.h:171
LPDEVMODEW pDevMode
Definition: winspool.h:862
PWSTR WINAPI AllocSplStr(PCWSTR pwszInput)
Definition: memory.c:56
PDEVMODEW DuplicateDevMode(PDEVMODEW pInput)
Definition: tools.c:61
BOOL FindDatatype(const PLOCAL_PRINT_PROCESSOR pPrintProcessor, PCWSTR pwszDatatype)
#define IS_VALID_JOB_ID(ID)
Definition: precomp.h:38
#define ERROR_INVALID_DATATYPE
Definition: winerror.h:1111
#define ERROR_INVALID_PRINTER_NAME
Definition: winerror.h:1108

Referenced by LocalOpenPrinter().

◆ _LocalOpenPrintServerHandle()

static DWORD _LocalOpenPrintServerHandle ( PHANDLE  phPrinter)
static

Definition at line 1258 of file printers.c.

1259{
1260 PLOCAL_HANDLE pHandle;
1261
1262 // Create a new generic handle.
1263 pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE));
1264 if (!pHandle)
1265 {
1266 ERR("DllAllocSplMem failed!\n");
1268 }
1269
1270 // Make the generic handle a Print Server handle.
1271 pHandle->HandleType = HandleType_PrintServer;
1272 pHandle->pSpecificHandle = NULL;
1273
1274 // Return it.
1275 *phPrinter = (HANDLE)pHandle;
1276 return ERROR_SUCCESS;
1277}

Referenced by LocalOpenPrinter().

◆ _LocalOpenXcvHandle()

static DWORD _LocalOpenXcvHandle ( PWSTR  pwszParameter,
PHANDLE  phPrinter 
)
static

Definition at line 1280 of file printers.c.

1281{
1282 BOOL bReturnValue;
1283 DWORD dwErrorCode;
1284 HANDLE hXcv;
1285 PLOCAL_HANDLE pHandle = NULL;
1286 PLOCAL_PORT pPort;
1287 PLOCAL_PRINT_MONITOR pPrintMonitor;
1288 PLOCAL_XCV_HANDLE pXcvHandle = NULL;
1289
1290 // Skip the "Xcv" string.
1291 pwszParameter += 3;
1292
1293 // Is XcvMonitor or XcvPort requested?
1294 if (wcsncmp(pwszParameter, L"Monitor ", 8) == 0)
1295 {
1296 // Skip the "Monitor " string.
1297 pwszParameter += 8;
1298
1299 // Look for this monitor in our Print Monitor list.
1300 pPrintMonitor = FindPrintMonitor(pwszParameter);
1301 if (!pPrintMonitor)
1302 {
1303 // The caller supplied a non-existing Monitor name.
1304 dwErrorCode = ERROR_INVALID_NAME;
1305 ERR("OpenXcvHandle failed on Monitor name! %lu\n", dwErrorCode);
1306 goto Failure;
1307 }
1308 }
1309 else if (wcsncmp(pwszParameter, L"Port ", 5) == 0)
1310 {
1311 // Skip the "Port " string.
1312 pwszParameter += 5;
1313
1314 // Look for this port in our Print Monitor Port list.
1315 pPort = FindPort(pwszParameter);
1316 if (!pPort)
1317 {
1318 // The supplied port is unknown to all our Print Monitors.
1319 dwErrorCode = ERROR_INVALID_NAME;
1320 ERR("OpenXcvHandle failed on Port name! %lu\n", dwErrorCode);
1321 goto Failure;
1322 }
1323
1324 pPrintMonitor = pPort->pPrintMonitor;
1325 }
1326 else
1327 {
1328 dwErrorCode = ERROR_INVALID_NAME;
1329 ERR("OpenXcvHandle failed on bad name! %lu\n", dwErrorCode);
1330 goto Failure;
1331 }
1332
1333 // Call the monitor's XcvOpenPort function.
1334 if (pPrintMonitor->bIsLevel2)
1335 bReturnValue = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnXcvOpenPort(pPrintMonitor->hMonitor, pwszParameter, SERVER_EXECUTE, &hXcv);
1336 else
1337 bReturnValue = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnXcvOpenPort(pwszParameter, SERVER_EXECUTE, &hXcv);
1338
1339 if (!bReturnValue)
1340 {
1341 // The XcvOpenPort function failed. Return its last error.
1342 dwErrorCode = GetLastError();
1343 ERR("XcvOpenPort function failed! %lu\n", dwErrorCode);
1344 goto Failure;
1345 }
1346
1347 // Create a new generic handle.
1348 pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE));
1349 if (!pHandle)
1350 {
1351 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1352 ERR("DllAllocSplMem failed!\n");
1353 goto Failure;
1354 }
1355
1356 // Create a new LOCAL_XCV_HANDLE.
1357 pXcvHandle = DllAllocSplMem(sizeof(LOCAL_XCV_HANDLE));
1358 if (!pXcvHandle)
1359 {
1360 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1361 ERR("DllAllocSplMem failed!\n");
1362 goto Failure;
1363 }
1364
1365 pXcvHandle->hXcv = hXcv;
1366 pXcvHandle->pPrintMonitor = pPrintMonitor;
1367
1368 // Make the generic handle a Xcv handle.
1369 pHandle->HandleType = HandleType_Xcv;
1370 pHandle->pSpecificHandle = pXcvHandle;
1371
1372 // Return it.
1373 *phPrinter = (HANDLE)pHandle;
1374 ERR("OpenXcvHandle Success! %p\n", pXcvHandle);
1375 return ERROR_SUCCESS;
1376
1377Failure:
1378 if (pHandle)
1379 DllFreeSplMem(pHandle);
1380
1381 if (pXcvHandle)
1382 DllFreeSplMem(pXcvHandle);
1383
1384 return dwErrorCode;
1385}
static HANDLE hXcv
Definition: localmon.c:73
PLOCAL_PRINT_MONITOR FindPrintMonitor(PCWSTR pwszName)
Definition: monitors.c:28
#define SERVER_EXECUTE
Definition: winspool.h:1378

Referenced by LocalOpenPrinter().

◆ _PrinterListCompareRoutine()

static int WINAPI _PrinterListCompareRoutine ( PVOID  FirstStruct,
PVOID  SecondStruct 
)
static

Definition at line 91 of file printers.c.

92{
95
96 return wcsicmp(A->pwszPrinterName, B->pwszPrinterName);
97}
Definition: ehthrow.cxx:93
Definition: ehthrow.cxx:54
struct _LOCAL_PRINTER * PLOCAL_PRINTER
Definition: precomp.h:62
_IRQL_requires_same_ _In_ PVOID _In_ PVOID SecondStruct
Definition: rtltypes.h:390
_IRQL_requires_same_ _In_ PVOID FirstStruct
Definition: rtltypes.h:389

Referenced by InitializePrinterList().

◆ BroadcastChange()

VOID BroadcastChange ( PLOCAL_HANDLE  pHandle)

Definition at line 350 of file printers.c.

351{
352 PLOCAL_PRINTER pPrinter;
353 PSKIPLIST_NODE pNode;
354 DWORD cchMachineName = 0;
355 WCHAR wszMachineName[MAX_PATH] = {0}; // if not local, use Machine Name then Printer Name... pPrinter->pJob->pwszMachineName?
356
357 for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
358 {
359 pPrinter = (PLOCAL_PRINTER)pNode->Element;
360
361 StringCchCopyW( &wszMachineName[cchMachineName], sizeof(wszMachineName), pPrinter->pwszPrinterName );
362
363 PostMessageW( HWND_BROADCAST, WM_DEVMODECHANGE, 0, (LPARAM)&wszMachineName );
364 }
365}
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
struct _SKIPLIST_NODE * Next[SKIPLIST_LEVELS]
Definition: skiplist.h:30
PVOID Element
Definition: skiplist.h:31
SKIPLIST_NODE Head
Definition: skiplist.h:37
LONG_PTR LPARAM
Definition: windef.h:208
BOOL WINAPI PostMessageW(_In_opt_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define HWND_BROADCAST
Definition: winuser.h:1204
#define WM_DEVMODECHANGE
Definition: winuser.h:1631

Referenced by LocalAddForm(), LocalDeleteForm(), and LocalSetForm().

◆ InitializePrinterList()

BOOL InitializePrinterList ( VOID  )

Definition at line 107 of file printers.c.

108{
109 DWORD cbData;
110 DWORD cchPrinterName;
111 DWORD dwErrorCode;
112 DWORD dwSubKeys;
113 DWORD i;
114 HKEY hSubKey = NULL;
115 PLOCAL_PORT pPort;
116 PLOCAL_PRINTER pPrinter = NULL;
117 PLOCAL_PRINT_PROCESSOR pPrintProcessor;
118 PWSTR pwszPort = NULL;
119 PWSTR pwszPrintProcessor = NULL;
120 WCHAR wszPrinterName[MAX_PRINTER_NAME + 1];
121
122 TRACE("InitializePrinterList()\n");
123
124 // Initialize an empty list for our printers.
126
127 // Get the number of subkeys of the printers registry key. Each subkey is a local printer there.
128 dwErrorCode = (DWORD)RegQueryInfoKeyW(hPrintersKey, NULL, NULL, NULL, &dwSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
129 if (dwErrorCode != ERROR_SUCCESS)
130 {
131 ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode);
132 goto Cleanup;
133 }
134
135 // Loop through all available local printers.
136 for (i = 0; i < dwSubKeys; i++)
137 {
138 // Cleanup tasks from the previous run
139 if (hSubKey)
140 {
141 RegCloseKey(hSubKey);
142 hSubKey = NULL;
143 }
144
145 if (pPrinter)
146 {
147 if (pPrinter->pDefaultDevMode)
149
150 if (pPrinter->pwszDefaultDatatype)
152
153 if (pPrinter->pwszDescription)
155
156 if (pPrinter->pwszPrinterDriver)
158
159 if (pPrinter->pwszPrinterName)
161
162 DllFreeSplMem(pPrinter);
163 pPrinter = NULL;
164 }
165
166 if (pwszPrintProcessor)
167 {
168 DllFreeSplStr(pwszPrintProcessor);
169 pwszPrintProcessor = NULL;
170 }
171
172 // Get the name of this printer.
173 cchPrinterName = _countof(wszPrinterName);
174 dwErrorCode = (DWORD)RegEnumKeyExW(hPrintersKey, i, wszPrinterName, &cchPrinterName, NULL, NULL, NULL, NULL);
175 if (dwErrorCode == ERROR_MORE_DATA)
176 {
177 // This printer name exceeds the maximum length and is invalid.
178 continue;
179 }
180 else if (dwErrorCode != ERROR_SUCCESS)
181 {
182 ERR("RegEnumKeyExW failed for iteration %lu with status %lu!\n", i, dwErrorCode);
183 continue;
184 }
185
186 // Open this Printer's registry key.
187 dwErrorCode = (DWORD)RegOpenKeyExW(hPrintersKey, wszPrinterName, 0, KEY_READ, &hSubKey);
188 if (dwErrorCode != ERROR_SUCCESS)
189 {
190 ERR("RegOpenKeyExW failed for Printer \"%S\" with status %lu!\n", wszPrinterName, dwErrorCode);
191 continue;
192 }
193
194 // Get the Print Processor.
195 pwszPrintProcessor = AllocAndRegQueryWSZ(hSubKey, L"Print Processor");
196 if (!pwszPrintProcessor)
197 continue;
198
199 // Try to find it in the Print Processor List.
200 pPrintProcessor = FindPrintProcessor(pwszPrintProcessor);
201 if (!pPrintProcessor)
202 {
203 ERR("Invalid Print Processor \"%S\" for Printer \"%S\"!\n", pwszPrintProcessor, wszPrinterName);
204 continue;
205 }
206
207 // Get the Port.
208 pwszPort = AllocAndRegQueryWSZ(hSubKey, L"Port");
209 if (!pwszPort)
210 continue;
211
212 // Try to find it in the Port List.
213 pPort = FindPort(pwszPort);
214 if (!pPort)
215 {
216 ERR("Invalid Port \"%S\" for Printer \"%S\"!\n", pwszPort, wszPrinterName);
217 continue;
218 }
219
220 // Create a new LOCAL_PRINTER structure for it.
221 pPrinter = DllAllocSplMem(sizeof(LOCAL_PRINTER));
222 if (!pPrinter)
223 {
224 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
225 ERR("DllAllocSplMem failed!\n");
226 goto Cleanup;
227 }
228
229 pPrinter->pwszPrinterName = AllocSplStr(wszPrinterName);
230 pPrinter->pPrintProcessor = pPrintProcessor;
231 pPrinter->pPort = pPort;
232 InitializePrinterJobList(pPrinter);
233
234 // Get the location.
235 pPrinter->pwszLocation = AllocAndRegQueryWSZ(hSubKey, L"Location");
236 if (!pPrinter->pwszLocation)
237 continue;
238
239 // Get the printer driver.
240 pPrinter->pwszPrinterDriver = AllocAndRegQueryWSZ(hSubKey, L"Printer Driver");
241 if (!pPrinter->pwszPrinterDriver)
242 continue;
243
244 // Get the description.
245 pPrinter->pwszDescription = AllocAndRegQueryWSZ(hSubKey, L"Description");
246 if (!pPrinter->pwszDescription)
247 continue;
248
249 // Get the default datatype.
250 pPrinter->pwszDefaultDatatype = AllocAndRegQueryWSZ(hSubKey, L"Datatype");
251 if (!pPrinter->pwszDefaultDatatype)
252 continue;
253
254 // Verify that it's valid.
255 if (!FindDatatype(pPrintProcessor, pPrinter->pwszDefaultDatatype))
256 {
257 ERR("Invalid default datatype \"%S\" for Printer \"%S\"!\n", pPrinter->pwszDefaultDatatype, wszPrinterName);
258 continue;
259 }
260
261 // Determine the size of the DevMode.
262 dwErrorCode = (DWORD)RegQueryValueExW(hSubKey, L"Default DevMode", NULL, NULL, NULL, &cbData);
263 if (dwErrorCode != ERROR_SUCCESS)
264 {
265 ERR("Couldn't query the size of the DevMode for Printer \"%S\", status is %lu, cbData is %lu!\n", wszPrinterName, dwErrorCode, cbData);
266 continue;
267 }
268
269 // Allocate enough memory for the DevMode.
270 pPrinter->pDefaultDevMode = DllAllocSplMem(cbData);
271 if (!pPrinter->pDefaultDevMode)
272 {
273 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
274 ERR("DllAllocSplMem failed!\n");
275 goto Cleanup;
276 }
277
278 // Get the default DevMode.
279 dwErrorCode = (DWORD)RegQueryValueExW(hSubKey, L"Default DevMode", NULL, NULL, (PBYTE)pPrinter->pDefaultDevMode, &cbData);
280 if (dwErrorCode != ERROR_SUCCESS)
281 {
282 ERR("Couldn't query a DevMode for Printer \"%S\", status is %lu, cbData is %lu!\n", wszPrinterName, dwErrorCode, cbData);
283 continue;
284 }
285
286 // Get the Attributes.
287 cbData = sizeof(DWORD);
288 dwErrorCode = (DWORD)RegQueryValueExW(hSubKey, L"Attributes", NULL, NULL, (PBYTE)&pPrinter->dwAttributes, &cbData);
289 if (dwErrorCode != ERROR_SUCCESS)
290 {
291 ERR("Couldn't query Attributes for Printer \"%S\", status is %lu!\n", wszPrinterName, dwErrorCode);
292 continue;
293 }
294
295 // Get the Status.
296 cbData = sizeof(DWORD);
297 dwErrorCode = (DWORD)RegQueryValueExW(hSubKey, L"Status", NULL, NULL, (PBYTE)&pPrinter->dwStatus, &cbData);
298 if (dwErrorCode != ERROR_SUCCESS)
299 {
300 ERR("Couldn't query Status for Printer \"%S\", status is %lu!\n", wszPrinterName, dwErrorCode);
301 continue;
302 }
303
304 // Add this printer to the printer list.
305 if (!InsertElementSkiplist(&PrinterList, pPrinter))
306 {
307 ERR("InsertElementSkiplist failed for Printer \"%S\"!\n", pPrinter->pwszPrinterName);
308 goto Cleanup;
309 }
310
311 // Don't let the cleanup routines free this.
312 pPrinter = NULL;
313 }
314
315 dwErrorCode = ERROR_SUCCESS;
316
317Cleanup:
318 // Inside the loop
319 if (hSubKey)
320 RegCloseKey(hSubKey);
321
322 if (pPrinter)
323 {
324 if (pPrinter->pDefaultDevMode)
326
327 if (pPrinter->pwszDefaultDatatype)
329
330 if (pPrinter->pwszDescription)
332
333 if (pPrinter->pwszPrinterDriver)
335
336 if (pPrinter->pwszPrinterName)
338
339 DllFreeSplMem(pPrinter);
340 }
341
342 if (pwszPrintProcessor)
343 DllFreeSplStr(pwszPrintProcessor);
344
345 SetLastError(dwErrorCode);
346 return (dwErrorCode == ERROR_SUCCESS);
347}
#define RegCloseKey(hKey)
Definition: registry.h:49
#define ERROR_MORE_DATA
Definition: dderror.h:13
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegEnumKeyExW(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPWSTR lpClass, _Inout_opt_ LPDWORD lpcbClass, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: reg.c:2504
LONG WINAPI RegQueryInfoKeyW(HKEY hKey, LPWSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen, LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime)
Definition: reg.c:3662
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
#define SetLastError(x)
Definition: compat.h:752
static const WCHAR Cleanup[]
Definition: register.c:80
#define MAX_PRINTER_NAME
Definition: fpSetJob.c:25
#define KEY_READ
Definition: nt_native.h:1023
#define DWORD
Definition: nt_native.h:44
void InitializePrinterJobList(PLOCAL_PRINTER pPrinter)
Definition: jobs.c:247
static int WINAPI _PrinterListCompareRoutine(PVOID FirstStruct, PVOID SecondStruct)
Definition: printers.c:91
BOOL InsertElementSkiplist(PSKIPLIST Skiplist, PVOID Element)
Definition: skiplist.c:250
void InitializeSkiplist(PSKIPLIST Skiplist, PSKIPLIST_ALLOCATE_ROUTINE AllocateRoutine, PSKIPLIST_COMPARE_ROUTINE CompareRoutine, PSKIPLIST_FREE_ROUTINE FreeRoutine)
Definition: skiplist.c:220
void(WINAPI * PSKIPLIST_FREE_ROUTINE)(PVOID)
Definition: skiplist.h:24
#define _countof(array)
Definition: sndvol32.h:70
#define TRACE(s)
Definition: solgame.cpp:4
HKEY hPrintersKey
Definition: main.c:12
PLOCAL_PRINT_PROCESSOR FindPrintProcessor(PCWSTR pwszName)
PWSTR AllocAndRegQueryWSZ(HKEY hKey, PCWSTR pwszValueName)
Definition: tools.c:26

Referenced by _InitializeLocalSpooler().

◆ LocalClosePrinter()

BOOL WINAPI LocalClosePrinter ( HANDLE  hPrinter)

Definition at line 1960 of file printers.c.

1961{
1962 PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
1963
1964 FIXME("LocalClosePrinter(%p)\n", hPrinter);
1965
1966 if (!pHandle)
1967 {
1969 return FALSE;
1970 }
1971
1972 if (pHandle->HandleType == HandleType_Port)
1973 {
1975 }
1976 else if (pHandle->HandleType == HandleType_Printer)
1977 {
1979 }
1980 else if (pHandle->HandleType == HandleType_PrintServer)
1981 {
1982 // Nothing to do.
1983 }
1984 else if (pHandle->HandleType == HandleType_Xcv)
1985 {
1987 }
1988 FIXME("LocalClosePrinter 1\n");
1989 // Free memory for the handle and the specific handle (if any).
1990 if (pHandle->pSpecificHandle)
1992 FIXME("LocalClosePrinter 2\n");
1993 DllFreeSplMem(pHandle);
1994 FIXME("LocalClosePrinter 3\n");
1995 return TRUE;
1996}
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
static void _LocalClosePrinterHandle(PLOCAL_PRINTER_HANDLE pPrinterHandle)
Definition: printers.c:1937
static void _LocalCloseXcvHandle(PLOCAL_XCV_HANDLE pXcvHandle)
Definition: printers.c:1950
static void _LocalClosePortHandle(PLOCAL_PORT_HANDLE pPortHandle)
Definition: printers.c:1926
struct _LOCAL_HANDLE * PLOCAL_HANDLE
Definition: precomp.h:56

◆ LocalEndDocPrinter()

BOOL WINAPI LocalEndDocPrinter ( HANDLE  hPrinter)

Definition at line 1857 of file printers.c.

1858{
1859 BOOL bReturnValue;
1860 DWORD dwErrorCode;
1861 PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
1862 PLOCAL_PORT_HANDLE pPortHandle;
1863 PLOCAL_PRINTER_HANDLE pPrinterHandle;
1864
1865 TRACE("LocalEndDocPrinter(%p)\n", hPrinter);
1866
1867 // Sanity checks.
1868 if (!pHandle)
1869 {
1870 dwErrorCode = ERROR_INVALID_HANDLE;
1871 goto Cleanup;
1872 }
1873
1874 // Port handles are an entirely different thing.
1875 if (pHandle->HandleType == HandleType_Port)
1876 {
1877 pPortHandle = (PLOCAL_PORT_HANDLE)pHandle->pSpecificHandle;
1878
1879 // Call the monitor's EndDocPort function.
1880 if (pPortHandle->pPort->pPrintMonitor->bIsLevel2)
1881 bReturnValue = ((PMONITOR2)pPortHandle->pPort->pPrintMonitor->pMonitor)->pfnEndDocPort(pPortHandle->hPort);
1882 else
1883 bReturnValue = ((LPMONITOREX)pPortHandle->pPort->pPrintMonitor->pMonitor)->Monitor.pfnEndDocPort(pPortHandle->hPort);
1884
1885 if (!bReturnValue)
1886 {
1887 // The EndDocPort function failed. Return its last error.
1888 dwErrorCode = GetLastError();
1889 goto Cleanup;
1890 }
1891
1892 // We were successful!
1893 dwErrorCode = ERROR_SUCCESS;
1894 goto Cleanup;
1895 }
1896
1897 // The remaining function deals with Printer handles only.
1898 if (pHandle->HandleType != HandleType_Printer)
1899 {
1900 dwErrorCode = ERROR_INVALID_HANDLE;
1901 goto Cleanup;
1902 }
1903
1904 pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle;
1905
1906 // We require StartDocPrinter or AddJob to be called first.
1907 if (!pPrinterHandle->bStartedDoc)
1908 {
1909 dwErrorCode = ERROR_SPL_NO_STARTDOC;
1910 goto Cleanup;
1911 }
1912
1913 // TODO: Something like ScheduleJob
1914
1915 // Finish the job.
1916 pPrinterHandle->bStartedDoc = FALSE;
1917 pPrinterHandle->pJob = NULL;
1918 dwErrorCode = ERROR_SUCCESS;
1919
1920Cleanup:
1921 SetLastError(dwErrorCode);
1922 return (dwErrorCode == ERROR_SUCCESS);
1923}
if(dx< 0)
Definition: linetemp.h:194
struct _LOCAL_PORT_HANDLE * PLOCAL_PORT_HANDLE
Definition: precomp.h:59
struct _LOCAL_PRINTER_HANDLE * PLOCAL_PRINTER_HANDLE
Definition: precomp.h:63
#define ERROR_SPL_NO_STARTDOC
Definition: winerror.h:1208

◆ LocalEndPagePrinter()

BOOL WINAPI LocalEndPagePrinter ( HANDLE  hPrinter)

Definition at line 1834 of file printers.c.

1835{
1836 DWORD dwErrorCode;
1837 PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
1838
1839 TRACE("LocalEndPagePrinter(%p)\n", hPrinter);
1840
1841 // Sanity checks.
1842 if (!pHandle || pHandle->HandleType != HandleType_Printer)
1843 {
1844 dwErrorCode = ERROR_INVALID_HANDLE;
1845 goto Cleanup;
1846 }
1847
1848 // This function doesn't do anything else for now.
1849 dwErrorCode = ERROR_SUCCESS;
1850
1851Cleanup:
1852 SetLastError(dwErrorCode);
1853 return (dwErrorCode == ERROR_SUCCESS);
1854}

◆ LocalEnumPrinters()

BOOL WINAPI LocalEnumPrinters ( DWORD  Flags,
LPWSTR  Name,
DWORD  Level,
LPBYTE  pPrinterEnum,
DWORD  cbBuf,
LPDWORD  pcbNeeded,
LPDWORD  pcReturned 
)

Definition at line 884 of file printers.c.

885{
886 DWORD cchComputerName = 0;
887 DWORD dwErrorCode;
888 PBYTE pPrinterInfoEnd;
889 PSKIPLIST_NODE pNode;
890 WCHAR wszComputerName[2 + MAX_COMPUTERNAME_LENGTH + 1 + 1] = { 0 };
891 PLOCAL_PRINTER pPrinter;
892
893 FIXME("LocalEnumPrinters(%lu, %S, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
894
895 // Do no sanity checks or assertions for pcbNeeded and pcReturned here.
896 // This is verified and required by localspl_apitest!
897
898 // Begin counting.
899 *pcbNeeded = 0;
900 *pcReturned = 0;
901
903 {
904 // If the flags for the Network Print Provider are given, bail out with ERROR_INVALID_NAME.
905 // This is the internal way for a Print Provider to signal that it doesn't handle this request.
906 dwErrorCode = ERROR_INVALID_NAME;
907 goto Cleanup;
908 }
909
911 {
912 // The Local Print Provider is the right destination for the request, but without any of these flags,
913 // there is no information that can be returned.
914 // So just signal a successful request.
915 dwErrorCode = ERROR_SUCCESS;
916 goto Cleanup;
917 }
918
919 if (Level == 3 || Level > 5)
920 {
921 // The caller supplied an invalid level for EnumPrinters.
922 dwErrorCode = ERROR_INVALID_LEVEL;
923 goto Cleanup;
924 }
925
926 if (Level == 1 && Flags & PRINTER_ENUM_NAME && !Name)
927 {
928 // The caller wants information about this Print Provider.
929 // spoolss packs this into an array of information about all Print Providers.
930 dwErrorCode = _DumpLevel1PrintProviderInformation(pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
931 goto Cleanup;
932 }
933
934 // Check the supplied Name parameter (if any).
935 // This may return a Computer Name string we later prepend to the output.
936 dwErrorCode = _LocalEnumPrintersCheckName(Flags, Name, wszComputerName, &cchComputerName);
937 if (dwErrorCode != ERROR_SUCCESS)
938 goto Cleanup;
939
940 // Count the required buffer size and the number of printers.
941 for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
942 {
943 pPrinter = (PLOCAL_PRINTER)pNode->Element;
944
945 // TODO: If PRINTER_ENUM_SHARED is given, add this Printer if it's shared instead of just ignoring it.
947 {
948 FIXME("Printer Sharing is not supported yet, returning no printers!\n");
949 continue;
950 }
951
952 pfnGetPrinterLevels[Level](pPrinter, NULL, NULL, pcbNeeded, cchComputerName, wszComputerName);
953 }
954
955 // Check if the supplied buffer is large enough.
956 if (cbBuf < *pcbNeeded)
957 {
958 dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
959 goto Cleanup;
960 }
961
962 // Copy over the Printer information.
963 pPrinterInfoEnd = &pPrinterEnum[*pcbNeeded];
964
965 for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
966 {
967 pPrinter = (PLOCAL_PRINTER)pNode->Element;
968
969 // TODO: If PRINTER_ENUM_SHARED is given, add this Printer if it's shared instead of just ignoring it.
971 continue;
972
973 pfnGetPrinterLevels[Level](pPrinter, &pPrinterEnum, &pPrinterInfoEnd, NULL, cchComputerName, wszComputerName);
974 (*pcReturned)++;
975 }
976
977 dwErrorCode = ERROR_SUCCESS;
978
979Cleanup:
980 SetLastError(dwErrorCode);
981 return (dwErrorCode == ERROR_SUCCESS);
982}
static DWORD _DumpLevel1PrintProviderInformation(PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
Definition: printers.c:486
static const PLocalGetPrinterLevelFunc pfnGetPrinterLevels[]
Definition: printers.c:28
static DWORD _LocalEnumPrintersCheckName(DWORD Flags, PCWSTR Name, PWSTR pwszComputerName, PDWORD pcchComputerName)
Definition: printers.c:391
#define ERROR_INVALID_LEVEL
Definition: winerror.h:196
#define PRINTER_ENUM_SHARED
Definition: winspool.h:901
#define PRINTER_ENUM_LOCAL
Definition: winspool.h:896
#define PRINTER_ENUM_NETWORK
Definition: winspool.h:902
#define PRINTER_ENUM_REMOTE
Definition: winspool.h:900
#define PRINTER_ENUM_CONNECTIONS
Definition: winspool.h:897
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:56

◆ LocalGetPrinter()

BOOL WINAPI LocalGetPrinter ( HANDLE  hPrinter,
DWORD  Level,
LPBYTE  pPrinter,
DWORD  cbBuf,
LPDWORD  pcbNeeded 
)

Definition at line 985 of file printers.c.

986{
987 // We never prepend a Computer Name to the output, but need to provide an empty string,
988 // because this variable is passed to StringCbCopyExW.
989 const WCHAR wszDummyComputerName[] = L"";
990
991 DWORD dwErrorCode;
992 PBYTE pPrinterEnd;
993 PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
994 PLOCAL_PRINTER_HANDLE pPrinterHandle;
995
996 TRACE("LocalGetPrinter(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
997
998 // Sanity checks.
999 if (!pHandle)
1000 {
1001 dwErrorCode = ERROR_INVALID_HANDLE;
1002 goto Cleanup;
1003 }
1004
1005 // Check if this is a printer handle.
1006 if (pHandle->HandleType != HandleType_Printer)
1007 {
1008 dwErrorCode = ERROR_INVALID_HANDLE;
1009 goto Cleanup;
1010 }
1011
1012 pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle;
1013
1014 if (Level > 9)
1015 {
1016 // The caller supplied an invalid level for GetPrinter.
1017 dwErrorCode = ERROR_INVALID_LEVEL;
1018 goto Cleanup;
1019 }
1020
1021 // Count the required buffer size.
1022 *pcbNeeded = 0;
1023 pfnGetPrinterLevels[Level](pPrinterHandle->pPrinter, NULL, NULL, pcbNeeded, 0, wszDummyComputerName);
1024
1025 // Check if the supplied buffer is large enough.
1026 if (cbBuf < *pcbNeeded)
1027 {
1028 dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
1029 goto Cleanup;
1030 }
1031
1032 // Copy over the Printer information.
1033 pPrinterEnd = &pPrinter[*pcbNeeded];
1034 pfnGetPrinterLevels[Level](pPrinterHandle->pPrinter, &pPrinter, &pPrinterEnd, NULL, 0, wszDummyComputerName);
1035 dwErrorCode = ERROR_SUCCESS;
1036
1037Cleanup:
1038 SetLastError(dwErrorCode);
1039 return (dwErrorCode == ERROR_SUCCESS);
1040}

◆ LocalOpenPrinter()

BOOL WINAPI LocalOpenPrinter ( PWSTR  lpPrinterName,
HANDLE phPrinter,
PPRINTER_DEFAULTSW  pDefault 
)

Definition at line 1398 of file printers.c.

1399{
1400 DWORD cchComputerName;
1401 DWORD cchFirstParameter;
1402 DWORD dwErrorCode;
1403 PWSTR p = lpPrinterName;
1404 PWSTR pwszFirstParameter = NULL;
1405 PWSTR pwszSecondParameter;
1406 WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH + 1];
1407
1408 TRACE("LocalOpenPrinter(%S, %p, %p)\n", lpPrinterName, phPrinter, pDefault);
1409
1410 ASSERT(phPrinter);
1411 *phPrinter = NULL;
1412
1413 if (!lpPrinterName)
1414 {
1415 // The caller wants a Print Server handle and provided a NULL string.
1416 dwErrorCode = _LocalOpenPrintServerHandle(phPrinter);
1417 goto Cleanup;
1418 }
1419
1420 // Skip any server name in the first parameter.
1421 // Does lpPrinterName begin with two backslashes to indicate a server name?
1422 if (lpPrinterName[0] == L'\\' && lpPrinterName[1] == L'\\')
1423 {
1424 // Skip these two backslashes.
1425 lpPrinterName += 2;
1426
1427 // Look for the terminating null character or closing backslash.
1428 p = lpPrinterName;
1429 while (*p != L'\0' && *p != L'\\')
1430 p++;
1431
1432 // Get the local computer name for comparison.
1433 cchComputerName = _countof(wszComputerName);
1434 if (!GetComputerNameW(wszComputerName, &cchComputerName))
1435 {
1436 dwErrorCode = GetLastError();
1437 ERR("GetComputerNameW failed with error %lu!\n", dwErrorCode);
1438 goto Cleanup;
1439 }
1440
1441 // Now compare this string excerpt with the local computer name.
1442 // The input parameter may not be writable, so we can't null-terminate the input string at this point.
1443 // This print provider only supports local printers, so both strings have to match.
1444 if (p - lpPrinterName != cchComputerName || _wcsnicmp(lpPrinterName, wszComputerName, cchComputerName) != 0)
1445 {
1446 dwErrorCode = ERROR_INVALID_NAME;
1447 goto Cleanup;
1448 }
1449
1450 // If lpPrinterName is only "\\COMPUTERNAME" with nothing more, the caller wants a handle to the local Print Server.
1451 if (!*p)
1452 {
1453 // The caller wants a Print Server handle and provided a string like:
1454 // "\\COMPUTERNAME"
1455 dwErrorCode = _LocalOpenPrintServerHandle(phPrinter);
1456 goto Cleanup;
1457 }
1458
1459 // We have checked the server name and don't need it anymore.
1460 lpPrinterName = p + 1;
1461 }
1462
1463 // Look for a comma. If it exists, it indicates the end of the first parameter.
1464 pwszSecondParameter = wcschr(lpPrinterName, L',');
1465 if (pwszSecondParameter)
1466 cchFirstParameter = pwszSecondParameter - p;
1467 else
1468 cchFirstParameter = wcslen(lpPrinterName);
1469
1470 // We must have at least one parameter.
1471 if (!cchFirstParameter && !pwszSecondParameter)
1472 {
1473 dwErrorCode = ERROR_INVALID_NAME;
1474 goto Cleanup;
1475 }
1476
1477 // Do we have a first parameter?
1478 if (cchFirstParameter)
1479 {
1480 // Yes, extract it.
1481 // No null-termination is necessary here, because DllAllocSplMem returns a zero-initialized buffer.
1482 pwszFirstParameter = DllAllocSplMem((cchFirstParameter + 1) * sizeof(WCHAR));
1483 CopyMemory(pwszFirstParameter, lpPrinterName, cchFirstParameter * sizeof(WCHAR));
1484 }
1485
1486 // Do we have a second parameter?
1487 if (pwszSecondParameter)
1488 {
1489 // Yes, skip the comma at the beginning.
1490 ++pwszSecondParameter;
1491
1492 // Skip whitespace as well.
1493 while (*pwszSecondParameter == L' ')
1494 ++pwszSecondParameter;
1495 }
1496
1497 // Now we can finally check the type of handle actually requested.
1498 if (pwszFirstParameter && pwszSecondParameter && wcsncmp(pwszSecondParameter, L"Port", 4) == 0)
1499 {
1500 // The caller wants a port handle and provided a string like:
1501 // "LPT1:, Port"
1502 // "\\COMPUTERNAME\LPT1:, Port"
1503 dwErrorCode = _LocalOpenPortHandle(pwszFirstParameter, phPrinter);
1504 }
1505 else if (!pwszFirstParameter && pwszSecondParameter && wcsncmp(pwszSecondParameter, L"Xcv", 3) == 0)
1506 {
1507 // The caller wants an Xcv handle and provided a string like:
1508 // ", XcvMonitor Local Port"
1509 // "\\COMPUTERNAME\, XcvMonitor Local Port"
1510 // ", XcvPort LPT1:"
1511 // "\\COMPUTERNAME\, XcvPort LPT1:"
1512 FIXME("OpenXcvHandle : %S\n",pwszSecondParameter);
1513 dwErrorCode = _LocalOpenXcvHandle(pwszSecondParameter, phPrinter);
1514 }
1515 else
1516 {
1517 // The caller wants a Printer or Printer Job handle and provided a string like:
1518 // "HP DeskJet"
1519 // "\\COMPUTERNAME\HP DeskJet"
1520 // "HP DeskJet, Job 5"
1521 // "\\COMPUTERNAME\HP DeskJet, Job 5"
1522 dwErrorCode = _LocalOpenPrinterHandle(pwszFirstParameter, pwszSecondParameter, phPrinter, pDefault);
1523 }
1524
1525Cleanup:
1526 if (pwszFirstParameter)
1527 DllFreeSplMem(pwszFirstParameter);
1528
1529 SetLastError(dwErrorCode);
1530 return (dwErrorCode == ERROR_SUCCESS);
1531}
#define wcschr
Definition: compat.h:17
#define ASSERT(a)
Definition: mode.c:44
static DWORD _LocalOpenPortHandle(PWSTR pwszPortName, PHANDLE phPrinter)
Definition: printers.c:1043
static DWORD _LocalOpenPrinterHandle(PWSTR pwszPrinterName, PWSTR pwszJobParameter, PHANDLE phPrinter, PPRINTER_DEFAULTSW pDefault)
Definition: printers.c:1117
static DWORD _LocalOpenPrintServerHandle(PHANDLE phPrinter)
Definition: printers.c:1258
static DWORD _LocalOpenXcvHandle(PWSTR pwszParameter, PHANDLE phPrinter)
Definition: printers.c:1280
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)

◆ LocalPrinterMessageBox()

DWORD WINAPI LocalPrinterMessageBox ( HANDLE  hPrinter,
DWORD  Error,
HWND  hWnd,
LPWSTR  pText,
LPWSTR  pCaption,
DWORD  dwType 
)

Definition at line 1391 of file printers.c.

1392{
1394 return 0;
1395}

◆ LocalReadPrinter()

BOOL WINAPI LocalReadPrinter ( HANDLE  hPrinter,
PVOID  pBuf,
DWORD  cbBuf,
PDWORD  pNoBytesRead 
)

Definition at line 1534 of file printers.c.

1535{
1536 BOOL bReturnValue;
1537 DWORD dwErrorCode;
1538 PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
1539 PLOCAL_PORT_HANDLE pPortHandle;
1540 PLOCAL_PRINTER_HANDLE pPrinterHandle;
1541
1542 TRACE("LocalReadPrinter(%p, %p, %lu, %p)\n", hPrinter, pBuf, cbBuf, pNoBytesRead);
1543
1544 // Sanity checks.
1545 if (!pHandle)
1546 {
1547 dwErrorCode = ERROR_INVALID_HANDLE;
1548 goto Cleanup;
1549 }
1550
1551 // Port handles are an entirely different thing.
1552 if (pHandle->HandleType == HandleType_Port)
1553 {
1554 pPortHandle = (PLOCAL_PORT_HANDLE)pHandle->pSpecificHandle;
1555
1556 // Call the monitor's ReadPort function.
1557 if (pPortHandle->pPort->pPrintMonitor->bIsLevel2)
1558 bReturnValue = ((PMONITOR2)pPortHandle->pPort->pPrintMonitor->pMonitor)->pfnReadPort(pPortHandle->hPort, pBuf, cbBuf, pNoBytesRead);
1559 else
1560 bReturnValue = ((LPMONITOREX)pPortHandle->pPort->pPrintMonitor->pMonitor)->Monitor.pfnReadPort(pPortHandle->hPort, pBuf, cbBuf, pNoBytesRead);
1561
1562 if (!bReturnValue)
1563 {
1564 // The ReadPort function failed. Return its last error.
1565 dwErrorCode = GetLastError();
1566 goto Cleanup;
1567 }
1568
1569 // We were successful!
1570 dwErrorCode = ERROR_SUCCESS;
1571 goto Cleanup;
1572 }
1573
1574 // The remaining function deals with Printer handles only.
1575 if (pHandle->HandleType != HandleType_Printer)
1576 {
1577 dwErrorCode = ERROR_INVALID_HANDLE;
1578 goto Cleanup;
1579 }
1580
1581 pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle;
1582
1583 // ReadPrinter needs an opened SPL file to work.
1584 // This only works if a Printer Job Handle was requested in OpenPrinter.
1585 if (pPrinterHandle->hSPLFile == INVALID_HANDLE_VALUE)
1586 {
1587 dwErrorCode = ERROR_INVALID_HANDLE;
1588 goto Cleanup;
1589 }
1590
1591 // Pass the parameters to ReadFile.
1592 if (!ReadFile(pPrinterHandle->hSPLFile, pBuf, cbBuf, pNoBytesRead, NULL))
1593 {
1594 dwErrorCode = GetLastError();
1595 ERR("ReadFile failed with error %lu!\n", dwErrorCode);
1596 goto Cleanup;
1597 }
1598
1599 dwErrorCode = ERROR_SUCCESS;
1600
1601Cleanup:
1602 SetLastError(dwErrorCode);
1603 return (dwErrorCode == ERROR_SUCCESS);
1604}
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742

◆ LocalStartDocPrinter()

DWORD WINAPI LocalStartDocPrinter ( HANDLE  hPrinter,
DWORD  Level,
PBYTE  pDocInfo 
)

Definition at line 1607 of file printers.c.

1608{
1609 BOOL bReturnValue;
1610 DWORD dwErrorCode;
1611 DWORD dwReturnValue = 0;
1612 PDOC_INFO_1W pDocInfo1 = (PDOC_INFO_1W)pDocInfo;
1613 PLOCAL_JOB pJob;
1614 PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
1615 PLOCAL_PORT_HANDLE pPortHandle;
1616 PLOCAL_PRINTER_HANDLE pPrinterHandle;
1617
1618 TRACE("LocalStartDocPrinter(%p, %lu, %p)\n", hPrinter, Level, pDocInfo);
1619
1620 // Sanity checks.
1621 if (!pHandle)
1622 {
1623 dwErrorCode = ERROR_INVALID_HANDLE;
1624 goto Cleanup;
1625 }
1626
1627 // Port handles are an entirely different thing.
1628 if (pHandle->HandleType == HandleType_Port)
1629 {
1630 pPortHandle = (PLOCAL_PORT_HANDLE)pHandle->pSpecificHandle;
1631
1632 // This call should come from a Print Processor and the job this port is going to print was assigned to us before opening the Print Processor.
1633 // Claim it exclusively for this port handle.
1634 pJob = pPortHandle->pPort->pNextJobToProcess;
1635 pPortHandle->pPort->pNextJobToProcess = NULL;
1636 ASSERT(pJob);
1637
1638 // Call the monitor's StartDocPort function.
1639 if (pPortHandle->pPort->pPrintMonitor->bIsLevel2)
1640 bReturnValue = ((PMONITOR2)pPortHandle->pPort->pPrintMonitor->pMonitor)->pfnStartDocPort(pPortHandle->hPort, pJob->pPrinter->pwszPrinterName, pJob->dwJobID, Level, pDocInfo);
1641 else
1642 bReturnValue = ((LPMONITOREX)pPortHandle->pPort->pPrintMonitor->pMonitor)->Monitor.pfnStartDocPort(pPortHandle->hPort, pJob->pPrinter->pwszPrinterName, pJob->dwJobID, Level, pDocInfo);
1643
1644 if (!bReturnValue)
1645 {
1646 // The StartDocPort function failed. Return its last error.
1647 dwErrorCode = GetLastError();
1648 goto Cleanup;
1649 }
1650
1651 // We were successful!
1652 dwErrorCode = ERROR_SUCCESS;
1653 dwReturnValue = pJob->dwJobID;
1654 goto Cleanup;
1655 }
1656
1657 // The remaining function deals with Printer handles only.
1658 if (pHandle->HandleType != HandleType_Printer)
1659 {
1660 dwErrorCode = ERROR_INVALID_HANDLE;
1661 goto Cleanup;
1662 }
1663
1664 if (!pDocInfo1)
1665 {
1666 dwErrorCode = ERROR_INVALID_PARAMETER;
1667 goto Cleanup;
1668 }
1669
1670 pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle;
1671
1672 // pJob may already be occupied if this is a Print Job handle. In this case, StartDocPrinter has to fail.
1673 if (pPrinterHandle->pJob)
1674 {
1675 dwErrorCode = ERROR_INVALID_PARAMETER;
1676 goto Cleanup;
1677 }
1678
1679 // Check the validity of the datatype if we got one.
1680 if (pDocInfo1->pDatatype && !FindDatatype(pPrinterHandle->pJob->pPrintProcessor, pDocInfo1->pDatatype))
1681 {
1682 dwErrorCode = ERROR_INVALID_DATATYPE;
1683 goto Cleanup;
1684 }
1685
1686 // Check if this is the right document information level.
1687 if (Level != 1)
1688 {
1689 dwErrorCode = ERROR_INVALID_LEVEL;
1690 goto Cleanup;
1691 }
1692
1693 // All requirements are met - create a new job.
1694 dwErrorCode = CreateJob(pPrinterHandle);
1695 if (dwErrorCode != ERROR_SUCCESS)
1696 goto Cleanup;
1697
1698 // Use any given datatype.
1699 if (pDocInfo1->pDatatype && !ReallocSplStr(&pPrinterHandle->pJob->pwszDatatype, pDocInfo1->pDatatype))
1700 {
1701 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1702 ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
1703 goto Cleanup;
1704 }
1705
1706 // Use any given document name.
1707 if (pDocInfo1->pDocName && !ReallocSplStr(&pPrinterHandle->pJob->pwszDocumentName, pDocInfo1->pDocName))
1708 {
1709 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1710 ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
1711 goto Cleanup;
1712 }
1713
1714 // We were successful!
1715 dwErrorCode = ERROR_SUCCESS;
1716 dwReturnValue = pPrinterHandle->pJob->dwJobID;
1717
1718Cleanup:
1719 SetLastError(dwErrorCode);
1720 return dwReturnValue;
1721}
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
DWORD WINAPI CreateJob(PLOCAL_PRINTER_HANDLE pPrinterHandle)
Definition: jobs.c:257
LPWSTR pDatatype
Definition: winspool.h:618
LPWSTR pDocName
Definition: winspool.h:616
DWORD dwJobID
Definition: precomp.h:140
PLOCAL_PRINT_PROCESSOR pPrintProcessor
Definition: precomp.h:145
PWSTR pwszDatatype
Definition: precomp.h:151
PWSTR pwszDocumentName
Definition: precomp.h:150
PLOCAL_JOB pNextJobToProcess
Definition: precomp.h:92
BOOL WINAPI ReallocSplStr(PWSTR *ppwszString, PCWSTR pwszInput)
Definition: memory.c:195
struct _DOC_INFO_1W * PDOC_INFO_1W

◆ LocalStartPagePrinter()

BOOL WINAPI LocalStartPagePrinter ( HANDLE  hPrinter)

Definition at line 1724 of file printers.c.

1725{
1726 DWORD dwErrorCode;
1727 PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
1728 PLOCAL_PRINTER_HANDLE pPrinterHandle;
1729
1730 TRACE("LocalStartPagePrinter(%p)\n", hPrinter);
1731
1732 // Sanity checks.
1733 if (!pHandle || pHandle->HandleType != HandleType_Printer)
1734 {
1735 dwErrorCode = ERROR_INVALID_HANDLE;
1736 goto Cleanup;
1737 }
1738
1739 pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle;
1740
1741 // We require StartDocPrinter or AddJob to be called first.
1742 if (!pPrinterHandle->bStartedDoc)
1743 {
1744 dwErrorCode = ERROR_SPL_NO_STARTDOC;
1745 goto Cleanup;
1746 }
1747
1748 // Increase the page count.
1749 ++pPrinterHandle->pJob->dwTotalPages;
1750 dwErrorCode = ERROR_SUCCESS;
1751
1752Cleanup:
1753 SetLastError(dwErrorCode);
1754 return (dwErrorCode == ERROR_SUCCESS);
1755}
DWORD dwTotalPages
Definition: precomp.h:155

◆ LocalWritePrinter()

BOOL WINAPI LocalWritePrinter ( HANDLE  hPrinter,
PVOID  pBuf,
DWORD  cbBuf,
PDWORD  pcWritten 
)

Definition at line 1758 of file printers.c.

1759{
1760 BOOL bReturnValue;
1761 DWORD dwErrorCode;
1762 PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
1763 PLOCAL_PORT_HANDLE pPortHandle;
1764 PLOCAL_PRINTER_HANDLE pPrinterHandle;
1765
1766 TRACE("LocalWritePrinter(%p, %p, %lu, %p)\n", hPrinter, pBuf, cbBuf, pcWritten);
1767
1768 // Sanity checks.
1769 if (!pHandle)
1770 {
1771 dwErrorCode = ERROR_INVALID_HANDLE;
1772 goto Cleanup;
1773 }
1774
1775 // Port handles are an entirely different thing.
1776 if (pHandle->HandleType == HandleType_Port)
1777 {
1778 pPortHandle = (PLOCAL_PORT_HANDLE)pHandle->pSpecificHandle;
1779
1780 // Call the monitor's WritePort function.
1781 if (pPortHandle->pPort->pPrintMonitor->bIsLevel2)
1782 bReturnValue = ((PMONITOR2)pPortHandle->pPort->pPrintMonitor->pMonitor)->pfnWritePort(pPortHandle->hPort, pBuf, cbBuf, pcWritten);
1783 else
1784 bReturnValue = ((LPMONITOREX)pPortHandle->pPort->pPrintMonitor->pMonitor)->Monitor.pfnWritePort(pPortHandle->hPort, pBuf, cbBuf, pcWritten);
1785
1786 if (!bReturnValue)
1787 {
1788 // The WritePort function failed. Return its last error.
1789 dwErrorCode = GetLastError();
1790 goto Cleanup;
1791 }
1792
1793 // We were successful!
1794 dwErrorCode = ERROR_SUCCESS;
1795 goto Cleanup;
1796 }
1797
1798 // The remaining function deals with Printer handles only.
1799 if (pHandle->HandleType != HandleType_Printer)
1800 {
1801 dwErrorCode = ERROR_INVALID_HANDLE;
1802 goto Cleanup;
1803 }
1804
1805 pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle;
1806
1807 // We require StartDocPrinter or AddJob to be called first.
1808 if (!pPrinterHandle->bStartedDoc)
1809 {
1810 dwErrorCode = ERROR_SPL_NO_STARTDOC;
1811 goto Cleanup;
1812 }
1813
1814 // TODO: This function is only called when doing non-spooled printing.
1815 // This needs to be investigated further. We can't just use pPrinterHandle->hSPLFile here, because that's currently reserved for Printer Job handles (see LocalReadPrinter).
1816#if 0
1817 // Pass the parameters to WriteFile.
1818 if (!WriteFile(SOME_SPOOL_FILE_HANDLE, pBuf, cbBuf, pcWritten, NULL))
1819 {
1820 dwErrorCode = GetLastError();
1821 ERR("WriteFile failed with error %lu!\n", GetLastError());
1822 goto Cleanup;
1823 }
1824#endif
1825
1826 dwErrorCode = ERROR_SUCCESS;
1827
1828Cleanup:
1829 SetLastError(dwErrorCode);
1830 return (dwErrorCode == ERROR_SUCCESS);
1831}
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24

Variable Documentation

◆ dwDeviceNotSelectedTimeout

const DWORD dwDeviceNotSelectedTimeout = 15000
static

These values serve no purpose anymore, but are still used in PRINTER_INFO_5 and HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\PrinterPorts

Definition at line 80 of file printers.c.

Referenced by _LocalGetPrinterLevel5().

◆ dwPrinterInfo0Offsets

DWORD dwPrinterInfo0Offsets[]
static
Initial value:
= {
}
#define MAXDWORD
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255

Definition at line 41 of file printers.c.

Referenced by _LocalGetPrinterLevel0().

◆ dwPrinterInfo1Offsets

DWORD dwPrinterInfo1Offsets[]
static

◆ dwPrinterInfo2Offsets

DWORD dwPrinterInfo2Offsets[]
static
Initial value:

Definition at line 53 of file printers.c.

Referenced by _LocalGetPrinterLevel2().

◆ dwPrinterInfo4Offsets

DWORD dwPrinterInfo4Offsets[]
static
Initial value:

Definition at line 67 of file printers.c.

Referenced by _LocalGetPrinterLevel4().

◆ dwPrinterInfo5Offsets

DWORD dwPrinterInfo5Offsets[]
static
Initial value:

Definition at line 72 of file printers.c.

Referenced by _LocalGetPrinterLevel5().

◆ dwTransmissionRetryTimeout

const DWORD dwTransmissionRetryTimeout = 45000
static

Definition at line 81 of file printers.c.

Referenced by _LocalGetPrinterLevel5().

◆ pfnGetPrinterLevels

const PLocalGetPrinterLevelFunc pfnGetPrinterLevels[]
static
Initial value:
= {
}
static void _LocalGetPrinterLevel1(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_1W *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
Definition: printers.c:556
void(* PLocalGetPrinterLevelFunc)(PLOCAL_PRINTER, PVOID, PBYTE *, PDWORD, DWORD, PCWSTR)
Definition: printers.c:26
static void _LocalGetPrinterLevel0(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_STRESS *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
Definition: printers.c:509
static void _LocalGetPrinterLevel8(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_8W *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
Definition: printers.c:836
static void _LocalGetPrinterLevel6(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_6 *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
Definition: printers.c:801
static void _LocalGetPrinterLevel7(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_7W *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
Definition: printers.c:817
static void _LocalGetPrinterLevel5(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_5W *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
Definition: printers.c:760
static void _LocalGetPrinterLevel3(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_3 *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
Definition: printers.c:704
static void _LocalGetPrinterLevel4(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_4W *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
Definition: printers.c:726
static void _LocalGetPrinterLevel2(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_2W *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
Definition: printers.c:611
static void _LocalGetPrinterLevel9(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_9W *ppPrinterInfo, PBYTE *ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PCWSTR wszComputerName)
Definition: printers.c:859

Definition at line 28 of file printers.c.

Referenced by LocalEnumPrinters(), and LocalGetPrinter().

◆ PrinterList