[Printing] Update and Add Functions

More forwards to LocalSpl and LocalMon. At sometime will be merged together.
Bug fixes.
Printer Driver code is a wine hack. (WIP)
Added information for shell tray icon notifications.
Sync wine WinSpool driver tests. Unplugged from build.
This commit is contained in:
James Tabor 2020-08-26 17:12:20 -05:00
parent 22fb1e947d
commit 62c4b828b4
54 changed files with 6000 additions and 564 deletions

View file

@ -120,22 +120,6 @@ static BOOL is_access_denied(DWORD res, DWORD lasterror)
return FALSE;
}
static BOOL on_win9x = FALSE;
static BOOL check_win9x(void)
{
if (pGetPrinterW)
{
SetLastError(0xdeadbeef);
pGetPrinterW(NULL, 0, NULL, 0, NULL);
return (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED);
}
else
{
return TRUE;
}
}
static void find_default_printer(VOID)
{
static char buffer[DEFAULT_PRINTER_SIZE];
@ -333,8 +317,6 @@ static void test_AddMonitor(void)
"returned %d with %d (expected '0' with ERROR_INVALID_LEVEL)\n",
res, GetLastError());
if (0)
{
/* This test crashes win9x on vmware (works with win9x on qemu 0.8.1) */
SetLastError(MAGIC_DEAD);
res = AddMonitorA(NULL, 2, NULL);
@ -344,7 +326,6 @@ static void test_AddMonitor(void)
(GetLastError() == ERROR_PRIVILEGE_NOT_HELD)),
"returned %d with %d (expected '0' with: MAGIC_DEAD or "
"ERROR_PRIVILEGE_NOT_HELD)\n", res, GetLastError());
}
ZeroMemory(&mi2a, sizeof(MONITOR_INFO_2A));
SetLastError(MAGIC_DEAD);
@ -1219,7 +1200,7 @@ static void test_EnumPrinterDrivers(void)
}
/* EnumPrinterDriversA returns the same number of bytes as EnumPrinterDriversW */
if (!on_win9x && pEnumPrinterDriversW)
if (pEnumPrinterDriversW)
{
DWORD double_needed;
DWORD double_returned;
@ -1407,15 +1388,14 @@ static void test_EnumPrintProcessors(void)
/* failure-Codes for NULL */
if (0) {
/* this test crashes on win98se */
SetLastError(0xdeadbeef);
pcbNeeded = 0xdeadbeef;
pcReturned = 0xdeadbeef;
res = EnumPrintProcessorsA(NULL, NULL, 1, NULL, cbBuf, &pcbNeeded, &pcReturned);
ok( !res && (GetLastError() == ERROR_INVALID_USER_BUFFER) ,
"got %u with %u (expected '0' with ERROR_INVALID_USER_BUFFER)\n",
res, GetLastError());
SetLastError(0xdeadbeef);
pcbNeeded = 0xdeadbeef;
pcReturned = 0xdeadbeef;
res = EnumPrintProcessorsA(NULL, NULL, 1, NULL, cbBuf, &pcbNeeded, &pcReturned);
todo_wine {
ok( !res && (GetLastError() == ERROR_INVALID_USER_BUFFER) ,
"got %u with %u (expected '0' with ERROR_INVALID_USER_BUFFER)\n",
res, GetLastError());
}
SetLastError(0xdeadbeef);
@ -1982,7 +1962,7 @@ static void test_SetDefaultPrinter(void)
}
if (!pSetDefaultPrinterA) return;
/* only supported on win2k and above */
/* only supported on win2k and above */
/* backup the original value */
org_value[0] = '\0';
@ -2356,7 +2336,7 @@ static void test_GetPrinter(void)
ok(needed > 0,"not expected needed buffer size %d\n", needed);
/* GetPrinterA returns the same number of bytes as GetPrinterW */
if (!on_win9x && !ret && pGetPrinterW && level != 6 && level != 7)
if (!ret && pGetPrinterW && level != 6 && level != 7)
{
DWORD double_needed;
ret = pGetPrinterW(hprn, level, NULL, 0, &double_needed);
@ -2408,9 +2388,6 @@ static void test_GetPrinterData(void)
res = OpenPrinterA(NULL, &hprn, NULL);
if (!res)
{
/* printserver not available on win9x */
if (!on_win9x)
win_skip("Unable to open the printserver: %d\n", GetLastError());
return;
}
@ -2593,7 +2570,7 @@ static void test_GetPrinterDriver(void)
}
/* GetPrinterDriverA returns the same number of bytes as GetPrinterDriverW */
if (!on_win9x && !ret && pGetPrinterDriverW)
if (!ret && pGetPrinterDriverW)
{
DWORD double_needed;
ret = pGetPrinterDriverW(hprn, NULL, level, NULL, 0, &double_needed);
@ -2961,7 +2938,7 @@ static void test_OpenPrinter_defaults(void)
ret = GetJobA( printer, add_job->JobId, 2, (BYTE *)job_info, needed, &needed );
ok( ret, "GetJobA() failed le=%d\n", GetLastError() );
todo_wine
todo_wine
ok( job_info->pDevMode != NULL, "got NULL DEVMODEA\n");
if (job_info->pDevMode)
ok( job_info->pDevMode->u1.s1.dmPaperSize == default_size, "got %d default %d\n",
@ -3081,10 +3058,6 @@ START_TEST(info)
pSetDefaultPrinterA = (void *) GetProcAddress(hwinspool, "SetDefaultPrinterA");
pXcvDataW = (void *) GetProcAddress(hwinspool, "XcvDataW");
on_win9x = check_win9x();
if (on_win9x)
win_skip("Several W-functions are not available on Win9x/WinMe\n");
find_default_printer();
find_local_server();
find_tempfile();
@ -3101,20 +3074,10 @@ START_TEST(info)
test_EnumForms(NULL);
if (default_printer) test_EnumForms(default_printer);
test_EnumMonitors();
if (!winetest_interactive)
skip("ROSTESTS-211: Skipping test_EnumPorts().\n");
else
test_EnumPorts();
test_EnumPorts();
test_EnumPrinterDrivers();
test_EnumPrinters();
if (!winetest_interactive)
skip("ROSTESTS-211: Skipping test_EnumPrintProcessors().\n");
else
test_EnumPrintProcessors();
test_EnumPrintProcessors();
test_GetDefaultPrinter();
test_GetPrinterDriverDirectory();
test_GetPrintProcessorDirectory();

View file

@ -351,55 +351,55 @@ extern "C" {
#define JOB_POSITION_UNSPECIFIED 0
typedef struct _ADDJOB_INFO_1A {
typedef struct _ADDJOB_INFO_1A {
LPSTR Path;
DWORD JobId;
} ADDJOB_INFO_1A,*PADDJOB_INFO_1A,*LPADDJOB_INFO_1A;
} ADDJOB_INFO_1A,*PADDJOB_INFO_1A,*LPADDJOB_INFO_1A;
typedef struct _ADDJOB_INFO_1W {
typedef struct _ADDJOB_INFO_1W {
LPWSTR Path;
DWORD JobId;
} ADDJOB_INFO_1W,*PADDJOB_INFO_1W,*LPADDJOB_INFO_1W;
} ADDJOB_INFO_1W,*PADDJOB_INFO_1W,*LPADDJOB_INFO_1W;
__MINGW_TYPEDEF_AW(ADDJOB_INFO_1)
__MINGW_TYPEDEF_AW(PADDJOB_INFO_1)
__MINGW_TYPEDEF_AW(LPADDJOB_INFO_1)
__MINGW_TYPEDEF_AW(ADDJOB_INFO_1)
__MINGW_TYPEDEF_AW(PADDJOB_INFO_1)
__MINGW_TYPEDEF_AW(LPADDJOB_INFO_1)
typedef struct _DRIVER_INFO_1A {
typedef struct _DRIVER_INFO_1A {
LPSTR pName;
} DRIVER_INFO_1A,*PDRIVER_INFO_1A,*LPDRIVER_INFO_1A;
} DRIVER_INFO_1A,*PDRIVER_INFO_1A,*LPDRIVER_INFO_1A;
typedef struct _DRIVER_INFO_1W {
typedef struct _DRIVER_INFO_1W {
LPWSTR pName;
} DRIVER_INFO_1W,*PDRIVER_INFO_1W,*LPDRIVER_INFO_1W;
} DRIVER_INFO_1W,*PDRIVER_INFO_1W,*LPDRIVER_INFO_1W;
__MINGW_TYPEDEF_AW(DRIVER_INFO_1)
__MINGW_TYPEDEF_AW(PDRIVER_INFO_1)
__MINGW_TYPEDEF_AW(LPDRIVER_INFO_1)
__MINGW_TYPEDEF_AW(DRIVER_INFO_1)
__MINGW_TYPEDEF_AW(PDRIVER_INFO_1)
__MINGW_TYPEDEF_AW(LPDRIVER_INFO_1)
typedef struct _DRIVER_INFO_2A {
typedef struct _DRIVER_INFO_2A {
DWORD cVersion;
LPSTR pName;
LPSTR pEnvironment;
LPSTR pDriverPath;
LPSTR pDataFile;
LPSTR pConfigFile;
} DRIVER_INFO_2A,*PDRIVER_INFO_2A,*LPDRIVER_INFO_2A;
} DRIVER_INFO_2A,*PDRIVER_INFO_2A,*LPDRIVER_INFO_2A;
typedef struct _DRIVER_INFO_2W {
typedef struct _DRIVER_INFO_2W {
DWORD cVersion;
LPWSTR pName;
LPWSTR pEnvironment;
LPWSTR pDriverPath;
LPWSTR pDataFile;
LPWSTR pConfigFile;
} DRIVER_INFO_2W,*PDRIVER_INFO_2W,*LPDRIVER_INFO_2W;
} DRIVER_INFO_2W,*PDRIVER_INFO_2W,*LPDRIVER_INFO_2W;
__MINGW_TYPEDEF_AW(DRIVER_INFO_2)
__MINGW_TYPEDEF_AW(PDRIVER_INFO_2)
__MINGW_TYPEDEF_AW(LPDRIVER_INFO_2)
__MINGW_TYPEDEF_AW(DRIVER_INFO_2)
__MINGW_TYPEDEF_AW(PDRIVER_INFO_2)
__MINGW_TYPEDEF_AW(LPDRIVER_INFO_2)
typedef struct _DRIVER_INFO_3A {
typedef struct _DRIVER_INFO_3A {
DWORD cVersion;
LPSTR pName;
LPSTR pEnvironment;
@ -410,9 +410,9 @@ extern "C" {
LPSTR pDependentFiles;
LPSTR pMonitorName;
LPSTR pDefaultDataType;
} DRIVER_INFO_3A,*PDRIVER_INFO_3A,*LPDRIVER_INFO_3A;
} DRIVER_INFO_3A,*PDRIVER_INFO_3A,*LPDRIVER_INFO_3A;
typedef struct _DRIVER_INFO_3W {
typedef struct _DRIVER_INFO_3W {
DWORD cVersion;
LPWSTR pName;
LPWSTR pEnvironment;
@ -423,13 +423,13 @@ extern "C" {
LPWSTR pDependentFiles;
LPWSTR pMonitorName;
LPWSTR pDefaultDataType;
} DRIVER_INFO_3W,*PDRIVER_INFO_3W,*LPDRIVER_INFO_3W;
} DRIVER_INFO_3W,*PDRIVER_INFO_3W,*LPDRIVER_INFO_3W;
__MINGW_TYPEDEF_AW(DRIVER_INFO_3)
__MINGW_TYPEDEF_AW(PDRIVER_INFO_3)
__MINGW_TYPEDEF_AW(LPDRIVER_INFO_3)
__MINGW_TYPEDEF_AW(DRIVER_INFO_3)
__MINGW_TYPEDEF_AW(PDRIVER_INFO_3)
__MINGW_TYPEDEF_AW(LPDRIVER_INFO_3)
typedef struct _DRIVER_INFO_4A {
typedef struct _DRIVER_INFO_4A {
DWORD cVersion;
LPSTR pName;
LPSTR pEnvironment;
@ -441,9 +441,9 @@ extern "C" {
LPSTR pMonitorName;
LPSTR pDefaultDataType;
LPSTR pszzPreviousNames;
} DRIVER_INFO_4A,*PDRIVER_INFO_4A,*LPDRIVER_INFO_4A;
} DRIVER_INFO_4A,*PDRIVER_INFO_4A,*LPDRIVER_INFO_4A;
typedef struct _DRIVER_INFO_4W {
typedef struct _DRIVER_INFO_4W {
DWORD cVersion;
LPWSTR pName;
LPWSTR pEnvironment;
@ -455,13 +455,13 @@ extern "C" {
LPWSTR pMonitorName;
LPWSTR pDefaultDataType;
LPWSTR pszzPreviousNames;
} DRIVER_INFO_4W,*PDRIVER_INFO_4W,*LPDRIVER_INFO_4W;
} DRIVER_INFO_4W,*PDRIVER_INFO_4W,*LPDRIVER_INFO_4W;
__MINGW_TYPEDEF_AW(DRIVER_INFO_4)
__MINGW_TYPEDEF_AW(PDRIVER_INFO_4)
__MINGW_TYPEDEF_AW(LPDRIVER_INFO_4)
__MINGW_TYPEDEF_AW(DRIVER_INFO_4)
__MINGW_TYPEDEF_AW(PDRIVER_INFO_4)
__MINGW_TYPEDEF_AW(LPDRIVER_INFO_4)
typedef struct _DRIVER_INFO_5A {
typedef struct _DRIVER_INFO_5A {
DWORD cVersion;
LPSTR pName;
LPSTR pEnvironment;
@ -471,9 +471,9 @@ extern "C" {
DWORD dwDriverAttributes;
DWORD dwConfigVersion;
DWORD dwDriverVersion;
} DRIVER_INFO_5A,*PDRIVER_INFO_5A,*LPDRIVER_INFO_5A;
} DRIVER_INFO_5A,*PDRIVER_INFO_5A,*LPDRIVER_INFO_5A;
typedef struct _DRIVER_INFO_5W {
typedef struct _DRIVER_INFO_5W {
DWORD cVersion;
LPWSTR pName;
LPWSTR pEnvironment;
@ -483,13 +483,13 @@ extern "C" {
DWORD dwDriverAttributes;
DWORD dwConfigVersion;
DWORD dwDriverVersion;
} DRIVER_INFO_5W,*PDRIVER_INFO_5W,*LPDRIVER_INFO_5W;
} DRIVER_INFO_5W,*PDRIVER_INFO_5W,*LPDRIVER_INFO_5W;
__MINGW_TYPEDEF_AW(DRIVER_INFO_5)
__MINGW_TYPEDEF_AW(PDRIVER_INFO_5)
__MINGW_TYPEDEF_AW(LPDRIVER_INFO_5)
__MINGW_TYPEDEF_AW(DRIVER_INFO_5)
__MINGW_TYPEDEF_AW(PDRIVER_INFO_5)
__MINGW_TYPEDEF_AW(LPDRIVER_INFO_5)
typedef struct _DRIVER_INFO_6A {
typedef struct _DRIVER_INFO_6A {
DWORD cVersion;
LPSTR pName;
LPSTR pEnvironment;
@ -507,9 +507,9 @@ extern "C" {
LPSTR pszOEMUrl;
LPSTR pszHardwareID;
LPSTR pszProvider;
} DRIVER_INFO_6A,*PDRIVER_INFO_6A,*LPDRIVER_INFO_6A;
} DRIVER_INFO_6A,*PDRIVER_INFO_6A,*LPDRIVER_INFO_6A;
typedef struct _DRIVER_INFO_6W {
typedef struct _DRIVER_INFO_6W {
DWORD cVersion;
LPWSTR pName;
LPWSTR pEnvironment;
@ -527,11 +527,11 @@ extern "C" {
LPWSTR pszOEMUrl;
LPWSTR pszHardwareID;
LPWSTR pszProvider;
} DRIVER_INFO_6W,*PDRIVER_INFO_6W,*LPDRIVER_INFO_6W;
} DRIVER_INFO_6W,*PDRIVER_INFO_6W,*LPDRIVER_INFO_6W;
__MINGW_TYPEDEF_AW(DRIVER_INFO_6)
__MINGW_TYPEDEF_AW(PDRIVER_INFO_6)
__MINGW_TYPEDEF_AW(LPDRIVER_INFO_6)
__MINGW_TYPEDEF_AW(DRIVER_INFO_6)
__MINGW_TYPEDEF_AW(PDRIVER_INFO_6)
__MINGW_TYPEDEF_AW(LPDRIVER_INFO_6)
typedef struct _DRIVER_INFO_8W {
DWORD cVersion;
@ -606,39 +606,39 @@ __MINGW_TYPEDEF_AW(LPDRIVER_INFO_8)
#define APD_COPY_NEW_FILES 0x00000008
#define APD_COPY_FROM_DIRECTORY 0x00000010
typedef struct _DOC_INFO_1A {
typedef struct _DOC_INFO_1A {
LPSTR pDocName;
LPSTR pOutputFile;
LPSTR pDatatype;
} DOC_INFO_1A,*PDOC_INFO_1A,*LPDOC_INFO_1A;
} DOC_INFO_1A,*PDOC_INFO_1A,*LPDOC_INFO_1A;
typedef struct _DOC_INFO_1W {
typedef struct _DOC_INFO_1W {
LPWSTR pDocName;
LPWSTR pOutputFile;
LPWSTR pDatatype;
} DOC_INFO_1W,*PDOC_INFO_1W,*LPDOC_INFO_1W;
} DOC_INFO_1W,*PDOC_INFO_1W,*LPDOC_INFO_1W;
__MINGW_TYPEDEF_AW(DOC_INFO_1)
__MINGW_TYPEDEF_AW(PDOC_INFO_1)
__MINGW_TYPEDEF_AW(LPDOC_INFO_1)
__MINGW_TYPEDEF_AW(DOC_INFO_1)
__MINGW_TYPEDEF_AW(PDOC_INFO_1)
__MINGW_TYPEDEF_AW(LPDOC_INFO_1)
typedef struct _FORM_INFO_1A {
typedef struct _FORM_INFO_1A {
DWORD Flags;
LPSTR pName;
SIZEL Size;
RECTL ImageableArea;
} FORM_INFO_1A,*PFORM_INFO_1A,*LPFORM_INFO_1A;
} FORM_INFO_1A,*PFORM_INFO_1A,*LPFORM_INFO_1A;
typedef struct _FORM_INFO_1W {
typedef struct _FORM_INFO_1W {
DWORD Flags;
LPWSTR pName;
SIZEL Size;
RECTL ImageableArea;
} FORM_INFO_1W,*PFORM_INFO_1W,*LPFORM_INFO_1W;
} FORM_INFO_1W,*PFORM_INFO_1W,*LPFORM_INFO_1W;
__MINGW_TYPEDEF_AW(FORM_INFO_1)
__MINGW_TYPEDEF_AW(PFORM_INFO_1)
__MINGW_TYPEDEF_AW(LPFORM_INFO_1)
__MINGW_TYPEDEF_AW(FORM_INFO_1)
__MINGW_TYPEDEF_AW(PFORM_INFO_1)
__MINGW_TYPEDEF_AW(LPFORM_INFO_1)
typedef struct _FORM_INFO_2A {
DWORD Flags;
@ -669,46 +669,50 @@ typedef struct _FORM_INFO_2W {
__MINGW_TYPEDEF_AW(FORM_INFO_2)
__MINGW_TYPEDEF_AW(PFORM_INFO_2)
typedef struct _DOC_INFO_2A {
#define STRING_NONE 0x00000001
#define STRING_MUIDLL 0x00000002
#define STRING_LANGPAIR 0x00000004
typedef struct _DOC_INFO_2A {
LPSTR pDocName;
LPSTR pOutputFile;
LPSTR pDatatype;
DWORD dwMode;
DWORD JobId;
} DOC_INFO_2A,*PDOC_INFO_2A,*LPDOC_INFO_2A;
} DOC_INFO_2A,*PDOC_INFO_2A,*LPDOC_INFO_2A;
typedef struct _DOC_INFO_2W {
typedef struct _DOC_INFO_2W {
LPWSTR pDocName;
LPWSTR pOutputFile;
LPWSTR pDatatype;
DWORD dwMode;
DWORD JobId;
} DOC_INFO_2W,*PDOC_INFO_2W,*LPDOC_INFO_2W;
} DOC_INFO_2W,*PDOC_INFO_2W,*LPDOC_INFO_2W;
__MINGW_TYPEDEF_AW(DOC_INFO_2)
__MINGW_TYPEDEF_AW(PDOC_INFO_2)
__MINGW_TYPEDEF_AW(LPDOC_INFO_2)
__MINGW_TYPEDEF_AW(DOC_INFO_2)
__MINGW_TYPEDEF_AW(PDOC_INFO_2)
__MINGW_TYPEDEF_AW(LPDOC_INFO_2)
#define DI_CHANNEL 1
#define DI_READ_SPOOL_JOB 3
typedef struct _DOC_INFO_3A {
typedef struct _DOC_INFO_3A {
LPSTR pDocName;
LPSTR pOutputFile;
LPSTR pDatatype;
DWORD dwFlags;
} DOC_INFO_3A,*PDOC_INFO_3A,*LPDOC_INFO_3A;
} DOC_INFO_3A,*PDOC_INFO_3A,*LPDOC_INFO_3A;
typedef struct _DOC_INFO_3W {
typedef struct _DOC_INFO_3W {
LPWSTR pDocName;
LPWSTR pOutputFile;
LPWSTR pDatatype;
DWORD dwFlags;
} DOC_INFO_3W,*PDOC_INFO_3W,*LPDOC_INFO_3W;
} DOC_INFO_3W,*PDOC_INFO_3W,*LPDOC_INFO_3W;
__MINGW_TYPEDEF_AW(DOC_INFO_3)
__MINGW_TYPEDEF_AW(PDOC_INFO_3)
__MINGW_TYPEDEF_AW(LPDOC_INFO_3)
__MINGW_TYPEDEF_AW(DOC_INFO_3)
__MINGW_TYPEDEF_AW(PDOC_INFO_3)
__MINGW_TYPEDEF_AW(LPDOC_INFO_3)
#define DI_MEMORYMAP_WRITE 0x00000001
@ -716,79 +720,79 @@ __MINGW_TYPEDEF_AW(PFORM_INFO_2)
#define FORM_BUILTIN 0x00000001
#define FORM_PRINTER 0x00000002
typedef struct _PRINTPROCESSOR_INFO_1A {
typedef struct _PRINTPROCESSOR_INFO_1A {
LPSTR pName;
} PRINTPROCESSOR_INFO_1A,*PPRINTPROCESSOR_INFO_1A,*LPPRINTPROCESSOR_INFO_1A;
} PRINTPROCESSOR_INFO_1A,*PPRINTPROCESSOR_INFO_1A,*LPPRINTPROCESSOR_INFO_1A;
typedef struct _PRINTPROCESSOR_INFO_1W {
typedef struct _PRINTPROCESSOR_INFO_1W {
LPWSTR pName;
} PRINTPROCESSOR_INFO_1W,*PPRINTPROCESSOR_INFO_1W,*LPPRINTPROCESSOR_INFO_1W;
} PRINTPROCESSOR_INFO_1W,*PPRINTPROCESSOR_INFO_1W,*LPPRINTPROCESSOR_INFO_1W;
__MINGW_TYPEDEF_AW(PRINTPROCESSOR_INFO_1)
__MINGW_TYPEDEF_AW(PPRINTPROCESSOR_INFO_1)
__MINGW_TYPEDEF_AW(LPPRINTPROCESSOR_INFO_1)
__MINGW_TYPEDEF_AW(PRINTPROCESSOR_INFO_1)
__MINGW_TYPEDEF_AW(PPRINTPROCESSOR_INFO_1)
__MINGW_TYPEDEF_AW(LPPRINTPROCESSOR_INFO_1)
typedef struct _PRINTPROCESSOR_CAPS_1 {
typedef struct _PRINTPROCESSOR_CAPS_1 {
DWORD dwLevel;
DWORD dwNupOptions;
DWORD dwPageOrderFlags;
DWORD dwNumberOfCopies;
} PRINTPROCESSOR_CAPS_1,*PPRINTPROCESSOR_CAPS_1;
} PRINTPROCESSOR_CAPS_1,*PPRINTPROCESSOR_CAPS_1;
#define NORMAL_PRINT 0x00000000
#define REVERSE_PRINT 0x00000001
typedef struct _PORT_INFO_1A {
typedef struct _PORT_INFO_1A {
LPSTR pName;
} PORT_INFO_1A,*PPORT_INFO_1A,*LPPORT_INFO_1A;
typedef struct _PORT_INFO_1W {
} PORT_INFO_1A,*PPORT_INFO_1A,*LPPORT_INFO_1A;
typedef struct _PORT_INFO_1W {
LPWSTR pName;
} PORT_INFO_1W,*PPORT_INFO_1W,*LPPORT_INFO_1W;
} PORT_INFO_1W,*PPORT_INFO_1W,*LPPORT_INFO_1W;
__MINGW_TYPEDEF_AW(PORT_INFO_1)
__MINGW_TYPEDEF_AW(PPORT_INFO_1)
__MINGW_TYPEDEF_AW(LPPORT_INFO_1)
__MINGW_TYPEDEF_AW(PORT_INFO_1)
__MINGW_TYPEDEF_AW(PPORT_INFO_1)
__MINGW_TYPEDEF_AW(LPPORT_INFO_1)
typedef struct _PORT_INFO_2A {
typedef struct _PORT_INFO_2A {
LPSTR pPortName;
LPSTR pMonitorName;
LPSTR pDescription;
DWORD fPortType;
DWORD Reserved;
} PORT_INFO_2A,*PPORT_INFO_2A,*LPPORT_INFO_2A;
} PORT_INFO_2A,*PPORT_INFO_2A,*LPPORT_INFO_2A;
typedef struct _PORT_INFO_2W {
typedef struct _PORT_INFO_2W {
LPWSTR pPortName;
LPWSTR pMonitorName;
LPWSTR pDescription;
DWORD fPortType;
DWORD Reserved;
} PORT_INFO_2W,*PPORT_INFO_2W,*LPPORT_INFO_2W;
} PORT_INFO_2W,*PPORT_INFO_2W,*LPPORT_INFO_2W;
__MINGW_TYPEDEF_AW(PORT_INFO_2)
__MINGW_TYPEDEF_AW(PPORT_INFO_2)
__MINGW_TYPEDEF_AW(LPPORT_INFO_2)
__MINGW_TYPEDEF_AW(PORT_INFO_2)
__MINGW_TYPEDEF_AW(PPORT_INFO_2)
__MINGW_TYPEDEF_AW(LPPORT_INFO_2)
#define PORT_TYPE_WRITE 0x0001
#define PORT_TYPE_READ 0x0002
#define PORT_TYPE_REDIRECTED 0x0004
#define PORT_TYPE_NET_ATTACHED 0x0008
typedef struct _PORT_INFO_3A {
typedef struct _PORT_INFO_3A {
DWORD dwStatus;
LPSTR pszStatus;
DWORD dwSeverity;
} PORT_INFO_3A,*PPORT_INFO_3A,*LPPORT_INFO_3A;
} PORT_INFO_3A,*PPORT_INFO_3A,*LPPORT_INFO_3A;
typedef struct _PORT_INFO_3W {
typedef struct _PORT_INFO_3W {
DWORD dwStatus;
LPWSTR pszStatus;
DWORD dwSeverity;
} PORT_INFO_3W,*PPORT_INFO_3W,*LPPORT_INFO_3W;
} PORT_INFO_3W,*PPORT_INFO_3W,*LPPORT_INFO_3W;
__MINGW_TYPEDEF_AW(PORT_INFO_3)
__MINGW_TYPEDEF_AW(PPORT_INFO_3)
__MINGW_TYPEDEF_AW(LPPORT_INFO_3)
__MINGW_TYPEDEF_AW(PORT_INFO_3)
__MINGW_TYPEDEF_AW(PPORT_INFO_3)
__MINGW_TYPEDEF_AW(LPPORT_INFO_3)
#define PORT_STATUS_TYPE_ERROR 1
#define PORT_STATUS_TYPE_WARNING 2
@ -807,86 +811,86 @@ __MINGW_TYPEDEF_AW(PFORM_INFO_2)
#define PORT_STATUS_WARMING_UP 11
#define PORT_STATUS_POWER_SAVE 12
typedef struct _MONITOR_INFO_1A{
typedef struct _MONITOR_INFO_1A{
LPSTR pName;
} MONITOR_INFO_1A,*PMONITOR_INFO_1A,*LPMONITOR_INFO_1A;
} MONITOR_INFO_1A,*PMONITOR_INFO_1A,*LPMONITOR_INFO_1A;
typedef struct _MONITOR_INFO_1W{
typedef struct _MONITOR_INFO_1W{
LPWSTR pName;
} MONITOR_INFO_1W,*PMONITOR_INFO_1W,*LPMONITOR_INFO_1W;
} MONITOR_INFO_1W,*PMONITOR_INFO_1W,*LPMONITOR_INFO_1W;
__MINGW_TYPEDEF_AW(MONITOR_INFO_1)
__MINGW_TYPEDEF_AW(PMONITOR_INFO_1)
__MINGW_TYPEDEF_AW(LPMONITOR_INFO_1)
__MINGW_TYPEDEF_AW(MONITOR_INFO_1)
__MINGW_TYPEDEF_AW(PMONITOR_INFO_1)
__MINGW_TYPEDEF_AW(LPMONITOR_INFO_1)
typedef struct _MONITOR_INFO_2A {
typedef struct _MONITOR_INFO_2A {
LPSTR pName;
LPSTR pEnvironment;
LPSTR pDLLName;
} MONITOR_INFO_2A,*PMONITOR_INFO_2A,*LPMONITOR_INFO_2A;
} MONITOR_INFO_2A,*PMONITOR_INFO_2A,*LPMONITOR_INFO_2A;
typedef struct _MONITOR_INFO_2W {
typedef struct _MONITOR_INFO_2W {
LPWSTR pName;
LPWSTR pEnvironment;
LPWSTR pDLLName;
} MONITOR_INFO_2W,*PMONITOR_INFO_2W,*LPMONITOR_INFO_2W;
} MONITOR_INFO_2W,*PMONITOR_INFO_2W,*LPMONITOR_INFO_2W;
__MINGW_TYPEDEF_AW(MONITOR_INFO_2)
__MINGW_TYPEDEF_AW(PMONITOR_INFO_2)
__MINGW_TYPEDEF_AW(LPMONITOR_INFO_2)
__MINGW_TYPEDEF_AW(MONITOR_INFO_2)
__MINGW_TYPEDEF_AW(PMONITOR_INFO_2)
__MINGW_TYPEDEF_AW(LPMONITOR_INFO_2)
typedef struct _DATATYPES_INFO_1A {
typedef struct _DATATYPES_INFO_1A {
LPSTR pName;
} DATATYPES_INFO_1A,*PDATATYPES_INFO_1A,*LPDATATYPES_INFO_1A;
} DATATYPES_INFO_1A,*PDATATYPES_INFO_1A,*LPDATATYPES_INFO_1A;
typedef struct _DATATYPES_INFO_1W {
typedef struct _DATATYPES_INFO_1W {
LPWSTR pName;
} DATATYPES_INFO_1W,*PDATATYPES_INFO_1W,*LPDATATYPES_INFO_1W;
} DATATYPES_INFO_1W,*PDATATYPES_INFO_1W,*LPDATATYPES_INFO_1W;
__MINGW_TYPEDEF_AW(DATATYPES_INFO_1)
__MINGW_TYPEDEF_AW(PDATATYPES_INFO_1)
__MINGW_TYPEDEF_AW(LPDATATYPES_INFO_1)
__MINGW_TYPEDEF_AW(DATATYPES_INFO_1)
__MINGW_TYPEDEF_AW(PDATATYPES_INFO_1)
__MINGW_TYPEDEF_AW(LPDATATYPES_INFO_1)
typedef struct _PRINTER_DEFAULTSA {
typedef struct _PRINTER_DEFAULTSA {
LPSTR pDatatype;
LPDEVMODEA pDevMode;
ACCESS_MASK DesiredAccess;
} PRINTER_DEFAULTSA,*PPRINTER_DEFAULTSA,*LPPRINTER_DEFAULTSA;
} PRINTER_DEFAULTSA,*PPRINTER_DEFAULTSA,*LPPRINTER_DEFAULTSA;
typedef struct _PRINTER_DEFAULTSW {
typedef struct _PRINTER_DEFAULTSW {
LPWSTR pDatatype;
LPDEVMODEW pDevMode;
ACCESS_MASK DesiredAccess;
} PRINTER_DEFAULTSW,*PPRINTER_DEFAULTSW,*LPPRINTER_DEFAULTSW;
} PRINTER_DEFAULTSW,*PPRINTER_DEFAULTSW,*LPPRINTER_DEFAULTSW;
__MINGW_TYPEDEF_AW(PRINTER_DEFAULTS)
__MINGW_TYPEDEF_AW(PPRINTER_DEFAULTS)
__MINGW_TYPEDEF_AW(LPPRINTER_DEFAULTS)
__MINGW_TYPEDEF_AW(PRINTER_DEFAULTS)
__MINGW_TYPEDEF_AW(PPRINTER_DEFAULTS)
__MINGW_TYPEDEF_AW(LPPRINTER_DEFAULTS)
typedef struct _PRINTER_ENUM_VALUESA {
typedef struct _PRINTER_ENUM_VALUESA {
LPSTR pValueName;
DWORD cbValueName;
DWORD dwType;
LPBYTE pData;
DWORD cbData;
} PRINTER_ENUM_VALUESA,*PPRINTER_ENUM_VALUESA,*LPPRINTER_ENUM_VALUESA;
} PRINTER_ENUM_VALUESA,*PPRINTER_ENUM_VALUESA,*LPPRINTER_ENUM_VALUESA;
typedef struct _PRINTER_ENUM_VALUESW {
typedef struct _PRINTER_ENUM_VALUESW {
LPWSTR pValueName;
DWORD cbValueName;
DWORD dwType;
LPBYTE pData;
DWORD cbData;
} PRINTER_ENUM_VALUESW,*PPRINTER_ENUM_VALUESW,*LPPRINTER_ENUM_VALUESW;
} PRINTER_ENUM_VALUESW,*PPRINTER_ENUM_VALUESW,*LPPRINTER_ENUM_VALUESW;
__MINGW_TYPEDEF_AW(PRINTER_ENUM_VALUES)
__MINGW_TYPEDEF_AW(PPRINTER_ENUM_VALUES)
__MINGW_TYPEDEF_AW(LPPRINTER_ENUM_VALUES)
__MINGW_TYPEDEF_AW(PRINTER_ENUM_VALUES)
__MINGW_TYPEDEF_AW(PPRINTER_ENUM_VALUES)
__MINGW_TYPEDEF_AW(LPPRINTER_ENUM_VALUES)
#define EnumPrinters __MINGW_NAME_AW(EnumPrinters)
WINBOOL WINAPI EnumPrintersA(DWORD Flags,LPSTR Name,DWORD Level,LPBYTE pPrinterEnum,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned);
WINBOOL WINAPI EnumPrintersW(DWORD Flags,LPWSTR Name,DWORD Level,LPBYTE pPrinterEnum,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned);
WINBOOL WINAPI EnumPrintersA(DWORD Flags,LPSTR Name,DWORD Level,LPBYTE pPrinterEnum,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned);
WINBOOL WINAPI EnumPrintersW(DWORD Flags,LPWSTR Name,DWORD Level,LPBYTE pPrinterEnum,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned);
#define PRINTER_ENUM_DEFAULT 0x00000001
#define PRINTER_ENUM_LOCAL 0x00000002

View file

@ -1173,14 +1173,14 @@ interface winspool {
DWORD _RpcAddPort(
[in, unique] WINSPOOL_HANDLE pName,
[in] ULONG_PTR hWnd,
[in] WCHAR* pMonitorName
[in, string] WCHAR* pMonitorName
);
/* Function 0x26 */
DWORD _RpcConfigurePort(
[in, unique] WINSPOOL_HANDLE pName,
[in] ULONG_PTR hWnd,
[in] WCHAR* pPortName
[in, string] WCHAR* pPortName
);
/* Function 0x27 */
@ -1242,7 +1242,7 @@ interface winspool {
DWORD _RpcDeleteMonitor(
[in, unique] WINSPOOL_HANDLE pName,
[in, string, unique] WCHAR* pEnvironment,
[in, string] WCHAR* pMonitorName
[in, string, unique] WCHAR* pMonitorName
);
/* Function 0x30 */
@ -1342,7 +1342,7 @@ interface winspool {
/* Function 0x3D */
DWORD _RpcAddPortEx(
[in] WINSPOOL_HANDLE pName,
[in, unique] WINSPOOL_HANDLE pName,
[in] WINSPOOL_PORT_CONTAINER* pPortContainer,
[in] WINSPOOL_PORT_VAR_CONTAINER* pPortVarContainer,
[in, string] WCHAR* pMonitorName
@ -1362,9 +1362,12 @@ interface winspool {
/* Function 0x3F */
DWORD _RpcSpoolerInit();
/* Function 0x40 (TODO) */
/* Function 0x40 */
DWORD _RpcResetPrinterEx(
/* TODO */
[in] WINSPOOL_PRINTER_HANDLE hPrinter,
[in, string, unique] WCHAR* pDatatype,
[in] WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer,
[in] DWORD dwFlags
);
/* Function 0x41 */
@ -1514,9 +1517,13 @@ interface winspool {
[in, string] const WCHAR* pKeyName
);
/* Function 0x53 (TODO) */
/* Function 0x53 */
DWORD _RpcSeekPrinter(
/* TODO */
[in] WINSPOOL_PRINTER_HANDLE hPrinter,
[in] LARGE_INTEGER liDistanceToMove,
[out] PLARGE_INTEGER pliNewPointer,
[in] DWORD dwMoveMethod,
[in] BOOL bWrite
);
/* Function 0x54 */
@ -1553,7 +1560,7 @@ interface winspool {
/* Function 0x58 */
DWORD _RpcXcvData(
[in] WINSPOOL_PRINTER_HANDLE hXcv,
[in, unique] WINSPOOL_PRINTER_HANDLE hXcv,
[in, string] const WCHAR* pszDataName,
[in, size_is(cbInputData)] BYTE* pInputData,
[in] DWORD cbInputData,
@ -1577,7 +1584,7 @@ interface winspool {
/* Function 0x5B */
DWORD _RpcGetSpoolFileInfo(
[in] WINSPOOL_PRINTER_HANDLE hPrinter,
[in, unique] WINSPOOL_PRINTER_HANDLE hPrinter,
[in] WINSPOOL_HANDLE hProcessHandle,
[in] DWORD Level,
[in] WINSPOOL_FILE_INFO_1* pFileInfo,
@ -1587,8 +1594,8 @@ interface winspool {
/* Function 0x5C */
DWORD _RpcCommitSpoolData(
[in] WINSPOOL_PRINTER_HANDLE hPrinter,
[in] WINSPOOL_HANDLE hProcessHandle,
[in, unique] WINSPOOL_PRINTER_HANDLE hPrinter,
[in, unique] WINSPOOL_HANDLE hProcessHandle,
[in] DWORD cbCommit,
[in] DWORD Level,
[in] WINSPOOL_FILE_INFO_1* pFileInfo,
@ -1598,7 +1605,7 @@ interface winspool {
/* Function 0x5D */
DWORD _RpcGetSpoolFileInfo2(
[in] WINSPOOL_PRINTER_HANDLE hPrinter,
[in, unique] WINSPOOL_PRINTER_HANDLE hPrinter,
[in] DWORD dwProcessId,
[in] DWORD Level,
[in] WINSPOOL_FILE_INFO_CONTAINER* pFileInfoContainer
@ -1615,12 +1622,12 @@ interface winspool {
/* Function 0x5F */
DWORD _RpcCloseSpoolFileHandle(
[in] WINSPOOL_PRINTER_HANDLE hPrinter
[in, unique] WINSPOOL_PRINTER_HANDLE hPrinter
);
/* Function 0x60 */
DWORD _RpcFlushPrinter(
[in] WINSPOOL_PRINTER_HANDLE hPrinter,
[in, unique] WINSPOOL_PRINTER_HANDLE hPrinter,
[in, size_is(cbBuf)] BYTE* pBuf,
[in] DWORD cbBuf,
[out] DWORD* pcWritten,

View file

@ -105,6 +105,22 @@ BOOL WINAPI StrRetToStrNW(LPWSTR,DWORD,LPSTRRET,const ITEMIDLIST*);
#define SHCNRF_RecursiveInterrupt 0x1000 /* Must be combined with SHCNRF_InterruptLevel */
#define SHCNRF_NewDelivery 0x8000 /* Messages use shared memory */
/****************************************************************************
* SHChangeNotify
*/
typedef struct _SHCNF_PRINTJOB_INFO
{
DWORD JobId;
// More info,,,
} SHCNF_PRINTJOB_INFO, *PSHCNF_PRINTJOB_INFO;
//
// Add missing types for print job notifications.
//
#define SHCNF_PRINTJOBA 0x0004
#define SHCNF_PRINTJOBW 0x0007
/****************************************************************************
* Shell Common Dialogs

View file

@ -4,14 +4,17 @@ spec2def(spoolss.dll spoolss.spec ADD_IMPORTLIB)
list(APPEND SOURCE
../marshalling.c
context.c
forms.c
jobs.c
main.c
memory.c
monitors.c
ports.c
printerdata.c
printerdrivers.c
printers.c
printprocessors.c
printproviders.c
spoolfile.c
tools.c)

View file

@ -0,0 +1,95 @@
/*
* PROJECT: ReactOS Spooler Router
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Functions for managing print Forms
* COPYRIGHT: Copyright 2020 ReactOS
*/
#include "precomp.h"
BOOL WINAPI
AddFormW(HANDLE hPrinter, DWORD Level, PBYTE pForm)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpAddForm(pHandle->hPrinter, Level, pForm);
}
BOOL WINAPI
DeleteFormW(HANDLE hPrinter, PWSTR pFormName)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpDeleteForm(pHandle->hPrinter, pFormName);
}
BOOL WINAPI
EnumFormsW(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if ( cbBuf && !pForm )
{
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpEnumForms(pHandle->hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned);
}
BOOL WINAPI
GetFormW(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if ( cbBuf && pForm )
{
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpGetForm(pHandle->hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded);
}
BOOL WINAPI
SetFormW(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpSetForm(pHandle->hPrinter, pFormName, Level, pForm);
}

View file

@ -7,6 +7,72 @@
#include "precomp.h"
BOOL WINAPI
AddMonitorW(PWSTR pName, DWORD Level, PBYTE pMonitors)
{
BOOL bReturnValue = TRUE;
DWORD dwErrorCode = MAXDWORD;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
// Loop through all Print Provider.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
// Check if this Print Provider provides the function.
if (!pPrintProvider->PrintProvider.fpAddMonitor)
continue;
bReturnValue = pPrintProvider->PrintProvider.fpAddMonitor(pName, Level, pMonitors);
if ( !bReturnValue )
{
dwErrorCode = GetLastError();
}
// dwErrorCode shall not be overwritten if a previous call already succeeded.
if (dwErrorCode != ERROR_SUCCESS)
dwErrorCode = GetLastError();
}
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
DeleteMonitorW(PWSTR pName, PWSTR pEnvironment, PWSTR pMonitorName)
{
BOOL bReturnValue = TRUE;
DWORD dwErrorCode = MAXDWORD;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
// Loop through all Print Provider.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
// Check if this Print Provider provides the function.
if (!pPrintProvider->PrintProvider.fpDeleteMonitor)
continue;
bReturnValue = pPrintProvider->PrintProvider.fpDeleteMonitor(pName, pEnvironment, pMonitorName);
if ( !bReturnValue )
{
dwErrorCode = GetLastError();
}
// dwErrorCode shall not be overwritten if a previous call already succeeded.
if (dwErrorCode != ERROR_SUCCESS)
dwErrorCode = GetLastError();
}
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
@ -14,6 +80,7 @@ EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcb
DWORD cbCallBuffer;
DWORD cbNeeded;
DWORD dwReturned;
DWORD dwErrorCode = MAXDWORD;
PBYTE pCallBuffer;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
@ -47,6 +114,11 @@ EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcb
dwReturned = 0;
bReturnValue = pPrintProvider->PrintProvider.fpEnumMonitors(pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
if ( !bReturnValue )
{
dwErrorCode = GetLastError();
}
// Add the returned counts to the total values.
*pcbNeeded += cbNeeded;
*pcReturned += dwReturned;
@ -61,10 +133,11 @@ EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcb
if (pCallBuffer)
pCallBuffer += cbNeeded;
// Check if we shall not ask other Print Providers.
if (bReturnValue == ROUTER_STOP_ROUTING)
break;
// dwErrorCode shall not be overwritten if a previous EnumPrinters call already succeeded.
if (dwErrorCode != ERROR_SUCCESS)
dwErrorCode = GetLastError();
}
return bReturnValue;
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}

View file

@ -7,6 +7,142 @@
#include "precomp.h"
BOOL WINAPI
AddPortExW(PWSTR pName, DWORD Level, PBYTE lpBuffer, PWSTR lpMonitorName)
{
BOOL bReturnValue = TRUE;
DWORD dwErrorCode = MAXDWORD;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
FIXME("AddPortEx(%S, %lu, %p, %s)\n", pName, Level, lpBuffer, debugstr_w(lpMonitorName));
// Loop through all Print Provider.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
// Check if this Print Provider provides the function.
if (!pPrintProvider->PrintProvider.fpAddPortEx)
continue;
bReturnValue = pPrintProvider->PrintProvider.fpAddPortEx(pName, Level, lpBuffer, lpMonitorName);
if ( !bReturnValue )
{
dwErrorCode = GetLastError();
}
// dwErrorCode shall not be overwritten if a previous call already succeeded.
if (dwErrorCode != ERROR_SUCCESS)
dwErrorCode = GetLastError();
}
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
AddPortW(PWSTR pName, HWND hWnd, PWSTR pMonitorName)
{
BOOL bReturnValue = TRUE;
DWORD dwErrorCode = MAXDWORD;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
FIXME("AddPort(%S, %p, %s)\n", pName, hWnd, debugstr_w(pMonitorName));
// Loop through all Print Provider.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
// Check if this Print Provider provides the function.
if (!pPrintProvider->PrintProvider.fpAddPort)
continue;
bReturnValue = pPrintProvider->PrintProvider.fpAddPort(pName, hWnd, pMonitorName);
if ( !bReturnValue )
{
dwErrorCode = GetLastError();
}
// dwErrorCode shall not be overwritten if a previous call already succeeded.
if (dwErrorCode != ERROR_SUCCESS)
dwErrorCode = GetLastError();
}
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
ConfigurePortW(PWSTR pName, HWND hWnd, PWSTR pPortName)
{
BOOL bReturnValue = TRUE;
DWORD dwErrorCode = MAXDWORD;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
// Loop through all Print Provider.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
// Check if this Print Provider provides the function.
if (!pPrintProvider->PrintProvider.fpConfigurePort)
continue;
bReturnValue = pPrintProvider->PrintProvider.fpConfigurePort(pName, hWnd, pPortName);
if ( !bReturnValue )
{
dwErrorCode = GetLastError();
}
// dwErrorCode shall not be overwritten if a previous call already succeeded.
if (dwErrorCode != ERROR_SUCCESS)
dwErrorCode = GetLastError();
}
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
DeletePortW(PWSTR pName, HWND hWnd, PWSTR pPortName)
{
BOOL bReturnValue = TRUE;
DWORD dwErrorCode = MAXDWORD;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
// Loop through all Print Provider.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
// Check if this Print Provider provides the function.
if (!pPrintProvider->PrintProvider.fpDeletePort)
continue;
bReturnValue = pPrintProvider->PrintProvider.fpDeletePort(pName, hWnd, pPortName);
if ( !bReturnValue )
{
dwErrorCode = GetLastError();
}
// dwErrorCode shall not be overwritten if a previous call already succeeded.
if (dwErrorCode != ERROR_SUCCESS)
dwErrorCode = GetLastError();
}
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
@ -14,6 +150,7 @@ EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded
DWORD cbCallBuffer;
DWORD cbNeeded;
DWORD dwReturned;
DWORD dwErrorCode = MAXDWORD;
PBYTE pCallBuffer;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
@ -38,11 +175,20 @@ EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
// Check if this Print Provider provides an EnumPorts function.
if (!pPrintProvider->PrintProvider.fpEnumPorts)
continue;
// Call the EnumPorts function of this Print Provider.
cbNeeded = 0;
dwReturned = 0;
bReturnValue = pPrintProvider->PrintProvider.fpEnumPorts(pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
if ( !bReturnValue )
{
dwErrorCode = GetLastError();
}
// Add the returned counts to the total values.
*pcbNeeded += cbNeeded;
*pcReturned += dwReturned;
@ -57,10 +203,44 @@ EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded
if (pCallBuffer)
pCallBuffer += cbNeeded;
// Check if we shall not ask other Print Providers.
if (bReturnValue == ROUTER_STOP_ROUTING)
break;
// dwErrorCode shall not be overwritten if a previous EnumPrinters call already succeeded.
if (dwErrorCode != ERROR_SUCCESS)
dwErrorCode = GetLastError();
}
return bReturnValue;
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
SetPortW(PWSTR pName, PWSTR pPortName, DWORD dwLevel, PBYTE pPortInfo)
{
BOOL bReturnValue = TRUE;
DWORD dwErrorCode = MAXDWORD;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
// Loop through all Print Provider.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
// Check if this Print Provider provides the function.
if (!pPrintProvider->PrintProvider.fpSetPort)
continue;
bReturnValue = pPrintProvider->PrintProvider.fpSetPort(pName, pPortName, dwLevel, pPortInfo);
if ( !bReturnValue )
{
dwErrorCode = GetLastError();
}
// dwErrorCode shall not be overwritten if a previous call already succeeded.
if (dwErrorCode != ERROR_SUCCESS)
dwErrorCode = GetLastError();
}
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}

View file

@ -7,6 +7,96 @@
#include "precomp.h"
DWORD WINAPI
DeletePrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pValueName)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpDeletePrinterDataEx(pHandle->hPrinter, pKeyName, pValueName);
}
DWORD WINAPI
DeletePrinterDataW(HANDLE hPrinter, PWSTR pValueName)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpDeletePrinterData(pHandle->hPrinter, pValueName);
}
DWORD WINAPI
DeletePrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpDeletePrinterKey(pHandle->hPrinter, pKeyName);
}
DWORD WINAPI
EnumPrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PBYTE pEnumValues, DWORD cbEnumValues, PDWORD pcbEnumValues, PDWORD pnEnumValues)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpEnumPrinterDataEx(pHandle->hPrinter, pKeyName, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues);
}
DWORD WINAPI
EnumPrinterDataW(HANDLE hPrinter, DWORD dwIndex, PWSTR pValueName, DWORD cbValueName, PDWORD pcbValueName, PDWORD pType, PBYTE pData, DWORD cbData, PDWORD pcbData)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpEnumPrinterData(pHandle->hPrinter, dwIndex, pValueName, cbValueName, pcbValueName, pType, pData, cbData, pcbData);
}
DWORD WINAPI
EnumPrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName, PWSTR pSubkey, DWORD cbSubkey, PDWORD pcbSubkey)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpEnumPrinterKey(pHandle->hPrinter, pKeyName, pSubkey, cbSubkey, pcbSubkey);
}
DWORD WINAPI
GetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
{

View file

@ -0,0 +1,254 @@
/*
* PROJECT: ReactOS Spooler Router
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Functions related to Printer Configuration Data
* COPYRIGHT: Copyright 2020 ReactOS
*/
#include "precomp.h"
BOOL WINAPI
AddPrinterDriverExW(PWSTR pName, DWORD Level, PBYTE pDriverInfo, DWORD dwFileCopyFlags)
{
BOOL bReturnValue;
DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
PLIST_ENTRY pEntry;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
// Loop through all Print Providers.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
bReturnValue = pPrintProvider->PrintProvider.fpAddPrinterDriverEx(pName, Level, pDriverInfo, dwFileCopyFlags);
if (bReturnValue == ROUTER_SUCCESS)
{
dwErrorCode = ERROR_SUCCESS;
goto Cleanup;
}
else if (bReturnValue == ROUTER_STOP_ROUTING)
{
ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pName);
dwErrorCode = GetLastError();
goto Cleanup;
}
}
Cleanup:
// ERROR_INVALID_NAME by the Print Provider is translated to ERROR_INVALID_PRINTER_NAME here, but not in other APIs as far as I know.
if (dwErrorCode == ERROR_INVALID_NAME)
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
AddPrinterDriverW(PWSTR pName, DWORD Level, PBYTE pDriverInfo)
{
TRACE("AddPrinterDriverW(%S, %lu, %p)\n", pName, Level, pDriverInfo);
return AddPrinterDriverExW(pName, Level, pDriverInfo, APD_COPY_NEW_FILES);
}
BOOL WINAPI
DeletePrinterDriverExW(PWSTR pName, PWSTR pEnvironment, PWSTR pDriverName, DWORD dwDeleteFlag, DWORD dwVersionFlag)
{
BOOL bReturnValue;
DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
PLIST_ENTRY pEntry;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
// Loop through all Print Providers.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
bReturnValue = pPrintProvider->PrintProvider.fpDeletePrinterDriverEx(pName, pEnvironment, pDriverName, dwDeleteFlag, dwVersionFlag);
if (bReturnValue == ROUTER_SUCCESS)
{
dwErrorCode = ERROR_SUCCESS;
goto Cleanup;
}
else if (bReturnValue == ROUTER_STOP_ROUTING)
{
ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pName);
dwErrorCode = GetLastError();
goto Cleanup;
}
}
Cleanup:
// ERROR_INVALID_NAME by the Print Provider is translated to ERROR_INVALID_PRINTER_NAME here, but not in other APIs as far as I know.
if (dwErrorCode == ERROR_INVALID_NAME)
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
DeletePrinterDriverW(PWSTR pName, PWSTR pEnvironment, PWSTR pDriverName)
{
TRACE("DeletePrinterDriverW(%S, %S, %S)\n", pName, pEnvironment, pDriverName);
return DeletePrinterDriverExW(pName, pEnvironment, pDriverName, 0, 0);
}
BOOL WINAPI
EnumPrinterDriversW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
DWORD cbCallBuffer;
DWORD cbNeeded;
DWORD dwErrorCode = MAXDWORD;
DWORD dwReturned;
PBYTE pCallBuffer;
BOOL Ret = FALSE;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
// Begin counting.
*pcbNeeded = 0;
*pcReturned = 0;
if ( cbBuf && !pDriverInfo )
{
dwErrorCode = ERROR_INVALID_USER_BUFFER;
goto Cleanup;
}
// At the beginning, we have the full buffer available.
cbCallBuffer = cbBuf;
pCallBuffer = pDriverInfo;
// Loop through all Print Providers.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
// Call the EnumPrinters function of this Print Provider.
cbNeeded = 0;
dwReturned = 0;
Ret = pPrintProvider->PrintProvider.fpEnumPrinterDrivers( pName, pEnvironment, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
if ( !Ret )
{
dwErrorCode = GetLastError();
}
// Add the returned counts to the total values.
*pcbNeeded += cbNeeded;
*pcReturned += dwReturned;
// Reduce the available buffer size for the next call without risking an underflow.
if (cbNeeded < cbCallBuffer)
cbCallBuffer -= cbNeeded;
else
cbCallBuffer = 0;
// Advance the buffer if the caller provided it.
if (pCallBuffer)
pCallBuffer += cbNeeded;
// dwErrorCode shall not be overwritten if a previous EnumPrinters call already succeeded.
if (dwErrorCode != ERROR_SUCCESS)
dwErrorCode = GetLastError();
}
Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpGetPrinterDriver(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
}
BOOL WINAPI
GetPrinterDriverExW(
HANDLE hPrinter,
LPWSTR pEnvironment,
DWORD Level,
LPBYTE pDriverInfo,
DWORD cbBuf,
LPDWORD pcbNeeded,
DWORD dwClientMajorVersion,
DWORD dwClientMinorVersion,
PDWORD pdwServerMajorVersion,
PDWORD pdwServerMinorVersion )
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
FIXME("GetPrinterDriverExW(%p, %lu, %lu, %p, %lu, %p, %lu, %lu, %p, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, dwClientMajorVersion, dwClientMinorVersion, pdwServerMajorVersion, pdwServerMinorVersion);
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if ( cbBuf && !pDriverInfo )
{
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpGetPrinterDriverEx(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, dwClientMajorVersion, dwClientMinorVersion, pdwServerMajorVersion, pdwServerMinorVersion);
}
BOOL WINAPI
GetPrinterDriverDirectoryW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverDirectory, DWORD cbBuf, PDWORD pcbNeeded)
{
BOOL bReturnValue;
DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
PLIST_ENTRY pEntry;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
if ( cbBuf && !pDriverDirectory )
{
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
// Loop through all Print Providers.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
bReturnValue = pPrintProvider->PrintProvider.fpGetPrinterDriverDirectory(pName, pEnvironment, Level, pDriverDirectory, cbBuf, pcbNeeded);
if (bReturnValue == ROUTER_SUCCESS)
{
dwErrorCode = ERROR_SUCCESS;
goto Cleanup;
}
else if (bReturnValue == ROUTER_STOP_ROUTING)
{
ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pName);
dwErrorCode = GetLastError();
goto Cleanup;
}
}
Cleanup:
// ERROR_INVALID_NAME by the Print Provider is translated to ERROR_INVALID_PRINTER_NAME here, but not in other APIs as far as I know.
if (dwErrorCode == ERROR_INVALID_NAME)
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}

View file

@ -7,6 +7,170 @@
#include "precomp.h"
BOOL WINAPI
AbortPrinter(HANDLE hPrinter)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpAbortPrinter(pHandle->hPrinter);
}
//
// See [MS-RPRN] 2.2.1.11 SPLCLIENT_INFO, SPLCLIENT_INFO Level.
//
HANDLE WINAPI
AddPrinterExW( PWSTR pName, DWORD Level, PBYTE pPrinter, PBYTE pClientInfo, DWORD ClientInfoLevel)
{
BOOL bReturnValue;
DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
HANDLE hPrinter = NULL;
PWSTR pPrinterName = NULL;
PLIST_ENTRY pEntry;
PSPOOLSS_PRINTER_HANDLE pHandle;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
if ( Level != 2 )
{
FIXME( "Unsupported level %d\n", Level );
SetLastError( ERROR_INVALID_LEVEL );
return hPrinter;
}
else
{
PPRINTER_INFO_2W pi2w = (PPRINTER_INFO_2W)pPrinter;
pPrinterName = pi2w->pPrinterName;
}
// Loop through all Print Providers to find one able to open this Printer.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
hPrinter = pPrintProvider->PrintProvider.fpAddPrinterEx(pName, Level, pPrinter, pClientInfo, ClientInfoLevel);
bReturnValue = GetLastError();
// Fallback.... ?
if ( hPrinter == NULL && bReturnValue == ERROR_NOT_SUPPORTED )
{
hPrinter = pPrintProvider->PrintProvider.fpAddPrinter(pName, Level, pPrinter);
}
bReturnValue = GetLastError();
if ( bReturnValue == ROUTER_SUCCESS && hPrinter )
{
// This Print Provider has opened this Printer.
// Store this information and return a handle.
pHandle = DllAllocSplMem(sizeof(SPOOLSS_PRINTER_HANDLE));
if (!pHandle)
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("DllAllocSplMem failed!\n");
goto Cleanup;
}
pHandle->pPrintProvider = pPrintProvider;
pHandle->hPrinter = hPrinter;
dwErrorCode = ERROR_SUCCESS;
goto Cleanup;
}
else if (bReturnValue == ROUTER_STOP_ROUTING)
{
ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pPrinterName);
dwErrorCode = GetLastError();
goto Cleanup;
}
}
Cleanup:
// ERROR_INVALID_NAME by the Print Provider is translated to ERROR_INVALID_PRINTER_NAME here, but not in other APIs as far as I know.
if (dwErrorCode == ERROR_INVALID_NAME)
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
SetLastError(dwErrorCode);
return hPrinter;
}
HANDLE WINAPI
AddPrinterW(PWSTR pName, DWORD Level, PBYTE pPrinter)
{
BOOL bReturnValue;
DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
HANDLE hPrinter = NULL;
PWSTR pPrinterName = NULL;
PLIST_ENTRY pEntry;
PSPOOLSS_PRINTER_HANDLE pHandle;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
FIXME("AddPrinterW(%S, %lu, %p)\n", pName, Level, pPrinter);
if ( Level != 2 )
{
FIXME( "Unsupported level %d\n", Level );
SetLastError( ERROR_INVALID_LEVEL );
return hPrinter;
}
else
{
PPRINTER_INFO_2W pi2w = (PPRINTER_INFO_2W)pPrinter;
pPrinterName = pi2w->pPrinterName;
}
// Xp return AddPrinterExW( pName, Level, pPrinter, NULL, 0); but,,,, W7u just Forward Direct.
// Loop through all Print Providers to find one able to open this Printer.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
hPrinter = pPrintProvider->PrintProvider.fpAddPrinter(pName, Level, pPrinter);
bReturnValue = GetLastError();
if ( bReturnValue == ROUTER_SUCCESS && hPrinter )
{
// This Print Provider has opened this Printer.
// Store this information and return a handle.
pHandle = DllAllocSplMem(sizeof(SPOOLSS_PRINTER_HANDLE));
if (!pHandle)
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("DllAllocSplMem failed!\n");
goto Cleanup;
}
pHandle->pPrintProvider = pPrintProvider;
pHandle->hPrinter = hPrinter;
dwErrorCode = ERROR_SUCCESS;
goto Cleanup;
}
else if (bReturnValue == ROUTER_STOP_ROUTING)
{
ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pPrinterName);
dwErrorCode = GetLastError();
goto Cleanup;
}
}
Cleanup:
// ERROR_INVALID_NAME by the Print Provider is translated to ERROR_INVALID_PRINTER_NAME here, but not in other APIs as far as I know.
if (dwErrorCode == ERROR_INVALID_NAME)
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
SetLastError(dwErrorCode);
return hPrinter;
}
BOOL WINAPI
ClosePrinter(HANDLE hPrinter)
@ -14,6 +178,8 @@ ClosePrinter(HANDLE hPrinter)
BOOL bReturnValue;
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
FIXME("ClosePrinter %p\n",hPrinter);
// Sanity checks.
if (!pHandle)
{
@ -25,13 +191,28 @@ ClosePrinter(HANDLE hPrinter)
// Call CloseHandle of the Print Provider.
bReturnValue = pHandle->pPrintProvider->PrintProvider.fpClosePrinter(pHandle->hPrinter);
FIXME("ClosePrinter 2\n");
// Free our handle information.
DllFreeSplMem(pHandle);
FIXME("ClosePrinter 3\n");
return bReturnValue;
}
BOOL WINAPI
DeletePrinter(HANDLE hPrinter)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpDeletePrinter(pHandle->hPrinter);
}
BOOL WINAPI
EndDocPrinter(HANDLE hPrinter)
{
@ -70,6 +251,7 @@ EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cb
DWORD dwErrorCode = MAXDWORD;
DWORD dwReturned;
PBYTE pCallBuffer;
BOOL Ret = FALSE;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
@ -95,7 +277,12 @@ EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cb
// Call the EnumPrinters function of this Print Provider.
cbNeeded = 0;
dwReturned = 0;
pPrintProvider->PrintProvider.fpEnumPrinters(Flags, Name, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
Ret = pPrintProvider->PrintProvider.fpEnumPrinters(Flags, Name, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
if ( !Ret )
{
dwErrorCode = GetLastError();
}
// Add the returned counts to the total values.
*pcbNeeded += cbNeeded;
@ -121,21 +308,6 @@ Cleanup:
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpGetPrinterDriver(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
}
BOOL WINAPI
GetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD cbBuf, PDWORD pcbNeeded)
{
@ -151,6 +323,24 @@ GetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD cbBuf, PDWORD pc
return pHandle->pPrintProvider->PrintProvider.fpGetPrinter(pHandle->hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
}
//
// Forward Dead API to Local/Remote....
//
DWORD WINAPI
PrinterMessageBoxW(HANDLE hPrinter, DWORD Error, HWND hWnd, LPWSTR pText, LPWSTR pCaption, DWORD dwType)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpPrinterMessageBox(pHandle->hPrinter, Error, hWnd, pText, pCaption, dwType);
}
BOOL WINAPI
OpenPrinterW(PWSTR pPrinterName, PHANDLE phPrinter, PPRINTER_DEFAULTSW pDefault)
{
@ -218,6 +408,36 @@ ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
return pHandle->pPrintProvider->PrintProvider.fpReadPrinter(pHandle->hPrinter, pBuf, cbBuf, pNoBytesRead);
}
BOOL WINAPI
SeekPrinter( HANDLE hPrinter, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER pliNewPointer, DWORD dwMoveMethod, BOOL bWrite )
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpSeekPrinter( pHandle->hPrinter, liDistanceToMove, pliNewPointer, dwMoveMethod, bWrite );
}
BOOL WINAPI
SetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD Command)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpSetPrinter( pHandle->hPrinter, Level, pPrinter, Command );
}
DWORD WINAPI
StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
{
@ -268,6 +488,8 @@ XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, P
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hXcv;
FIXME("XcvDataW( %p, %S,,,)\n",hXcv, pszDataName);
// Sanity checks.
if (!pHandle)
{

View file

@ -6,6 +6,23 @@
*/
#include "precomp.h"
#include <prtprocenv.h>
BOOL WINAPI
AddPrintProcessorW(PWSTR pName, PWSTR pEnvironment, PWSTR pPathName, PWSTR pPrintProcessorName)
{
if (!pEnvironment || !*pEnvironment)
pEnvironment = (PWSTR)wszCurrentEnvironment;
return FALSE;
}
BOOL WINAPI
DeletePrintProcessorW(PWSTR pName, PWSTR pEnvironment, PWSTR pPrintProcessorName)
{
if (!pEnvironment || !*pEnvironment)
pEnvironment = (PWSTR)wszCurrentEnvironment;
return FALSE;
}
BOOL WINAPI
EnumPrintProcessorDatatypesW(PWSTR pName, PWSTR pPrintProcessorName, DWORD Level, PBYTE pDatatypes, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
@ -19,6 +36,12 @@ EnumPrintProcessorDatatypesW(PWSTR pName, PWSTR pPrintProcessorName, DWORD Level
return FALSE;
}
if ( cbBuf && !pDatatypes )
{
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
// Always call this function on the Local Spooler.
pPrintProvider = CONTAINING_RECORD(PrintProviderList.Flink, SPOOLSS_PRINT_PROVIDER, Entry);
return pPrintProvider->PrintProvider.fpEnumPrintProcessorDatatypes(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned);
@ -29,6 +52,13 @@ EnumPrintProcessorsW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pPrintP
{
// Always call this function on the Local Spooler.
PSPOOLSS_PRINT_PROVIDER pPrintProvider = CONTAINING_RECORD(PrintProviderList.Flink, SPOOLSS_PRINT_PROVIDER, Entry);
if ( cbBuf && !pPrintProcessorInfo )
{
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
return pPrintProvider->PrintProvider.fpEnumPrintProcessors(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
}
@ -44,6 +74,12 @@ GetPrintProcessorDirectoryW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE
return FALSE;
}
if ( cbBuf && !pPrintProcessorInfo )
{
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
// Always call this function on the Local Spooler.
pPrintProvider = CONTAINING_RECORD(PrintProviderList.Flink, SPOOLSS_PRINT_PROVIDER, Entry);
return pPrintProvider->PrintProvider.fpGetPrintProcessorDirectory(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded);

View file

@ -0,0 +1,26 @@
/*
* PROJECT: ReactOS Spooler Router
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Functions for managing print Providers
* COPYRIGHT: Copyright 2020 ReactOS
*/
#include "precomp.h"
//
// These do not forward!!!
//
BOOL WINAPI
AddPrintProvidorW(PWSTR pName, DWORD Level, PBYTE pProviderInfo)
{
FIXME("AddPrintProvidorW(%S, %lu, %p)\n", pName, Level, pProviderInfo);
return FALSE;
}
BOOL WINAPI
DeletePrintProvidorW(PWSTR pName, PWSTR pEnvironment, PWSTR pPrintProviderName)
{
FIXME("DeletePrintProvidorW(%s, %s, %s)\n", pName, pEnvironment, pPrintProviderName);
return FALSE;
}

View file

@ -1,18 +1,18 @@
@ stub AbortPrinter
@ stdcall AbortPrinter(ptr)
@ stub AddDriverCatalog
@ stub AddFormW
@ stdcall AddFormW(ptr long ptr)
@ stdcall AddJobW(long long ptr long ptr)
@ stub AddMonitorW
@ stdcall AddMonitorW(wstr long ptr)
@ stub AddPerMachineConnectionW
@ stub AddPortExW
@ stub AddPortW
@ stdcall AddPortExW(wstr long ptr wstr)
@ stdcall AddPortW(wstr ptr wstr)
@ stub AddPrinterConnectionW
@ stub AddPrinterDriverExW
@ stub AddPrinterDriverW
@ stub AddPrinterExW
@ stub AddPrinterW
@ stub AddPrintProcessorW
@ stub AddPrintProvidorW
@ stdcall AddPrinterDriverExW(wstr long ptr long)
@ stdcall AddPrinterDriverW(wstr long ptr)
@ stdcall AddPrinterExW(wstr long ptr ptr long)
@ stdcall AddPrinterW(wstr long ptr)
@ stdcall AddPrintProcessorW(wstr wstr wstr wstr)
@ stdcall AddPrintProvidorW(wstr long ptr)
@ stub AdjustPointers
@ stub AdjustPointersInStructuresArray
@ stub AlignKMPtr
@ -36,37 +36,37 @@
@ stub ClusterSplClose
@ stub ClusterSplIsAlive
@ stub ClusterSplOpen
@ stub ConfigurePortW
@ stdcall ConfigurePortW(wstr ptr wstr)
@ stub CreatePrinterIC
@ stub DbgGetPointers
@ stub DeleteFormW
@ stub DeleteMonitorW
@ stdcall DeleteFormW(ptr wstr)
@ stdcall DeleteMonitorW(wstr wstr wstr)
@ stub DeletePerMachineConnectionW
@ stub DeletePortW
@ stub DeletePrinter
@ stdcall DeletePortW(wstr ptr wstr)
@ stdcall DeletePrinter(ptr)
@ stub DeletePrinterConnectionW
@ stub DeletePrinterDataExW
@ stub DeletePrinterDataW
@ stub DeletePrinterDriverExW
@ stub DeletePrinterDriverW
@ stdcall DeletePrinterDataExW(ptr wstr wstr)
@ stdcall DeletePrinterDataW(ptr wstr)
@ stdcall DeletePrinterDriverExW(wstr wstr wstr long long)
@ stdcall DeletePrinterDriverW(wstr wstr wstr)
@ stub DeletePrinterIC
@ stub DeletePrinterKeyW
@ stub DeletePrintProcessorW
@ stub DeletePrintProvidorW
@ stdcall DeletePrinterKeyW(ptr wstr)
@ stdcall DeletePrintProcessorW(wstr wstr wstr)
@ stdcall DeletePrintProvidorW(wstr wstr wstr)
@ stdcall DllAllocSplMem(long)
@ stdcall DllFreeSplMem(ptr)
@ stdcall DllFreeSplStr(ptr)
@ stdcall EndDocPrinter(long)
@ stdcall EndPagePrinter(long)
@ stub EnumFormsW
@ stdcall EnumFormsW(ptr long ptr long ptr ptr)
@ stdcall EnumJobsW(long long long long ptr long ptr ptr)
@ stdcall EnumMonitorsW(wstr long ptr long ptr ptr)
@ stub EnumPerMachineConnectionsW
@ stdcall EnumPortsW(wstr long ptr long ptr ptr)
@ stub EnumPrinterDataExW
@ stub EnumPrinterDataW
@ stub EnumPrinterDriversW
@ stub EnumPrinterKeyW
@ stdcall EnumPrinterDataExW(ptr wstr ptr long ptr ptr)
@ stdcall EnumPrinterDataW(ptr long wstr long ptr ptr ptr long ptr)
@ stdcall EnumPrinterDriversW(wstr wstr long ptr long ptr ptr)
@ stdcall EnumPrinterKeyW(ptr wstr wstr long ptr)
@ stdcall EnumPrintersW(long wstr long ptr long ptr ptr)
@ stdcall EnumPrintProcessorDatatypesW(wstr wstr long ptr long ptr ptr)
@ stdcall EnumPrintProcessorsW(wstr wstr long ptr long ptr ptr)
@ -76,14 +76,14 @@
@ stub FormatRegistryKeyForPrinter
@ stub FreeOtherNames
@ stub GetClientUserHandle
@ stub GetFormW
@ stdcall GetFormW(ptr wstr long ptr long ptr)
@ stub GetJobAttributes
@ stdcall GetJobW(long long long ptr long ptr)
@ stub GetNetworkId
@ stdcall GetPrinterDataExW(long wstr wstr ptr ptr long ptr)
@ stdcall GetPrinterDataW(long wstr ptr ptr long ptr)
@ stub GetPrinterDriverDirectoryW
@ stub GetPrinterDriverExW
@ stdcall GetPrinterDriverDirectoryW(wstr wstr long ptr long ptr)
@ stdcall GetPrinterDriverExW(ptr wstr long ptr long ptr long long ptr ptr)
@ stdcall GetPrinterDriverW(long wstr long ptr long ptr)
@ stdcall GetPrinterW(long long ptr long ptr)
@ stdcall GetPrintProcessorDirectoryW(wstr wstr long ptr long ptr)
@ -102,7 +102,7 @@
@ stdcall MarshallUpStructuresArray(long ptr long ptr long long)
@ stub MIDL_user_allocate1
@ stub MIDL_user_free1
@ stub OldGetPrinterDriverW
@ stdcall OldGetPrinterDriverW(long wstr long ptr long ptr) GetPrinterDriverW
@ stub OpenPrinterExW
@ stub OpenPrinterPortW
@ stdcall OpenPrinterW(wstr ptr ptr)
@ -110,7 +110,7 @@
@ stub PartialReplyPrinterChangeNotification
@ stub PlayGdiScriptOnPrinterIC
@ stub PrinterHandleRundown
@ stub PrinterMessageBoxW
@ stdcall PrinterMessageBoxW(ptr long ptr wstr wstr long)
@ stub ProvidorFindClosePrinterChangeNotification
@ stub ProvidorFindFirstPrinterChangeNotification
@ stub pszDbgAllocMsgA
@ -121,7 +121,7 @@
@ stub ReplyClosePrinter
@ stub ReplyOpenPrinter
@ stub ReplyPrinterChangeNotification
@ stub ResetPrinterW
@ stdcall -stub ResetPrinterW(ptr ptr)
@ stdcall RevertToPrinterSelf()
@ stub RouterAllocBidiMem
@ stub RouterAllocBidiResponseContainer
@ -133,18 +133,18 @@
@ stub RouterRefreshPrinterChangeNotification
@ stub RouterReplyPrinter
@ stdcall ScheduleJob(long long)
@ stub SeekPrinter
@ stdcall SeekPrinter(ptr int64 ptr long long)
@ stub SendRecvBidiData
@ stub SetAllocFailCount
@ stub SetFormW
@ stdcall SetFormW(ptr wstr long ptr)
@ stdcall SetJobW(long long long ptr long)
@ stub SetPortW
@ stdcall SetPortW(wstr wstr long ptr)
@ stdcall SetPrinterDataExW(long wstr wstr long ptr long)
@ stdcall SetPrinterDataW(long wstr long ptr long)
@ stub SetPrinterW
@ stdcall SetPrinterW(ptr long ptr long)
@ stdcall SplCloseSpoolFileHandle(ptr)
@ stdcall SplCommitSpoolData(ptr ptr long long ptr long ptr)
@ stub SplDriverUnloadComplete
@ stdcall -stub SplDriverUnloadComplete(wstr)
@ stdcall SplGetSpoolFileInfo(ptr ptr long ptr long ptr)
@ stdcall SplInitializeWinSpoolDrv(ptr)
@ stub SplIsSessionZero

View file

@ -2,6 +2,8 @@
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/idl)
add_rpc_files(server ${REACTOS_SOURCE_DIR}/sdk/include/reactos/idl/winspool.idl)
spec2def(spoolsv.exe spoolsv.spec ADD_IMPORTLIB)
list(APPEND SOURCE
forms.c
init.c

View file

@ -6,38 +6,125 @@
*/
#include "precomp.h"
#include <marshalling/forms.h>
DWORD
_RpcAddForm(WINSPOOL_PRINTER_HANDLE hPrinter, WINSPOOL_FORM_CONTAINER* pFormInfoContainer)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!AddFormW(hPrinter, pFormInfoContainer->Level, (PBYTE)pFormInfoContainer->FormInfo.pFormInfo1))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
_RpcDeleteForm(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pFormName)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!DeleteFormW(hPrinter, pFormName))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
_RpcEnumForms(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Level, BYTE* pForm, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
PBYTE pFormsEnumAligned;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
pFormsEnumAligned = AlignRpcPtr(pForm, &cbBuf);
if (EnumFormsW(hPrinter, Level, pFormsEnumAligned, cbBuf, pcbNeeded, pcReturned))
{
// Replace absolute pointer addresses in the output by relative offsets.
ASSERT(Level >= 1 && Level <= 2);
MarshallDownStructuresArray(pFormsEnumAligned, *pcReturned, pFormInfoMarshalling[Level]->pInfo, pFormInfoMarshalling[Level]->cbStructureSize, TRUE);
}
else
{
dwErrorCode = GetLastError();
}
RpcRevertToSelf();
UndoAlignRpcPtr(pForm, pFormsEnumAligned, cbBuf, pcbNeeded);
return dwErrorCode;
}
DWORD
_RpcGetForm(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pFormName, DWORD Level, BYTE* pForm, DWORD cbBuf, DWORD* pcbNeeded)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
PBYTE pFormAligned;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
pFormAligned = AlignRpcPtr(pForm, &cbBuf);
if (GetFormW(hPrinter, pFormName, Level, pFormAligned, cbBuf, pcbNeeded))
{
// Replace absolute pointer addresses in the output by relative offsets.
ASSERT(Level >= 1 && Level <= 2);
MarshallDownStructure(pFormAligned, pFormInfoMarshalling[Level]->pInfo, pFormInfoMarshalling[Level]->cbStructureSize, TRUE);
}
else
{
dwErrorCode = GetLastError();
}
RpcRevertToSelf();
UndoAlignRpcPtr(pForm, pFormAligned, cbBuf, pcbNeeded);
return dwErrorCode;
}
DWORD
_RpcSetForm(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pFormName, WINSPOOL_FORM_CONTAINER* pFormInfoContainer)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!SetFormW(hPrinter, pFormName, pFormInfoContainer->Level, (PBYTE)pFormInfoContainer->FormInfo.pFormInfo1))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}

View file

@ -11,15 +11,39 @@
DWORD
_RpcAddMonitor(WINSPOOL_HANDLE pName, WINSPOOL_MONITOR_CONTAINER* pMonitorContainer)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!AddMonitorW(pName, pMonitorContainer->Level, (PBYTE)pMonitorContainer->MonitorInfo.pMonitorInfo2))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
_RpcDeleteMonitor(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, WCHAR* pMonitorName)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!DeleteMonitorW( pName, pEnvironment, pMonitorName ))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD

View file

@ -11,29 +11,101 @@
DWORD
_RpcAddPort(WINSPOOL_HANDLE pName, ULONG_PTR hWnd, WCHAR* pMonitorName)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
FIXME("AddPort(%S, %p, %s)\n", pName, hWnd, debugstr_w(pMonitorName));
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!AddPortW( pName, (HWND)hWnd, pMonitorName ))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
_RpcAddPortEx(WINSPOOL_HANDLE pName, WINSPOOL_PORT_CONTAINER* pPortContainer, WINSPOOL_PORT_VAR_CONTAINER* pPortVarContainer, WCHAR* pMonitorName)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode, Level = pPortContainer->Level;
WINSPOOL_PORT_INFO_FF PortInfoFF;
PBYTE lpBuffer;
FIXME("AddPortEx(%S, %lu, %s)\n", pName, Level, debugstr_w(pMonitorName));
switch (Level)
{
case 1:
lpBuffer = (PBYTE)pPortContainer->PortInfo.pPortInfo1;
break;
case 0xFFFFFFFF:
PortInfoFF.pPortName = pPortContainer->PortInfo.pPortInfoFF->pPortName;
PortInfoFF.cbMonitorData = pPortVarContainer->cbMonitorData;
PortInfoFF.pMonitorData = pPortVarContainer->pMonitorData;
lpBuffer = (PBYTE)&PortInfoFF;
break;
default:
ERR("Level = %d, unsupported!\n", Level);
return ERROR_INVALID_LEVEL;
}
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!AddPortExW(pName, Level, lpBuffer, pMonitorName ))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
_RpcConfigurePort(WINSPOOL_HANDLE pName, ULONG_PTR hWnd, WCHAR* pPortName)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!ConfigurePortW( pName, (HWND)hWnd, pPortName ))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
_RpcDeletePort(WINSPOOL_HANDLE pName, ULONG_PTR hWnd, WCHAR* pPortName)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!DeletePortW( pName, (HWND)hWnd, pPortName ))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
@ -71,6 +143,18 @@ _RpcEnumPorts(WINSPOOL_HANDLE pName, DWORD Level, BYTE* pPort, DWORD cbBuf, DWOR
DWORD
_RpcSetPort(WINSPOOL_HANDLE pName, WCHAR* pPortName, WINSPOOL_PORT_CONTAINER* pPortContainer)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!SetPortW(pName, pPortName, pPortContainer->Level, (PBYTE)pPortContainer->PortInfo.pPortInfo3))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}

View file

@ -11,36 +11,325 @@
DWORD
_RpcAddPrinterDriver(WINSPOOL_HANDLE pName, WINSPOOL_DRIVER_CONTAINER* pDriverContainer)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
PBYTE pDriverInfo = NULL;
switch ( pDriverContainer->Level )
{
case 8:
{
WINSPOOL_DRIVER_INFO_8 *pdi = pDriverContainer->DriverInfo.Level8;
PDRIVER_INFO_8W pdi8w = DllAllocSplMem(sizeof(DRIVER_INFO_8W));
pDriverInfo = (PBYTE)pdi8w;
pdi8w->pszPrintProcessor = pdi->pPrintProcessor;
pdi8w->pszVendorSetup = pdi->pVendorSetup;
pdi8w->pszzColorProfiles = pdi->pszzColorProfiles;
pdi8w->pszInfPath = pdi->pInfPath;
pdi8w->pszzCoreDriverDependencies = pdi->pszzCoreDriverDependencies;
pdi8w->ftMinInboxDriverVerDate = pdi->ftMinInboxDriverVerDate;
pdi8w->dwlMinInboxDriverVerVersion = pdi->dwlMinInboxDriverVerVersion;
}
case 6:
{
WINSPOOL_DRIVER_INFO_6 *pdi = pDriverContainer->DriverInfo.Level6;
PDRIVER_INFO_6W pdi6w;
if ( pDriverInfo == NULL )
{
pdi6w = DllAllocSplMem(sizeof(DRIVER_INFO_6W));
pDriverInfo = (PBYTE)pdi6w;
}
else
{
pdi6w = (PDRIVER_INFO_6W)pDriverInfo;
}
pdi6w->pszMfgName = pdi->pMfgName;
pdi6w->pszOEMUrl = pdi->pOEMUrl;
pdi6w->pszHardwareID = pdi->pHardwareID;
pdi6w->pszProvider = pdi->pProvider;
pdi6w->ftDriverDate = pdi->ftDriverDate;
pdi6w->dwlDriverVersion = pdi->dwlDriverVersion;
}
case 4:
{
WINSPOOL_DRIVER_INFO_4 *pdi = pDriverContainer->DriverInfo.Level4;
PDRIVER_INFO_4W pdi4w;
if ( pDriverInfo == NULL )
{
pdi4w = DllAllocSplMem(sizeof(DRIVER_INFO_4W));
pDriverInfo = (PBYTE)pdi4w;
}
else
{
pdi4w = (PDRIVER_INFO_4W)pDriverInfo;
}
pdi4w->pszzPreviousNames = pdi->pszzPreviousNames;
}
case 3:
{
WINSPOOL_DRIVER_INFO_3 *pdi = pDriverContainer->DriverInfo.Level3;
PDRIVER_INFO_3W pdi3w;
if ( pDriverInfo == NULL )
{
pdi3w = DllAllocSplMem(sizeof(DRIVER_INFO_3W));
pDriverInfo = (PBYTE)pdi3w;
}
else
{
pdi3w = (PDRIVER_INFO_3W)pDriverInfo;
}
pdi3w->pHelpFile = pdi->pHelpFile;
pdi3w->pDependentFiles = pdi->pDependentFiles;
pdi3w->pMonitorName = pdi->pMonitorName;
pdi3w->pDefaultDataType = pdi->pDefaultDataType;
pdi3w->pDependentFiles = pdi->pDependentFiles;
}
case 2:
{
WINSPOOL_DRIVER_INFO_2 *pdi = pDriverContainer->DriverInfo.Level2;
PDRIVER_INFO_2W pdi2w;
if ( pDriverInfo == NULL )
{
pdi2w = DllAllocSplMem(sizeof(DRIVER_INFO_2W));
pDriverInfo = (PBYTE)pdi2w;
}
else
{
pdi2w = (PDRIVER_INFO_2W)pDriverInfo;
}
pdi2w->pName = pdi->pName;
pdi2w->pEnvironment = pdi->pEnvironment;
pdi2w->pDriverPath = pdi->pDriverPath;
pdi2w->pDataFile = pdi->pDataFile;
pdi2w->pConfigFile = pdi->pConfigFile;
}
break;
//
// At this point pDriverInfo is null.
//
default:
return ERROR_INVALID_LEVEL;
}
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!AddPrinterDriverW( pName, pDriverContainer->Level, pDriverInfo ))
dwErrorCode = GetLastError();
if ( pDriverInfo ) DllFreeSplMem( pDriverInfo );
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
_RpcAddPrinterDriverEx(WINSPOOL_HANDLE pName, WINSPOOL_DRIVER_CONTAINER* pDriverContainer, DWORD dwFileCopyFlags)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
PBYTE pDriverInfo = NULL;
switch ( pDriverContainer->Level )
{
case 8:
{
WINSPOOL_DRIVER_INFO_8 *pdi = pDriverContainer->DriverInfo.Level8;
PDRIVER_INFO_8W pdi8w = DllAllocSplMem(sizeof(DRIVER_INFO_8W));
pDriverInfo = (PBYTE)pdi8w;
pdi8w->pszPrintProcessor = pdi->pPrintProcessor;
pdi8w->pszVendorSetup = pdi->pVendorSetup;
pdi8w->pszzColorProfiles = pdi->pszzColorProfiles;
pdi8w->pszInfPath = pdi->pInfPath;
pdi8w->pszzCoreDriverDependencies = pdi->pszzCoreDriverDependencies;
pdi8w->ftMinInboxDriverVerDate = pdi->ftMinInboxDriverVerDate;
pdi8w->dwlMinInboxDriverVerVersion = pdi->dwlMinInboxDriverVerVersion;
}
case 6:
{
WINSPOOL_DRIVER_INFO_6 *pdi = pDriverContainer->DriverInfo.Level6;
PDRIVER_INFO_6W pdi6w;
if ( pDriverInfo == NULL )
{
pdi6w = DllAllocSplMem(sizeof(DRIVER_INFO_6W));
pDriverInfo = (PBYTE)pdi6w;
}
else
{
pdi6w = (PDRIVER_INFO_6W)pDriverInfo;
}
pdi6w->pszMfgName = pdi->pMfgName;
pdi6w->pszOEMUrl = pdi->pOEMUrl;
pdi6w->pszHardwareID = pdi->pHardwareID;
pdi6w->pszProvider = pdi->pProvider;
pdi6w->ftDriverDate = pdi->ftDriverDate;
pdi6w->dwlDriverVersion = pdi->dwlDriverVersion;
}
case 4:
{
WINSPOOL_DRIVER_INFO_4 *pdi = pDriverContainer->DriverInfo.Level4;
PDRIVER_INFO_4W pdi4w;
if ( pDriverInfo == NULL )
{
pdi4w = DllAllocSplMem(sizeof(DRIVER_INFO_4W));
pDriverInfo = (PBYTE)pdi4w;
}
else
{
pdi4w = (PDRIVER_INFO_4W)pDriverInfo;
}
pdi4w->pszzPreviousNames = pdi->pszzPreviousNames;
}
case 3:
{
WINSPOOL_DRIVER_INFO_3 *pdi = pDriverContainer->DriverInfo.Level3;
PDRIVER_INFO_3W pdi3w;
if ( pDriverInfo == NULL )
{
pdi3w = DllAllocSplMem(sizeof(DRIVER_INFO_3W));
pDriverInfo = (PBYTE)pdi3w;
}
else
{
pdi3w = (PDRIVER_INFO_3W)pDriverInfo;
}
pdi3w->pHelpFile = pdi->pHelpFile;
pdi3w->pDependentFiles = pdi->pDependentFiles;
pdi3w->pMonitorName = pdi->pMonitorName;
pdi3w->pDefaultDataType = pdi->pDefaultDataType;
pdi3w->pDependentFiles = pdi->pDependentFiles;
}
case 2:
{
WINSPOOL_DRIVER_INFO_2 *pdi = pDriverContainer->DriverInfo.Level2;
PDRIVER_INFO_2W pdi2w;
if ( pDriverInfo == NULL )
{
pdi2w = DllAllocSplMem(sizeof(DRIVER_INFO_2W));
pDriverInfo = (PBYTE)pdi2w;
}
else
{
pdi2w = (PDRIVER_INFO_2W)pDriverInfo;
}
pdi2w->pName = pdi->pName;
pdi2w->pEnvironment = pdi->pEnvironment;
pdi2w->pDriverPath = pdi->pDriverPath;
pdi2w->pDataFile = pdi->pDataFile;
pdi2w->pConfigFile = pdi->pConfigFile;
}
break;
//
// At this point pDriverInfo is null.
//
default:
return ERROR_INVALID_LEVEL;
}
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!AddPrinterDriverExW( pName, pDriverContainer->Level, pDriverInfo, dwFileCopyFlags ))
dwErrorCode = GetLastError();
if ( pDriverInfo ) DllFreeSplMem( pDriverInfo );
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
_RpcDeletePrinterDriver(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, WCHAR* pDriverName)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!DeletePrinterDriverW(pName, pEnvironment, pDriverName))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
_RpcDeletePrinterDriverEx(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, WCHAR* pDriverName, DWORD dwDeleteFlag, DWORD dwVersionNum)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!DeletePrinterDriverExW(pName, pEnvironment, pDriverName, dwDeleteFlag, dwVersionNum))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
_RpcEnumPrinterDrivers(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, DWORD Level, BYTE* pDrivers, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
PBYTE pPrinterDriversEnumAligned;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
pPrinterDriversEnumAligned = AlignRpcPtr(pDrivers, &cbBuf);
if (EnumPrinterDriversW(pName, pEnvironment, Level, pPrinterDriversEnumAligned, cbBuf, pcbNeeded, pcReturned))
{
// Replace absolute pointer addresses in the output by relative offsets.
ASSERT(Level <= 6 || Level == 8);
MarshallDownStructuresArray(pPrinterDriversEnumAligned, *pcReturned, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
}
else
{
dwErrorCode = GetLastError();
}
RpcRevertToSelf();
UndoAlignRpcPtr(pDrivers, pPrinterDriversEnumAligned, cbBuf, pcbNeeded);
return dwErrorCode;
}
DWORD
@ -49,7 +338,7 @@ _RpcGetPrinterDriver(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pEnvironment, DWOR
DWORD dwErrorCode;
PBYTE pDriverAligned;
ERR("_RpcGetPrinterDriver(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriver, cbBuf, pcbNeeded);
TRACE("_RpcGetPrinterDriver(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriver, cbBuf, pcbNeeded);
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
@ -63,7 +352,88 @@ _RpcGetPrinterDriver(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pEnvironment, DWOR
if (GetPrinterDriverW(hPrinter, pEnvironment, Level, pDriverAligned, cbBuf, pcbNeeded))
{
// Replace relative offset addresses in the output by absolute pointers.
ASSERT(Level >= 1 && Level <= 5);
ASSERT(Level <= 6 || Level == 8);
MarshallDownStructure(pDriverAligned, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
}
else
{
dwErrorCode = GetLastError();
}
RpcRevertToSelf();
UndoAlignRpcPtr(pDriver, pDriverAligned, cbBuf, pcbNeeded);
return dwErrorCode;
}
BOOL WINAPI YGetPrinterDriver2(
HANDLE hPrinter,
LPWSTR pEnvironment,
DWORD Level,
LPBYTE pDriver,
DWORD cbBuf,
LPDWORD pcbNeeded,
DWORD dwClientMajorVersion,
DWORD dwClientMinorVersion,
PDWORD pdwServerMajorVersion,
PDWORD pdwServerMinorVersion,
BOOL bRPC ) // Seems that all Y fuctions have this.
{
DWORD dwErrorCode;
PBYTE pDriverAligned;
FIXME("_Rpc(Y)GetPrinterDriver2(%p, %lu, %lu, %p, %lu, %p, %lu, %lu, %p, %p)\n", hPrinter, pEnvironment, Level, pDriver, cbBuf, pcbNeeded, dwClientMajorVersion, dwClientMinorVersion, pdwServerMajorVersion, pdwServerMinorVersion);
if ( bRPC )
{
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
}
pDriverAligned = AlignRpcPtr(pDriver, &cbBuf);
if (GetPrinterDriverExW(hPrinter, pEnvironment, Level, pDriverAligned, cbBuf, pcbNeeded, dwClientMajorVersion, dwClientMinorVersion, pdwServerMajorVersion, pdwServerMinorVersion))
{
// Replace relative offset addresses in the output by absolute pointers.
ASSERT(Level <= 6 || Level == 8);
MarshallDownStructure(pDriverAligned, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
}
else
{
dwErrorCode = GetLastError();
}
if ( bRPC ) RpcRevertToSelf();
UndoAlignRpcPtr(pDriver, pDriverAligned, cbBuf, pcbNeeded);
return dwErrorCode;
}
DWORD
_RpcGetPrinterDriver2(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pEnvironment, DWORD Level, BYTE* pDriver, DWORD cbBuf, DWORD* pcbNeeded, DWORD dwClientMajorVersion, DWORD dwClientMinorVersion, DWORD* pdwServerMaxVersion, DWORD* pdwServerMinVersion)
{
DWORD dwErrorCode;
PBYTE pDriverAligned;
FIXME("_RpcGetPrinterDriver2(%p, %lu, %lu, %p, %lu, %p, %lu, %lu, %p, %p)\n", hPrinter, pEnvironment, Level, pDriver, cbBuf, pcbNeeded, dwClientMajorVersion, dwClientMinorVersion, pdwServerMaxVersion, pdwServerMinVersion);
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
pDriverAligned = AlignRpcPtr(pDriver, &cbBuf);
if (GetPrinterDriverExW(hPrinter, pEnvironment, Level, pDriverAligned, cbBuf, pcbNeeded, dwClientMajorVersion, dwClientMinorVersion, pdwServerMaxVersion, pdwServerMinVersion))
{
// Replace relative offset addresses in the output by absolute pointers.
ASSERT(Level <= 6 || Level == 8);
MarshallDownStructure(pDriverAligned, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
}
else
@ -77,16 +447,21 @@ _RpcGetPrinterDriver(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pEnvironment, DWOR
return dwErrorCode;
}
DWORD
_RpcGetPrinterDriver2(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pEnvironment, DWORD Level, BYTE* pDriver, DWORD cbBuf, DWORD* pcbNeeded, DWORD dwClientMajorVersion, DWORD dwClientMinorVersion, DWORD* pdwServerMaxVersion, DWORD* pdwServerMinVersion)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
}
DWORD
_RpcGetPrinterDriverDirectory(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, DWORD Level, BYTE* pDriverDirectory, DWORD cbBuf, DWORD* pcbNeeded)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!GetPrinterDriverDirectoryW(pName, pEnvironment, Level, pDriverDirectory, cbBuf, pcbNeeded))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}

View file

@ -11,8 +11,20 @@
DWORD
_RpcAbortPrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!AbortPrinter(hPrinter))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
@ -53,8 +65,20 @@ _RpcClosePrinter(WINSPOOL_PRINTER_HANDLE* phPrinter)
DWORD
_RpcDeletePrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!DeletePrinter(hPrinter))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
@ -224,17 +248,64 @@ _RpcResetPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pDatatype, WINSPOOL_DE
}
DWORD
_RpcResetPrinterEx(VOID)
_RpcResetPrinterEx(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pDatatype, WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer, DWORD dwFlags)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
PRINTER_DEFAULTSW pdw;
if (pDatatype)
{
pdw.pDatatype = pDatatype;
}
else
{
pdw.pDatatype = dwFlags & RESETPRINTERDEFAULTDATATYPE ? (PWSTR)-1 : NULL;
}
if (pDevModeContainer->pDevMode)
{
pdw.pDevMode = (PDEVMODEW)pDevModeContainer->pDevMode;
// Fixme : Need to check DevMode before forward call, by copy devmode.c from WinSpool.
// Local SV!SplIsValidDevmode((PDW)pDevModeContainer->pDevMode, pDevModeContainer->cbBuf)
}
else
{
pdw.pDevMode = dwFlags & RESETPRINTERDEFAULTDEVMODE ? (PDEVMODEW)-1 : NULL;
}
pdw.DesiredAccess = 0;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!ResetPrinterW(hPrinter, &pdw))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
_RpcSeekPrinter(VOID)
_RpcSeekPrinter( WINSPOOL_PRINTER_HANDLE hPrinter, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER pliNewPointer, DWORD dwMoveMethod, BOOL bWrite )
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!SeekPrinter(hPrinter, liDistanceToMove, pliNewPointer, dwMoveMethod, bWrite))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD

View file

@ -11,15 +11,39 @@
DWORD
_RpcAddPrintProcessor(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, WCHAR* pPathName, WCHAR* pPrintProcessorName)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!AddPrintProcessorW(pName, pEnvironment, pPathName, pPrintProcessorName))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
_RpcDeletePrintProcessor(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, WCHAR* pPrintProcessorName)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!DeletePrintProcessorW(pName, pEnvironment, pPrintProcessorName))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD

View file

@ -10,13 +10,38 @@
DWORD
_RpcAddPrintProvidor(WINSPOOL_HANDLE pName, WINSPOOL_PROVIDOR_CONTAINER* pProvidorContainer)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!AddPrintProvidorW(pName, pProvidorContainer->Level, (PBYTE)pProvidorContainer->ProvidorInfo.pProvidorInfo1))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
_RpcDeletePrintProvidor(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, WCHAR* pPrintProviderName)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!DeletePrintProvidorW(pName, pEnvironment, pPrintProviderName))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}

View file

@ -42,11 +42,26 @@ _RpcDeletePrinterConnection(WINSPOOL_HANDLE pName)
return ERROR_INVALID_FUNCTION;
}
//
// Forward Dead API....
//
DWORD
_RpcPrinterMessageBox(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Error, ULONG_PTR hWnd, WCHAR* pText, WCHAR* pCaption, DWORD dwType)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
PrinterMessageBoxW(hPrinter, Error, (HWND)hWnd, pText, pCaption, dwType);
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD

View file

@ -0,0 +1,18 @@
@ stdcall -stub YAbortPrinter(ptr long)
@ stdcall -stub YAddJob(long long ptr long ptr long)
@ stdcall -stub YDriverUnloadComplete(wstr long)
@ stdcall -stub YEndDocPrinter(long long)
@ stdcall -stub YEndPagePrinter(long long)
@ stdcall -stub YFlushPrinter(ptr ptr long ptr long long)
@ stdcall -stub YGetPrinter(ptr long ptr long ptr long)
@ stdcall YGetPrinterDriver2(ptr wstr long ptr long ptr long long ptr ptr long)
@ stdcall -stub YGetPrinterDriverDirectory(wstr wstr long ptr long ptr long)
@ stdcall -stub YReadPrinter(ptr ptr long ptr long)
@ stdcall -stub YSeekPrinter(ptr int64 ptr long long long)
@ stdcall -stub YSetJob(ptr long long ptr long long)
@ stdcall -stub YSetPort(wstr wstr long ptr long)
@ stdcall -stub YSetPrinter(ptr long ptr long long)
@ stdcall -stub YSplReadPrinter(ptr ptr long long)
@ stdcall -stub YStartDocPrinter(ptr long ptr long)
@ stdcall -stub YStartPagePrinter(ptr long)
@ stdcall -stub YWritePrinter(ptr ptr long ptr long)

View file

@ -10,6 +10,20 @@
DWORD
_RpcXcvData(WINSPOOL_PRINTER_HANDLE hXcv, const WCHAR* pszDataName, BYTE* pInputData, DWORD cbInputData, BYTE* pOutputData, DWORD cbOutputData, DWORD* pcbOutputNeeded, DWORD* pdwStatus)
{
UNIMPLEMENTED;
return ERROR_INVALID_FUNCTION;
DWORD dwErrorCode;
FIXME("RpcXcvData( %p, %S,,,)\n",hXcv, pszDataName);
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
if (!XcvDataW(hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded, pdwStatus))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
}

View file

@ -177,6 +177,7 @@ BOOL WINAPI
EnumFormsA(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
DWORD dwErrorCode, i;
PFORM_INFO_1W pfi1w = (PFORM_INFO_1W)pForm;
PFORM_INFO_2W pfi2w = (PFORM_INFO_2W)pForm;
TRACE("EnumFormsA(%p, %lu, %p, %lu, %p, %p)\n", hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned);
@ -203,13 +204,18 @@ EnumFormsA(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNee
{
goto Cleanup;
}
// Fall through...
case 1:
dwErrorCode = UnicodeToAnsiInPlace(pfi2w[i].pName);
if (dwErrorCode != ERROR_SUCCESS)
{
goto Cleanup;
}
break;
case 1:
dwErrorCode = UnicodeToAnsiInPlace(pfi1w[i].pName);
if (dwErrorCode != ERROR_SUCCESS)
{
goto Cleanup;
}
}
}
return TRUE;
@ -269,7 +275,8 @@ GetFormA(HANDLE hPrinter, PSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf,
{
DWORD dwErrorCode, len;
LPWSTR FormNameW = NULL;
FORM_INFO_2W* pfi2w = (FORM_INFO_2W*)pForm;
PFORM_INFO_1W pfi1w = (PFORM_INFO_1W)pForm;
PFORM_INFO_2W pfi2w = (PFORM_INFO_2W)pForm;
TRACE("GetFormA(%p, %s, %lu, %p, %lu, %p)\n", hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded);
@ -300,20 +307,18 @@ GetFormA(HANDLE hPrinter, PSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf,
{
goto Cleanup;
}
// Fall through...
case 1:
dwErrorCode = UnicodeToAnsiInPlace(pfi2w->pName);
if (dwErrorCode != ERROR_SUCCESS)
{
goto Cleanup;
}
break;
default:
ERR("Level = %d, unsupported!\n", Level);
dwErrorCode = ERROR_INVALID_HANDLE;
SetLastError(dwErrorCode);
break;
case 1:
dwErrorCode = UnicodeToAnsiInPlace(pfi1w->pName);
if (dwErrorCode != ERROR_SUCCESS)
{
goto Cleanup;
}
}
}
Cleanup:

View file

@ -65,10 +65,12 @@ AddJobW(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNeeded
if (dwErrorCode == ERROR_SUCCESS)
{
JOB_INFO_1W* pji1w = (JOB_INFO_1W*)pData;
// Replace relative offset addresses in the output by absolute pointers.
MarshallUpStructure(cbBuf, pData, AddJobInfo1Marshalling.pInfo, AddJobInfo1Marshalling.cbStructureSize, TRUE);
pHandle->bJob = TRUE;
FIXME("Notify Tray Icon\n");
UpdateTrayIcon( hPrinter, pji1w->JobId );
}
Cleanup:
@ -489,23 +491,23 @@ SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command
case 1:
{
JOB_INFO_1W *info1W = (JOB_INFO_1W*)JobW;
HeapFree(GetProcessHeap(), 0, info1W->pUserName);
HeapFree(GetProcessHeap(), 0, info1W->pDocument);
HeapFree(GetProcessHeap(), 0, info1W->pDatatype);
HeapFree(GetProcessHeap(), 0, info1W->pStatus);
if (info1W->pUserName) HeapFree(GetProcessHeap(), 0, info1W->pUserName);
if (info1W->pDocument) HeapFree(GetProcessHeap(), 0, info1W->pDocument);
if (info1W->pDatatype) HeapFree(GetProcessHeap(), 0, info1W->pDatatype);
if (info1W->pStatus) HeapFree(GetProcessHeap(), 0, info1W->pStatus);
break;
}
case 2:
{
JOB_INFO_2W *info2W = (JOB_INFO_2W*)JobW;
HeapFree(GetProcessHeap(), 0, info2W->pUserName);
HeapFree(GetProcessHeap(), 0, info2W->pDocument);
HeapFree(GetProcessHeap(), 0, info2W->pNotifyName);
HeapFree(GetProcessHeap(), 0, info2W->pDatatype);
HeapFree(GetProcessHeap(), 0, info2W->pPrintProcessor);
HeapFree(GetProcessHeap(), 0, info2W->pParameters);
HeapFree(GetProcessHeap(), 0, info2W->pDevMode);
HeapFree(GetProcessHeap(), 0, info2W->pStatus);
if (info2W->pUserName) HeapFree(GetProcessHeap(), 0, info2W->pUserName);
if (info2W->pDocument) HeapFree(GetProcessHeap(), 0, info2W->pDocument);
if (info2W->pNotifyName) HeapFree(GetProcessHeap(), 0, info2W->pNotifyName);
if (info2W->pDatatype) HeapFree(GetProcessHeap(), 0, info2W->pDatatype);
if (info2W->pPrintProcessor) HeapFree(GetProcessHeap(), 0, info2W->pPrintProcessor);
if (info2W->pParameters) HeapFree(GetProcessHeap(), 0, info2W->pParameters);
if (info2W->pDevMode) HeapFree(GetProcessHeap(), 0, info2W->pDevMode);
if (info2W->pStatus) HeapFree(GetProcessHeap(), 0, info2W->pStatus);
break;
}
}

View file

@ -18,7 +18,7 @@ AddMonitorA(PSTR pName, DWORD Level, PBYTE pMonitors)
MONITOR_INFO_2W mi2w;
mi2a = (LPMONITOR_INFO_2A) pMonitors;
TRACE("AddMonitorA(%s, %d, %p) : %s %s %s\n", debugstr_a(pName), Level, pMonitors,
FIXME("AddMonitorA(%s, %d, %p) : %s %s %s\n", debugstr_a(pName), Level, pMonitors,
debugstr_a(mi2a ? mi2a->pName : NULL),
debugstr_a(mi2a ? mi2a->pEnvironment : NULL),
debugstr_a(mi2a ? mi2a->pDLLName : NULL));
@ -65,10 +65,10 @@ AddMonitorA(PSTR pName, DWORD Level, PBYTE pMonitors)
res = AddMonitorW(nameW, Level, (LPBYTE) &mi2w);
HeapFree(GetProcessHeap(), 0, mi2w.pName);
HeapFree(GetProcessHeap(), 0, mi2w.pEnvironment);
HeapFree(GetProcessHeap(), 0, mi2w.pDLLName);
HeapFree(GetProcessHeap(), 0, nameW);
if (mi2w.pName) HeapFree(GetProcessHeap(), 0, mi2w.pName);
if (mi2w.pEnvironment) HeapFree(GetProcessHeap(), 0, mi2w.pEnvironment);
if (mi2w.pDLLName) HeapFree(GetProcessHeap(), 0, mi2w.pDLLName);
if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
return (res);
}
@ -78,7 +78,8 @@ AddMonitorW(PWSTR pName, DWORD Level, PBYTE pMonitors)
{
DWORD dwErrorCode;
WINSPOOL_MONITOR_CONTAINER MonitorInfoContainer;
TRACE("AddMonitorW(%S, %lu, %p)\n", pName, Level, pMonitors);
FIXME("AddMonitorW(%S, %lu, %p)\n", pName, Level, pMonitors);
if (Level != 2)
{
@ -101,7 +102,7 @@ AddMonitorW(PWSTR pName, DWORD Level, PBYTE pMonitors)
ERR("_RpcAddMonitor failed with exception code %lu!\n", dwErrorCode);
}
RpcEndExcept;
FIXME("AddMonitorW Error Code %lu\n", dwErrorCode);
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
@ -136,9 +137,9 @@ DeleteMonitorA(PSTR pName, PSTR pEnvironment, PSTR pMonitorName)
res = DeleteMonitorW(nameW, EnvironmentW, MonitorNameW);
HeapFree(GetProcessHeap(), 0, MonitorNameW);
HeapFree(GetProcessHeap(), 0, EnvironmentW);
HeapFree(GetProcessHeap(), 0, nameW);
if (MonitorNameW) HeapFree(GetProcessHeap(), 0, MonitorNameW);
if (EnvironmentW) HeapFree(GetProcessHeap(), 0, EnvironmentW);
if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
return (res);
}
@ -148,7 +149,7 @@ DeleteMonitorW(PWSTR pName, PWSTR pEnvironment, PWSTR pMonitorName)
{
DWORD dwErrorCode;
TRACE("DeleteMonitorW(%S, %S, %S)\n", pName, pEnvironment, pMonitorName);
FIXME("DeleteMonitorW(%S, %S, %S)\n", pName, pEnvironment, pMonitorName);
// Do the RPC call
RpcTryExcept
@ -296,8 +297,8 @@ emA_cleanup:
if (pcbNeeded) *pcbNeeded = needed;
if (pcReturned) *pcReturned = (res) ? numentries : 0;
HeapFree(GetProcessHeap(), 0, nameW);
HeapFree(GetProcessHeap(), 0, bufferW);
if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
if (bufferW) HeapFree(GetProcessHeap(), 0, bufferW);
FIXME("returning %d with %d (%d byte for %d entries)\n", (res), GetLastError(), needed, numentries);

View file

@ -8,27 +8,40 @@
#include "precomp.h"
#include <marshalling/ports.h>
typedef struct _MONITORUIDATA
{
HMODULE hLibrary;
HANDLE hActCtx;
ULONG_PTR ulpCookie;
PWSTR pModuleName;
BOOL Activeated;
} MONITORUIDATA, *PMONITORUIDATA;
typedef DWORD (*PPfpFunction)(LPWSTR, ULONG_PTR, LPWSTR);
typedef struct _PORTTHREADINFO
{
LPWSTR pName;
HWND hWnd;
LPWSTR pPortName;
FARPROC fpFunction;
DWORD dwErrorCode;
HANDLE hEvent;
LPWSTR pName;
ULONG_PTR hWnd;
LPWSTR pPortName;
PPfpFunction fpFunction;
DWORD dwErrorCode;
HANDLE hEvent;
} PORTTHREADINFO, *PPORTTHREADINFO;
VOID WINAPI
IntPortThread( PPORTTHREADINFO pPortThreadInfo )
{
FIXME("IPT : %s\n",debugstr_w( pPortThreadInfo->pPortName ));
// Do the RPC call
RpcTryExcept
{
pPortThreadInfo->dwErrorCode = (*pPortThreadInfo->fpFunction)( pPortThreadInfo->pName, pPortThreadInfo->hWnd, pPortThreadInfo->pPortName);
pPortThreadInfo->dwErrorCode = pPortThreadInfo->fpFunction( pPortThreadInfo->pName, pPortThreadInfo->hWnd, pPortThreadInfo->pPortName );
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
pPortThreadInfo->dwErrorCode = RpcExceptionCode();
ERR("IPT : _RpcXyzPort failed with exception code %lu!\n", pPortThreadInfo->dwErrorCode);
}
RpcEndExcept;
@ -39,7 +52,7 @@ IntPortThread( PPORTTHREADINFO pPortThreadInfo )
// Start a thread to wait on a printer port.
//
BOOL WINAPI
StartPortThread( LPWSTR pName, HWND hWnd, LPWSTR pPortName, FARPROC fpFunction )
StartPortThread( LPWSTR pName, HWND hWnd, LPWSTR pPortName, PPfpFunction fpFunction )
{
PORTTHREADINFO PortThreadInfo;
HANDLE htHandle;
@ -49,7 +62,7 @@ StartPortThread( LPWSTR pName, HWND hWnd, LPWSTR pPortName, FARPROC fpFunction )
if ( hWnd ) EnableWindow( hWnd, FALSE );
PortThreadInfo.pName = pName;
PortThreadInfo.hWnd = hWnd;
PortThreadInfo.hWnd = (ULONG_PTR)hWnd;
PortThreadInfo.pPortName = pPortName;
PortThreadInfo.fpFunction = fpFunction;
PortThreadInfo.dwErrorCode = ERROR_SUCCESS;
@ -86,6 +99,322 @@ StartPortThread( LPWSTR pName, HWND hWnd, LPWSTR pPortName, FARPROC fpFunction )
return (PortThreadInfo.dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
GetMonitorUIFullName( PWSTR pDeviceName, PWSTR *pModuleName )
{
STRSAFE_LPWSTR SysDir;
UINT length;
HRESULT hr;
*pModuleName = NULL;
SysDir = HeapAlloc(hProcessHeap, 0, MAX_PATH*sizeof(WCHAR));
if ( SysDir )
{
memset( SysDir, 0, MAX_PATH*sizeof(WCHAR) );
length = GetSystemDirectoryW( SysDir, MAX_PATH*sizeof(WCHAR) );
if ( length > 0 )
{
StringCbCatW(SysDir, MAX_PATH*sizeof(WCHAR), L"\\");
hr = StringCchCatW( SysDir, MAX_PATH*sizeof(WCHAR), pDeviceName );
if ( !FAILED(hr) )
{
*pModuleName = SysDir;
return TRUE;
}
SetLastError(HRESULT_CODE(hr));
}
HeapFree(hProcessHeap, 0, SysDir);
}
return FALSE;
}
BOOL WINAPI
GetMonitorUIActivationContext( PWSTR pDeviceName, PMONITORUIDATA pmuid )
{
// ACTCTXW actctx;
// HANDLE handle;
BOOL Ret = FALSE;
FIXME("GMUIAC : Module pDeviceName %S\n",pDeviceName);
if ( !GetMonitorUIFullName( pDeviceName, &pmuid->pModuleName ) )
{
ERR("GetMonitorUIFullName Failed\n");
return Ret;
}
/* OMG! SxS again?
memset(&actctx, 0, sizeof(ACTCTXW));
actctx.cbSize = sizeof(ACTCTXW);
actctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;
actctx.lpResourceName = MAKEINTRESOURCEW(123); This might be the reason....
actctx.lpSource = pmuid->pModuleName;
handle = CreateActCtxW(&actctx);
if ( handle != INVALID_HANDLE_VALUE )
{
pmuid->hActCtx = handle;
if ( ActivateActCtx( handle, &pmuid->ulpCookie ) )
{
pmuid->Activeated = TRUE;
Ret = TRUE;
}
else
{
pmuid->Activeated = FALSE;
}
}
else
{
ERR("GetMonitorUIActivationContext Failed %S\n",pmuid->pModuleName);
}*/
pmuid->hActCtx = INVALID_HANDLE_VALUE;
Ret = TRUE;
return Ret;
}
VOID FASTCALL
FreeMonitorUI( PMONITORUIDATA pmuid )
{
if ( pmuid )
{
if ( pmuid->hLibrary )
{
FreeLibrary( pmuid->hLibrary );
}
if ( pmuid->Activeated )
{
DeactivateActCtx( 0, pmuid->ulpCookie );
}
if ( pmuid->hActCtx != INVALID_HANDLE_VALUE )
{
ReleaseActCtx( pmuid->hActCtx );
}
if ( pmuid->pModuleName )
{
DllFreeSplMem( pmuid->pModuleName );
}
DllFreeSplMem( pmuid );
}
}
BOOL FASTCALL
StrNCatBuff( PWSTR ptr, size_t Size, PWSTR args, ...)
{
va_list Args;
PWSTR pwstr;
HRESULT hr;
BOOL Ret = TRUE;
va_start(Args, args );
for ( pwstr = args ; pwstr ; pwstr = va_arg( Args, PWSTR ) )
{
hr = StringCchCatNW( ptr, Size, pwstr, wcslen(pwstr) );
if ( FAILED(hr) )
{
SetLastError(HRESULT_CODE(hr));
Ret = FALSE;
break;
}
}
va_end(Args);
return Ret;
}
PWSTR WINAPI
ConstructXcvName( PWSTR pName, PWSTR pMonitorPortName, PWSTR pXcvName )
{
BOOL Ret = FALSE;
PWSTR pwstr = NULL;
size_t sXcv, smpn = 0, Size = 0;
if ( pName )
{
Size = wcslen( pName ) + 1;
}
sXcv = wcslen( pXcvName ) + Size;
if ( pMonitorPortName )
{
smpn = wcslen( pMonitorPortName );
}
Size = sXcv + smpn + 3;
pwstr = DllAllocSplMem( Size * sizeof(WCHAR) );
memset( pwstr, 0, Size );
if ( pwstr )
{
// The caller wants an Xcv handle and provided a string like:
// ", XcvMonitor Local Port"
// "\\COMPUTERNAME\, XcvMonitor Local Port"
// ", XcvPort LPT1:"
// "\\COMPUTERNAME\, XcvPort LPT1:"
//
// This produces; !pName ",XcvMonitor " or pName "\\COMPUTERNAME\XcvMonitor "
//
Ret = StrNCatBuff( pwstr,
Size,
pName ? pName : L"",
pName ? L"\\" : L",",
pXcvName,
L" ",
pMonitorPortName ? pMonitorPortName : L"",
NULL );
}
if ( !Ret )
{
DllFreeSplMem( pwstr );
pwstr = NULL;
}
return pwstr;
}
DWORD WINAPI
GetMonitorUI( PWSTR pName, PWSTR pMonitorPortName, PWSTR pXcvName, PMONITORUI *pmui, PMONITORUIDATA *ppmuid )
{
DWORD dwErrorCode = ERROR_SUCCESS, cbOutputNeeded, dwStatus;
HANDLE hPrinter = NULL;
HMODULE hModule;
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
PWSTR pDevice = NULL, pOutputString = NULL;
PMONITORUIDATA pmuid = NULL;
PRINTER_DEFAULTSW wDefault = { 0, 0, PRINTER_ATTRIBUTE_QUEUED };
BYTE OutputData[1024], InputData[4];
*pmui = NULL;
*ppmuid = NULL;
pDevice = ConstructXcvName( pName, pMonitorPortName, pXcvName );
if ( !pDevice )
{
return GetLastError();
}
FIXME("GMUI : XcvName : %S\n",pDevice);
if ( OpenPrinterW( (LPWSTR)pDevice, &hPrinter, &wDefault ) )
{
pHandle = (PSPOOLER_HANDLE)hPrinter;
// Do the RPC call
RpcTryExcept
{
dwErrorCode = _RpcXcvData( pHandle->hPrinter,
L"MonitorUI",
(PBYTE)&InputData,
0,
(PBYTE)&OutputData,
1024,
&cbOutputNeeded,
&dwStatus );
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwErrorCode = RpcExceptionCode();
ERR("GMUI : _RpcXcvData failed with exception code %lu!\n", dwErrorCode);
}
RpcEndExcept;
if ( dwErrorCode == ERROR_INSUFFICIENT_BUFFER )
{
pOutputString = DllAllocSplMem( cbOutputNeeded );
// Do the RPC call
RpcTryExcept
{
dwErrorCode = _RpcXcvData( pHandle->hPrinter,
L"MonitorUI",
(PBYTE)&InputData,
0,
(PBYTE)pOutputString,
cbOutputNeeded,
&cbOutputNeeded,
&dwStatus );
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwErrorCode = RpcExceptionCode();
ERR("GMUI : _RpcXcvData failed with exception code %lu!\n", dwErrorCode);
}
RpcEndExcept;
}
if ( dwErrorCode != ERROR_SUCCESS || dwStatus != ERROR_SUCCESS )
{
goto Cleanup;
}
pmuid = DllAllocSplMem( sizeof(MONITORUIDATA) );
if ( pmuid )
{
memset( pmuid, 0, sizeof(MONITORUIDATA) );
pmuid->hActCtx = INVALID_HANDLE_VALUE;
}
else
{
ERR("GMUI : Memory error\n");
dwErrorCode = GetLastError();
goto Cleanup;
}
if ( GetMonitorUIActivationContext( pOutputString ? pOutputString : (PWSTR)&OutputData, pmuid ) )
{
FIXME("GMUI : MonitorUI Path : %S\n",pmuid->pModuleName);
hModule = LoadLibraryW( pmuid->pModuleName );
if ( hModule )
{
FARPROC fpInitializePrintMonitorUI = (PVOID) GetProcAddress( hModule, "InitializePrintMonitorUI" );
if ( fpInitializePrintMonitorUI )
{
pmuid->hLibrary = hModule;
*pmui = (PMONITORUI)(*fpInitializePrintMonitorUI)();
*ppmuid = pmuid;
}
else
{
ERR("GMUI : Failed to get MUI %S\n",pmuid->pModuleName);
FreeMonitorUI( pmuid );
}
}
else
{
ERR("GMUI : Failed to load library %S\n",pmuid->pModuleName);
}
}
}
else
{
ERR("GMUI : Failed to open printer handle\n");
}
dwErrorCode = GetLastError();
Cleanup:
if ( hPrinter ) ClosePrinter( hPrinter );
if ( pOutputString ) DllFreeSplMem( pOutputString );
if ( pDevice ) DllFreeSplMem( pDevice );
FIXME("GMUI : Error Code Exit %d\n",dwErrorCode);
return dwErrorCode;
}
BOOL WINAPI
AddPortA(PSTR pName, HWND hWnd, PSTR pMonitorName)
@ -113,8 +442,8 @@ AddPortA(PSTR pName, HWND hWnd, PSTR pMonitorName)
res = AddPortW(nameW, hWnd, monitorW);
HeapFree(GetProcessHeap(), 0, nameW);
HeapFree(GetProcessHeap(), 0, monitorW);
if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
if (monitorW) HeapFree(GetProcessHeap(), 0, monitorW);
return res;
}
@ -127,12 +456,12 @@ AddPortExW(PWSTR pName, DWORD Level, PBYTE lpBuffer, PWSTR lpMonitorName)
WINSPOOL_PORT_VAR_CONTAINER PortVarContainer;
WINSPOOL_PORT_INFO_FF *pPortInfoFF;
TRACE("AddPortExW(%S, %lu, %p, %S)\n", pName, Level, lpBuffer, lpMonitorName);
FIXME("AddPortExW(%S, %lu, %p, %S)\n", pName, Level, lpBuffer, lpMonitorName);
switch (Level)
{
case 1:
// FIXME!!!! Only Level 1 is supported? See note in wine winspool test info.c : line 575.
// FIXME!!!! Only Level 1 is supported? See note in wine winspool test info.c : line 575. It's just not supported here.
PortInfoContainer.PortInfo.pPortInfo1 = (WINSPOOL_PORT_INFO_1*)lpBuffer;
PortInfoContainer.Level = Level;
PortVarContainer.cbMonitorData = 0;
@ -182,7 +511,7 @@ AddPortExA(PSTR pName, DWORD Level, PBYTE lpBuffer, PSTR lpMonitorName)
pi1A = (PORT_INFO_1A *)lpBuffer;
pPortInfoFF = (WINSPOOL_PORT_INFO_FF*)lpBuffer;
TRACE("AddPortExA(%s, %d, %p, %s): %s\n", debugstr_a(pName), Level, lpBuffer, debugstr_a(lpMonitorName), debugstr_a(pi1A ? pi1A->pName : NULL));
FIXME("AddPortExA(%s, %d, %p, %s): %s\n", debugstr_a(pName), Level, lpBuffer, debugstr_a(lpMonitorName), debugstr_a(pi1A ? pi1A->pName : NULL));
if ( !lpBuffer || !lpMonitorName )
{
@ -256,8 +585,44 @@ Cleanup:
BOOL WINAPI
AddPortW(PWSTR pName, HWND hWnd, PWSTR pMonitorName)
{
TRACE("AddPortW(%S, %p, %S)\n", pName, hWnd, pMonitorName);
return StartPortThread(pName, hWnd, pMonitorName, (FARPROC)_RpcAddPort);
DWORD SessionId, dwErrorCode = 0;
PMONITORUIDATA pmuid;
PMONITORUI pmui = NULL;
BOOL Ret = FALSE;
FIXME("AddPortW(%S, %p, %S)\n", pName, hWnd, pMonitorName);
dwErrorCode = GetMonitorUI( pName, pMonitorName, L"XcvMonitor", &pmui, &pmuid );
FIXME("AddPortW Error %d\n",dwErrorCode);
if (dwErrorCode != ERROR_SUCCESS )
{
if ( dwErrorCode == ERROR_NOT_SUPPORTED ||
dwErrorCode == ERROR_MOD_NOT_FOUND ||
dwErrorCode == ERROR_INVALID_PRINT_MONITOR ||
dwErrorCode == ERROR_UNKNOWN_PORT ||
dwErrorCode == ERROR_INVALID_PRINTER_NAME )
{
if ( ProcessIdToSessionId( GetCurrentProcessId(), &SessionId ) && SessionId ) // Looking if this is remote.
{
dwErrorCode = ERROR_NOT_SUPPORTED;
}
else
{
Ret = StartPortThread( pName, hWnd, pMonitorName, (PPfpFunction)_RpcAddPort );
FIXME("AddPortW return StartPortThread\n");
dwErrorCode = GetLastError();
}
}
}
else
{
Ret = (*pmui->pfnAddPortUI)( pName, hWnd, pMonitorName, NULL );
}
SetLastError(dwErrorCode);
FreeMonitorUI( pmuid );
return Ret;
}
BOOL WINAPI
@ -288,8 +653,8 @@ ConfigurePortA(PSTR pName, HWND hWnd, PSTR pPortName)
res = ConfigurePortW(nameW, hWnd, portW);
HeapFree(GetProcessHeap(), 0, nameW);
HeapFree(GetProcessHeap(), 0, portW);
if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
if (portW) HeapFree(GetProcessHeap(), 0, portW);
return res;
}
@ -297,8 +662,43 @@ ConfigurePortA(PSTR pName, HWND hWnd, PSTR pPortName)
BOOL WINAPI
ConfigurePortW(PWSTR pName, HWND hWnd, PWSTR pPortName)
{
TRACE("ConfigurePortW(%S, %p, %S)\n", pName, hWnd, pPortName);
return StartPortThread(pName, hWnd, pPortName, (FARPROC)_RpcConfigurePort);
DWORD SessionId, dwErrorCode = 0;
PMONITORUIDATA pmuid;
PMONITORUI pmui = NULL;
BOOL Ret = FALSE;
FIXME("ConfigurePortW(%S, %p, %S)\n", pName, hWnd, pPortName);
dwErrorCode = GetMonitorUI( pName, pPortName, L"XcvPort", &pmui, &pmuid );
if (dwErrorCode != ERROR_SUCCESS )
{
if ( dwErrorCode == ERROR_NOT_SUPPORTED ||
dwErrorCode == ERROR_MOD_NOT_FOUND ||
dwErrorCode == ERROR_INVALID_PRINT_MONITOR ||
dwErrorCode == ERROR_UNKNOWN_PORT ||
dwErrorCode == ERROR_INVALID_PRINTER_NAME )
{
if ( ProcessIdToSessionId( GetCurrentProcessId(), &SessionId ) && SessionId ) // Looking if this is remote.
{
dwErrorCode = ERROR_NOT_SUPPORTED;
}
else
{
Ret = StartPortThread(pName, hWnd, pPortName, (PPfpFunction)_RpcConfigurePort );
dwErrorCode = GetLastError();
}
}
}
else
{
Ret = (*pmui->pfnConfigurePortUI)( pName, hWnd, pPortName );
}
SetLastError(dwErrorCode);
FreeMonitorUI( pmuid );
return Ret;
}
BOOL WINAPI
@ -309,7 +709,7 @@ DeletePortA(PSTR pName, HWND hWnd, PSTR pPortName)
INT len;
DWORD res;
TRACE("DeletePortA(%s, %p, %s)\n", debugstr_a(pName), hWnd, debugstr_a(pPortName));
FIXME("DeletePortA(%s, %p, %s)\n", debugstr_a(pName), hWnd, debugstr_a(pPortName));
/* convert servername to unicode */
if (pName)
@ -329,8 +729,8 @@ DeletePortA(PSTR pName, HWND hWnd, PSTR pPortName)
res = DeletePortW(nameW, hWnd, portW);
HeapFree(GetProcessHeap(), 0, nameW);
HeapFree(GetProcessHeap(), 0, portW);
if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
if (portW) HeapFree(GetProcessHeap(), 0, portW);
return res;
}
@ -338,8 +738,36 @@ DeletePortA(PSTR pName, HWND hWnd, PSTR pPortName)
BOOL WINAPI
DeletePortW(PWSTR pName, HWND hWnd, PWSTR pPortName)
{
TRACE("DeletePortW(%S, %p, %S)\n", pName, hWnd, pPortName);
return StartPortThread(pName, hWnd, pPortName, (FARPROC)_RpcDeletePort);
DWORD dwErrorCode = 0;
PMONITORUIDATA pmuid;
PMONITORUI pmui = NULL;
BOOL Ret = FALSE;
FIXME("DeletePortW(%S, %p, %S)\n", pName, hWnd, pPortName);
dwErrorCode = GetMonitorUI( pName, pPortName, L"XcvPort", &pmui, &pmuid );
FIXME("DeletePortW Error %d\n",dwErrorCode);
if (dwErrorCode != ERROR_SUCCESS )
{
if ( dwErrorCode == ERROR_NOT_SUPPORTED ||
dwErrorCode == ERROR_MOD_NOT_FOUND ||
dwErrorCode == ERROR_INVALID_PRINT_MONITOR ||
dwErrorCode == ERROR_UNKNOWN_PORT ||
dwErrorCode == ERROR_INVALID_PRINTER_NAME )
{
Ret = StartPortThread(pName, hWnd, pPortName, (PPfpFunction)_RpcDeletePort );
dwErrorCode = GetLastError();
}
}
else
{
Ret = (*pmui->pfnDeletePortUI)( pName, hWnd, pPortName );
}
SetLastError(dwErrorCode);
FreeMonitorUI( pmuid );
return Ret;
}
BOOL WINAPI
@ -354,6 +782,13 @@ EnumPortsA(PSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded,
TRACE("EnumPortsA(%s, %d, %p, %d, %p, %p)\n", debugstr_a(pName), Level, pPorts, cbBuf, pcbNeeded, pcReturned);
if ((Level < 1) || (Level > 2))
{
ERR("Level = %d, unsupported!\n", Level);
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
/* convert servername to unicode */
if (pName)
{
@ -470,8 +905,8 @@ cleanup:
if (pcbNeeded) *pcbNeeded = needed;
if (pcReturned) *pcReturned = (res) ? numentries : 0;
HeapFree(GetProcessHeap(), 0, nameW);
HeapFree(GetProcessHeap(), 0, bufferW);
if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
if (bufferW) HeapFree(GetProcessHeap(), 0, bufferW);
TRACE("returning %d with %d (%d byte for %d of %d entries)\n",
(res), GetLastError(), needed, (res)? numentries : 0, numentries);
@ -486,6 +921,13 @@ EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded
TRACE("EnumPortsW(%S, %lu, %p, %lu, %p, %p)\n", pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
if ((Level < 1) || (Level > 2))
{
ERR("Level = %d, unsupported!\n", Level);
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
// Do the RPC call
RpcTryExcept
{

View file

@ -62,9 +62,10 @@ extern CRITICAL_SECTION rtlCritSec;
// utils.c
DWORD UnicodeToAnsiInPlace(PWSTR pwszField);
DWORD UnicodeToAnsiZZInPlace(PWSTR pwszzField);
SECURITY_DESCRIPTOR * get_sd( SECURITY_DESCRIPTOR *sd, DWORD *size );
SECURITY_DESCRIPTOR * get_sd(SECURITY_DESCRIPTOR *sd, DWORD *size);
LONG WINAPI IntProtectHandle(HANDLE,BOOL);
BOOL WINAPI IntUnprotectHandle(HANDLE);
VOID UpdateTrayIcon(HANDLE hPrinter, DWORD JobId);
// devmode.c
extern void RosConvertAnsiDevModeToUnicodeDevmode(PDEVMODEA pDevModeInput, PDEVMODEW *pDevModeOutput);

View file

@ -57,7 +57,7 @@ DeletePrinterDataA(HANDLE hPrinter, PSTR pValueName)
res = DeletePrinterDataW( hPrinter, valuenameW );
HeapFree(GetProcessHeap(), 0, valuenameW);
if (valuenameW) HeapFree(GetProcessHeap(), 0, valuenameW);
return res;
@ -89,8 +89,8 @@ DeletePrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PCSTR pValueName)
res = DeletePrinterDataExW( hPrinter, keynameW, valuenameW );
HeapFree(GetProcessHeap(), 0, keynameW);
HeapFree(GetProcessHeap(), 0, valuenameW);
if (keynameW) HeapFree(GetProcessHeap(), 0, keynameW);
if (valuenameW) HeapFree(GetProcessHeap(), 0, valuenameW);
return res;
}
@ -129,7 +129,7 @@ DeletePrinterKeyA(HANDLE hPrinter, PCSTR pKeyName)
res = DeletePrinterKeyW( hPrinter, keynameW );
HeapFree(GetProcessHeap(), 0, keynameW);
if (keynameW) HeapFree(GetProcessHeap(), 0, keynameW);
return res;
}
@ -219,18 +219,17 @@ EnumPrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PBYTE pEnumValues, DWORD cbE
dwBufSize = 0;
for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex)
{
PPRINTER_ENUM_VALUESW ppev =
&((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
PPRINTER_ENUM_VALUESW ppev = &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
if (dwBufSize < ppev->cbValueName)
dwBufSize = ppev->cbValueName;
if (dwBufSize < ppev->cbData && (ppev->dwType == REG_SZ ||
ppev->dwType == REG_EXPAND_SZ || ppev->dwType == REG_MULTI_SZ))
if ( dwBufSize < ppev->cbData &&
(ppev->dwType == REG_SZ || ppev->dwType == REG_EXPAND_SZ || ppev->dwType == REG_MULTI_SZ))
dwBufSize = ppev->cbData;
}
TRACE ("Largest Unicode name or value is %i bytes\n", dwBufSize);
FIXME ("Largest Unicode name or value is %i bytes\n", dwBufSize);
pBuffer = HeapAlloc (hHeap, 0, dwBufSize);
if (pBuffer == NULL)

View file

@ -7,6 +7,7 @@
#include "precomp.h"
#include <marshalling/printerdrivers.h>
extern const WCHAR wszCurrentEnvironment[];
static int multi_sz_lenA(const char *str)
@ -231,26 +232,26 @@ AddPrinterDriverExA(PSTR pName, DWORD Level, PBYTE pDriverInfo, DWORD dwFileCopy
res = AddPrinterDriverExW(nameW, Level, (LPBYTE) &diW, dwFileCopyFlags);
TRACE("got %u with %u\n", res, GetLastError());
HeapFree(GetProcessHeap(), 0, nameW);
HeapFree(GetProcessHeap(), 0, diW.pName);
HeapFree(GetProcessHeap(), 0, diW.pEnvironment);
HeapFree(GetProcessHeap(), 0, diW.pDriverPath);
HeapFree(GetProcessHeap(), 0, diW.pDataFile);
HeapFree(GetProcessHeap(), 0, diW.pConfigFile);
HeapFree(GetProcessHeap(), 0, diW.pHelpFile);
HeapFree(GetProcessHeap(), 0, diW.pDependentFiles);
HeapFree(GetProcessHeap(), 0, diW.pMonitorName);
HeapFree(GetProcessHeap(), 0, diW.pDefaultDataType);
HeapFree(GetProcessHeap(), 0, diW.pszzPreviousNames);
HeapFree(GetProcessHeap(), 0, diW.pszMfgName);
HeapFree(GetProcessHeap(), 0, diW.pszOEMUrl);
HeapFree(GetProcessHeap(), 0, diW.pszHardwareID);
HeapFree(GetProcessHeap(), 0, diW.pszProvider);
HeapFree(GetProcessHeap(), 0, diW.pszPrintProcessor);
HeapFree(GetProcessHeap(), 0, diW.pszVendorSetup);
HeapFree(GetProcessHeap(), 0, diW.pszzColorProfiles);
HeapFree(GetProcessHeap(), 0, diW.pszInfPath);
HeapFree(GetProcessHeap(), 0, diW.pszzCoreDriverDependencies);
if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
if (diW.pName) HeapFree(GetProcessHeap(), 0, diW.pName);
if (diW.pEnvironment) HeapFree(GetProcessHeap(), 0, diW.pEnvironment);
if (diW.pDriverPath) HeapFree(GetProcessHeap(), 0, diW.pDriverPath);
if (diW.pDataFile) HeapFree(GetProcessHeap(), 0, diW.pDataFile);
if (diW.pConfigFile) HeapFree(GetProcessHeap(), 0, diW.pConfigFile);
if (diW.pHelpFile) HeapFree(GetProcessHeap(), 0, diW.pHelpFile);
if (diW.pDependentFiles) HeapFree(GetProcessHeap(), 0, diW.pDependentFiles);
if (diW.pMonitorName) HeapFree(GetProcessHeap(), 0, diW.pMonitorName);
if (diW.pDefaultDataType) HeapFree(GetProcessHeap(), 0, diW.pDefaultDataType);
if (diW.pszzPreviousNames) HeapFree(GetProcessHeap(), 0, diW.pszzPreviousNames);
if (diW.pszMfgName) HeapFree(GetProcessHeap(), 0, diW.pszMfgName);
if (diW.pszOEMUrl) HeapFree(GetProcessHeap(), 0, diW.pszOEMUrl);
if (diW.pszHardwareID) HeapFree(GetProcessHeap(), 0, diW.pszHardwareID);
if (diW.pszProvider) HeapFree(GetProcessHeap(), 0, diW.pszProvider);
if (diW.pszPrintProcessor) HeapFree(GetProcessHeap(), 0, diW.pszPrintProcessor);
if (diW.pszVendorSetup) HeapFree(GetProcessHeap(), 0, diW.pszVendorSetup);
if (diW.pszzColorProfiles) HeapFree(GetProcessHeap(), 0, diW.pszzColorProfiles);
if (diW.pszInfPath) HeapFree(GetProcessHeap(), 0, diW.pszInfPath);
if (diW.pszzCoreDriverDependencies) HeapFree(GetProcessHeap(), 0, diW.pszzCoreDriverDependencies);
TRACE("=> %u with %u\n", res, GetLastError());
return res;
@ -259,7 +260,7 @@ AddPrinterDriverExA(PSTR pName, DWORD Level, PBYTE pDriverInfo, DWORD dwFileCopy
BOOL WINAPI
AddPrinterDriverExW(PWSTR pName, DWORD Level, PBYTE pDriverInfo, DWORD dwFileCopyFlags)
{
DWORD dwErrorCode;
DWORD dwErrorCode = ERROR_SUCCESS;
WINSPOOL_DRIVER_INFO_8 * pdi = NULL;
WINSPOOL_DRIVER_CONTAINER pDriverContainer;
@ -310,7 +311,6 @@ AddPrinterDriverExW(PWSTR pName, DWORD Level, PBYTE pDriverInfo, DWORD dwFileCop
}
case 4:
{
PDRIVER_INFO_4W pdi4w = (PDRIVER_INFO_4W)pDriverInfo;
if ( pdi == NULL ) pdi = HeapAlloc(hProcessHeap, 0, sizeof(WINSPOOL_DRIVER_INFO_4));
@ -398,6 +398,7 @@ DeletePrinterDriverA(PSTR pName, PSTR pEnvironment, PSTR pDriverName)
BOOL WINAPI
DeletePrinterDriverExA(PSTR pName, PSTR pEnvironment, PSTR pDriverName, DWORD dwDeleteFlag, DWORD dwVersionFlag)
{
DWORD dwErrorCode;
UNICODE_STRING NameW, EnvW, DriverW;
BOOL ret;
@ -409,10 +410,13 @@ DeletePrinterDriverExA(PSTR pName, PSTR pEnvironment, PSTR pDriverName, DWORD dw
ret = DeletePrinterDriverExW(NameW.Buffer, EnvW.Buffer, DriverW.Buffer, dwDeleteFlag, dwVersionFlag);
dwErrorCode = GetLastError();
RtlFreeUnicodeString(&DriverW);
RtlFreeUnicodeString(&EnvW);
RtlFreeUnicodeString(&NameW);
SetLastError(dwErrorCode);
return ret;
}
@ -461,20 +465,22 @@ DeletePrinterDriverW(PWSTR pName, PWSTR pEnvironment, PWSTR pDriverName)
BOOL WINAPI
EnumPrinterDriversA(PSTR pName, PSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
BOOL ret;
BOOL ret = FALSE;
DWORD dwErrorCode, i;
UNICODE_STRING pNameW, pEnvironmentW;
PWSTR pwstrNameW, pwstrEnvironmentW;
PDRIVER_INFO_1W pdi1w = (PDRIVER_INFO_1W)pDriverInfo;
PDRIVER_INFO_8W pdi8w = (PDRIVER_INFO_8W)pDriverInfo;
TRACE("EnumPrinterDriversA(%s, %s, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned);
FIXME("EnumPrinterDriversA(%s, %s, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned);
pwstrNameW = AsciiToUnicode(&pNameW, pName);
pwstrEnvironmentW = AsciiToUnicode(&pEnvironmentW, pEnvironment);
ret = EnumPrinterDriversW( pwstrNameW, pwstrEnvironmentW, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned );
dwErrorCode = GetLastError();
if (ret)
{
for ( i = 0; i < *pcReturned; i++ )
@ -613,11 +619,13 @@ EnumPrinterDriversA(PSTR pName, PSTR pEnvironment, DWORD Level, PBYTE pDriverInf
}
}
}
dwErrorCode = ERROR_SUCCESS;
}
Cleanup:
RtlFreeUnicodeString(&pNameW);
RtlFreeUnicodeString(&pEnvironmentW);
SetLastError(dwErrorCode);
FIXME("EnumPrinterDriversA Exit %d Err %d\n",ret,GetLastError());
return ret;
}
@ -626,10 +634,10 @@ EnumPrinterDriversW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverI
{
DWORD dwErrorCode;
TRACE("EnumPrinterDriversW(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned);
FIXME("EnumPrinterDriversW(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned);
// Dismiss invalid levels already at this point.
if (Level > 8 || Level == 7 || Level < 1)
if (Level < 1 || Level == 7 || Level > 8)
{
dwErrorCode = ERROR_INVALID_LEVEL;
goto Cleanup;
@ -663,7 +671,7 @@ EnumPrinterDriversW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverI
}
Cleanup:
SetLastError(dwErrorCode);
SetLastError(dwErrorCode); FIXME("EnumPrinterDriversW Exit Err %d\n",dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
@ -688,7 +696,7 @@ GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriv
if (Level < 1 || Level == 7 || Level > 8)
{
dwErrorCode = ERROR_INVALID_LEVEL;
ERR("Invalid Level!\n");
ERR("Invalid Level! %d\n",Level);
goto Cleanup;
}
@ -817,13 +825,13 @@ GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriv
case 2:
case 5:
{
dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pName);
dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pConfigFile);
if (dwErrorCode != ERROR_SUCCESS)
{
goto Cleanup;
}
dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pDataFile);
dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pEnvironment);
if (dwErrorCode != ERROR_SUCCESS)
{
goto Cleanup;
@ -835,13 +843,13 @@ GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriv
goto Cleanup;
}
dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pDataFile);
dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pEnvironment);
if (dwErrorCode != ERROR_SUCCESS)
{
goto Cleanup;
}
dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pConfigFile);
dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pName);
if (dwErrorCode != ERROR_SUCCESS)
{
goto Cleanup;
@ -977,6 +985,12 @@ GetPrinterDriverDirectoryW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE p
TRACE("GetPrinterDriverDirectoryW(%S, %S, %lu, %p, %lu, %p)\n", pName, pEnvironment, Level, pDriverDirectory, cbBuf, pcbNeeded);
if (Level != 1)
{
dwErrorCode = ERROR_INVALID_LEVEL;
goto Cleanup;
}
if ( !pEnvironment || !*pEnvironment )
{
pEnvironment = (PWSTR)wszCurrentEnvironment;
@ -994,6 +1008,7 @@ GetPrinterDriverDirectoryW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE p
}
RpcEndExcept;
Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}

View file

@ -509,7 +509,7 @@ LoadPrinterDriver( HANDLE hspool )
hLibrary = LoadLibrary(pdi->pConfigFile);
FIXME("IGPD : Get Printer Driver %S\n",pdi->pConfigFile);
FIXME("IGPD : Get Printer Driver Config File : %S\n",pdi->pConfigFile);
RtlFreeHeap( GetProcessHeap(), 0, pdi);
return hLibrary;
@ -657,7 +657,7 @@ DevQueryPrintEx( PDEVQUERYPRINT_INFO pDQPInfo )
INT WINAPI
DocumentEvent( HANDLE hPrinter, HDC hdc, int iEsc, ULONG cbIn, PVOID pvIn, ULONG cbOut, PVOID pvOut)
{
TRACE("DocumentEvent(%p, %p, %lu, %lu, %p, %lu, %p)\n", hPrinter, hdc, iEsc, cbIn, pvIn, cbOut, pvOut);
FIXME("DocumentEvent(%p, %p, %lu, %lu, %p, %lu, %p)\n", hPrinter, hdc, iEsc, cbIn, pvIn, cbOut, pvOut);
UNIMPLEMENTED;
return DOCUMENTEVENT_UNSUPPORTED;
}
@ -2938,6 +2938,38 @@ ResetPrinterW(HANDLE hPrinter, PPRINTER_DEFAULTSW pDefault)
return FALSE;
}
BOOL WINAPI
SeekPrinter( HANDLE hPrinter, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER pliNewPointer, DWORD dwMoveMethod, BOOL bWrite )
{
DWORD dwErrorCode;
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
FIXME("SeekPrinter(%p, %I64u, %p, %lu, %d)\n", hPrinter, liDistanceToMove.QuadPart, pliNewPointer, dwMoveMethod, bWrite);
// Sanity checks.
if (!pHandle)
{
dwErrorCode = ERROR_INVALID_HANDLE;
goto Cleanup;
}
// Do the RPC call
RpcTryExcept
{
dwErrorCode = _RpcSeekPrinter(pHandle->hPrinter, liDistanceToMove, pliNewPointer, dwMoveMethod, bWrite);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwErrorCode = RpcExceptionCode();
ERR("_RpcSeekPrinter failed with exception code %lu!\n", dwErrorCode);
}
RpcEndExcept;
Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
SetDefaultPrinterA(LPCSTR pszPrinter)
{
@ -3802,7 +3834,7 @@ StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
dwReturnValue = pHandle->dwJobID;
if ( !pHandle->bTrayIcon )
{
FIXME("Notify Tray Icon\n");
UpdateTrayIcon( hPrinter, pHandle->dwJobID );
}
}
@ -3905,6 +3937,65 @@ Cleanup:
BOOL WINAPI
XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus)
{
DWORD dwErrorCode, Bogus = 0;
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hXcv;
TRACE("XcvDataW(%p, %S, %p, %lu, %p, %lu, %p, %p)\n", hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded, pdwStatus);
return FALSE;
if ( pcbOutputNeeded == NULL )
{
dwErrorCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
// Sanity checks.
if (!pHandle) // ( IntProtectHandle( hXcv, FALSE ) )
{
dwErrorCode = ERROR_INVALID_HANDLE;
goto Cleanup;
}
//
// Do fixups.
//
if ( pInputData == NULL )
{
if ( !cbInputData )
{
pInputData = (PBYTE)&Bogus;
}
}
if ( pOutputData == NULL )
{
if ( !cbOutputData )
{
pOutputData = (PBYTE)&Bogus;
}
}
// Do the RPC call
RpcTryExcept
{
dwErrorCode = _RpcXcvData( pHandle->hPrinter,
pszDataName,
pInputData,
cbInputData,
pOutputData,
cbOutputData,
pcbOutputNeeded,
pdwStatus );
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwErrorCode = RpcExceptionCode();
ERR("_RpcXcvData failed with exception code %lu!\n", dwErrorCode);
}
RpcEndExcept;
//IntUnprotectHandle( hXcv );
Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}

View file

@ -246,9 +246,9 @@ epp_cleanup:
if (pcbNeeded) *pcbNeeded = needed;
if (pcReturned) *pcReturned = (res) ? numentries : 0;
HeapFree(GetProcessHeap(), 0, nameW);
HeapFree(GetProcessHeap(), 0, envW);
HeapFree(GetProcessHeap(), 0, bufferW);
if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
if (envW) HeapFree(GetProcessHeap(), 0, envW);
if (bufferW) HeapFree(GetProcessHeap(), 0, bufferW);
TRACE("returning %d with %d (%d byte for %d entries)\n", (res), GetLastError(), needed, numentries);

View file

@ -6,6 +6,14 @@
*/
#include "precomp.h"
#include <shlobj.h>
#include <undocshell.h>
#define MAX_GETPRINTER_SIZE 4096 - MAX_PATH
typedef void (WINAPI *PPfpSHChangeNotify)(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2);
static HMODULE hShell32 = (HMODULE)-1;
/*
* Converts an incoming Unicode string to an ANSI string.
@ -330,3 +338,41 @@ SECURITY_DESCRIPTOR * get_sd( SECURITY_DESCRIPTOR *sd, DWORD *size )
return retsd;
}
VOID
UpdateTrayIcon( HANDLE hPrinter, DWORD JobId )
{
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
SHCNF_PRINTJOB_INFO spji;
PRINTER_INFO_1W pi1w[MAX_GETPRINTER_SIZE] = {0};
DWORD cbNeeded;
PPfpSHChangeNotify fpFunction;
pHandle->bTrayIcon = TRUE;
spji.JobId = JobId;
if (!GetPrinterW( hPrinter, 1, (PBYTE)&pi1w, MAX_GETPRINTER_SIZE, &cbNeeded) )
{
ERR("UpdateTrayIcon : GetPrinterW cbNeeded %d\n");
return;
}
if ( hShell32 == (HMODULE)-1 )
{
hShell32 = LoadLibraryW(L"shell32.dll");
}
if ( hShell32 )
{
fpFunction = (PPfpSHChangeNotify)GetProcAddress( hShell32, "SHChangeNotify" );
if ( fpFunction )
{
fpFunction( SHCNE_CREATE, (SHCNF_FLUSHNOWAIT|SHCNF_FLUSH|SHCNF_PRINTJOBW), pi1w->pName , &spji );
}
}
else
{
ERR("UpdateTrayIcon : No Shell32!\n");
}
}

View file

@ -172,7 +172,7 @@
271 stdcall ResetPrinterA(ptr ptr)
272 stdcall ResetPrinterW(ptr ptr)
273 stdcall ScheduleJob(ptr long)
274 stdcall -stub SeekPrinter(ptr int64 ptr long long)
274 stdcall SeekPrinter(ptr int64 ptr long long)
275 stub SetAllocFailCount
276 stdcall SetFormA(ptr str long str)
277 stdcall SetFormW(ptr str long str)

View file

@ -8,7 +8,10 @@
static const MARSHALLING FormInfo1Marshalling = {
sizeof(FORM_INFO_1W),
{
{ FIELD_OFFSET(FORM_INFO_1W, Flags), RTL_FIELD_SIZE(FORM_INFO_1W, Flags), RTL_FIELD_SIZE(FORM_INFO_1W, Flags), FALSE },
{ FIELD_OFFSET(FORM_INFO_1W, pName), RTL_FIELD_SIZE(FORM_INFO_1W, pName), RTL_FIELD_SIZE(FORM_INFO_1W, pName), TRUE },
{ FIELD_OFFSET(FORM_INFO_1W, Size), RTL_FIELD_SIZE(FORM_INFO_1W, Size), RTL_FIELD_SIZE(FORM_INFO_1W, Size), FALSE },
{ FIELD_OFFSET(FORM_INFO_1W, ImageableArea), RTL_FIELD_SIZE(FORM_INFO_1W, ImageableArea), RTL_FIELD_SIZE(FORM_INFO_1W, ImageableArea), FALSE },
{ MAXDWORD, 0, 0, FALSE }
}
};
@ -16,10 +19,16 @@ static const MARSHALLING FormInfo1Marshalling = {
static const MARSHALLING FormInfo2Marshalling = {
sizeof(FORM_INFO_2W),
{
{ FIELD_OFFSET(FORM_INFO_2W, Flags), RTL_FIELD_SIZE(FORM_INFO_2W, Flags), RTL_FIELD_SIZE(FORM_INFO_2W, Flags), FALSE },
{ FIELD_OFFSET(FORM_INFO_2W, pName), RTL_FIELD_SIZE(FORM_INFO_2W, pName), RTL_FIELD_SIZE(FORM_INFO_2W, pName), TRUE },
{ FIELD_OFFSET(FORM_INFO_2W, Size), RTL_FIELD_SIZE(FORM_INFO_2W, Size), RTL_FIELD_SIZE(FORM_INFO_2W, Size), FALSE },
{ FIELD_OFFSET(FORM_INFO_2W, ImageableArea), RTL_FIELD_SIZE(FORM_INFO_2W, ImageableArea), RTL_FIELD_SIZE(FORM_INFO_2W, ImageableArea), FALSE },
{ FIELD_OFFSET(FORM_INFO_2W, pKeyword), RTL_FIELD_SIZE(FORM_INFO_2W, pKeyword), RTL_FIELD_SIZE(FORM_INFO_2W, pKeyword), TRUE },
{ FIELD_OFFSET(FORM_INFO_2W, StringType), RTL_FIELD_SIZE(FORM_INFO_2W, StringType), RTL_FIELD_SIZE(FORM_INFO_2W, StringType), FALSE },
{ FIELD_OFFSET(FORM_INFO_2W, pMuiDll), RTL_FIELD_SIZE(FORM_INFO_2W, pMuiDll), RTL_FIELD_SIZE(FORM_INFO_2W, pMuiDll), TRUE },
{ FIELD_OFFSET(FORM_INFO_2W, pDisplayName), RTL_FIELD_SIZE(FORM_INFO_2W, pDisplayName), RTL_FIELD_SIZE(FORM_INFO_2W, pDisplayName), FALSE },
{ FIELD_OFFSET(FORM_INFO_2W, dwResourceId), RTL_FIELD_SIZE(FORM_INFO_2W, dwResourceId), RTL_FIELD_SIZE(FORM_INFO_2W, dwResourceId), FALSE },
{ FIELD_OFFSET(FORM_INFO_2W, pDisplayName), RTL_FIELD_SIZE(FORM_INFO_2W, pDisplayName), RTL_FIELD_SIZE(FORM_INFO_2W, pDisplayName), TRUE },
{ FIELD_OFFSET(FORM_INFO_2W, wLangId), RTL_FIELD_SIZE(FORM_INFO_2W, wLangId), RTL_FIELD_SIZE(FORM_INFO_2W, wLangId), FALSE },
{ MAXDWORD, 0, 0, FALSE }
}
};

View file

@ -125,5 +125,6 @@ static const MARSHALLING* pPrinterDriverMarshalling[] = {
&PrinterDriver4Marshalling,
&PrinterDriver5Marshalling,
&PrinterDriver6Marshalling,
NULL,
&PrinterDriver8Marshalling,
};

View file

@ -8,6 +8,21 @@
#ifndef _REACTOS_SPOOLSS_H
#define _REACTOS_SPOOLSS_H
#define RESETPRINTERDEFAULTDATATYPE 0x0001
#define RESETPRINTERDEFAULTDEVMODE 0x0002
#define PORT_IS_UNKNOWN 0
#define PORT_IS_LPT 1
#define PORT_IS_COM 2
#define PORT_IS_FILE 3
#define PORT_IS_FILENAME 4
#define PORT_IS_WINE 5
#define PORT_IS_UNIXNAME 5
#define PORT_IS_PIPE 6
#define PORT_IS_VNET 7
#define PORT_IS_XPS 8
// Constants
#define MAX_PRINTER_NAME 220
@ -64,6 +79,7 @@ typedef struct _FILE_INFO_1
DWORD dwOptions;
} FILE_INFO_1, *PFILE_INFO_1;
BOOL WINAPI AddPortExW(LPWSTR, DWORD, LPBYTE, LPWSTR);
PVOID WINAPI AlignRpcPtr(PVOID pBuffer, PDWORD pcbBuffer);
PWSTR WINAPI AllocSplStr(PCWSTR pwszInput);
PVOID WINAPI DllAllocSplMem(DWORD dwBytes);
@ -73,11 +89,13 @@ BOOL WINAPI InitializeRouter(HANDLE SpoolerStatusHandle);
PBYTE WINAPI PackStrings(PCWSTR* pSource, PBYTE pDest, const DWORD* DestOffsets, PBYTE pEnd);
PVOID WINAPI ReallocSplMem(PVOID pOldMem, DWORD cbOld, DWORD cbNew);
BOOL WINAPI ReallocSplStr(PWSTR* ppwszString, PCWSTR pwszInput);
BOOL WINAPI SeekPrinter(HANDLE hPrinter,LARGE_INTEGER liDistanceToMove,PLARGE_INTEGER pliNewPointer,DWORD dwMoveMethod,BOOL bWrite);
BOOL WINAPI SplInitializeWinSpoolDrv(PVOID* pTable);
BOOL WINAPI SpoolerInit(VOID);
PDWORD WINAPI UndoAlignRpcPtr(PVOID pDestinationBuffer, PVOID pSourceBuffer, DWORD cbBuffer, PDWORD pcbNeeded);
BOOL WINAPI SplGetSpoolFileInfo(HANDLE hPrinter,HANDLE hProcessHandle,DWORD Level,FILE_INFO_1 *pFileInfo,DWORD dwSize,DWORD* dwNeeded );
BOOL WINAPI SplCommitSpoolData(HANDLE hPrinter,HANDLE hProcessHandle,DWORD cbCommit,DWORD Level,FILE_INFO_1 *pFileInfo,DWORD dwSize,DWORD* dwNeeded);
BOOL WINAPI SplCloseSpoolFileHandle( HANDLE hPrinter );
BOOL WINAPI GetPrinterDriverExW(HANDLE hPrinter,LPWSTR pEnvironment,DWORD Level,LPBYTE pDriverInfo,DWORD cbBuf,LPDWORD pcbNeeded,DWORD dwClientMajorVersion,DWORD dwClientMinorVersion,PDWORD pdwServerMajorVersion,PDWORD pdwServerMinorVersion );
#endif

View file

@ -24,10 +24,10 @@ static MONITOR2 _MonitorFunctions = {
LocalmonReadPort, // pfnReadPort
LocalmonEndDocPort, // pfnEndDocPort
LocalmonClosePort, // pfnClosePort
NULL, // pfnAddPort
NULL, // pfnAddPortEx
NULL, // pfnConfigurePort
NULL, // pfnDeletePort
LocalmonAddPort, // pfnAddPort moved to localui.dll since w2k, but~
LocalmonAddPortEx, // pfnAddPortEx
LocalmonConfigurePort, // pfnConfigurePort moved to localui.dll since w2k, but~
LocalmonDeletePort, // pfnDeletePort moved to localui.dll since w2k, but~
LocalmonGetPrinterDataFromPort, // pfnGetPrinterDataFromPort
LocalmonSetPortTimeOuts, // pfnSetPortTimeOuts
LocalmonXcvOpenPort, // pfnXcvOpenPort
@ -114,32 +114,48 @@ LocalmonShutdown(HANDLE hMonitor)
PLOCALMON_HANDLE pLocalmon;
PLOCALMON_PORT pPort;
PLOCALMON_XCV pXcv;
PLIST_ENTRY pEntry;
TRACE("LocalmonShutdown(%p)\n", hMonitor);
pLocalmon = (PLOCALMON_HANDLE)hMonitor;
// Close all virtual file ports.
while (!IsListEmpty(&pLocalmon->FilePorts))
if ( pLocalmon->Sig != SIGLCMMON )
{
pPort = CONTAINING_RECORD(&pLocalmon->FilePorts.Flink, LOCALMON_PORT, Entry);
LocalmonClosePort((HANDLE)pPort);
ERR("LocalmonShutdown : Invalid Monitor Handle\n",hMonitor);
return;
}
// Close all virtual file ports.
if (!IsListEmpty(&pLocalmon->FilePorts))
{
for (pEntry = pLocalmon->FilePorts.Flink; pEntry != &pLocalmon->FilePorts; pEntry = pEntry->Flink)
{
pPort = CONTAINING_RECORD(&pLocalmon->FilePorts.Flink, LOCALMON_PORT, Entry);
LocalmonClosePort((HANDLE)pPort);
}
}
// Do the same for the open Xcv ports.
while (!IsListEmpty(&pLocalmon->XcvHandles))
if (!IsListEmpty(&pLocalmon->XcvHandles))
{
pXcv = CONTAINING_RECORD(&pLocalmon->XcvHandles.Flink, LOCALMON_XCV, Entry);
LocalmonXcvClosePort((HANDLE)pXcv);
for (pEntry = pLocalmon->XcvHandles.Flink; pEntry != &pLocalmon->XcvHandles; pEntry = pEntry->Flink)
{
pXcv = CONTAINING_RECORD(pEntry, LOCALMON_XCV, Entry);
LocalmonXcvClosePort((HANDLE)pXcv);
}
}
// Now close all registry ports, remove them from the list and free their memory.
while (!IsListEmpty(&pLocalmon->RegistryPorts))
if (!IsListEmpty(&pLocalmon->RegistryPorts))
{
pPort = CONTAINING_RECORD(&pLocalmon->RegistryPorts.Flink, LOCALMON_PORT, Entry);
LocalmonClosePort((HANDLE)pPort);
RemoveEntryList(&pPort->Entry);
DllFreeSplMem(pPort);
for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink)
{
pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry);
if ( LocalmonClosePort((HANDLE)pPort) ) continue;
RemoveEntryList(&pPort->Entry);
DllFreeSplMem(pPort);
}
}
// Finally clean the LOCALMON_HANDLE structure itself.
@ -164,6 +180,7 @@ InitializePrintMonitor2(PMONITORINIT pMonitorInit, PHANDLE phMonitor)
// Create a new LOCALMON_HANDLE structure.
pLocalmon = DllAllocSplMem(sizeof(LOCALMON_HANDLE));
pLocalmon->Sig = SIGLCMMON;
InitializeCriticalSection(&pLocalmon->Section);
InitializeListHead(&pLocalmon->FilePorts);
InitializeListHead(&pLocalmon->RegistryPorts);
@ -198,9 +215,10 @@ InitializePrintMonitor2(PMONITORINIT pMonitorInit, PHANDLE phMonitor)
goto Cleanup;
}
pPort->Sig = SIGLCMPORT;
pPort->pLocalmon = pLocalmon;
pPort->hFile = INVALID_HANDLE_VALUE;
pPort->pwszPortName = (PWSTR)((PBYTE)pPort + sizeof(LOCALMON_PORT));
pPort->pwszPortName = (PWSTR)(pPort+1);
// Get the port name.
cchPortName = cchMaxPortName + 1;
@ -229,6 +247,7 @@ InitializePrintMonitor2(PMONITORINIT pMonitorInit, PHANDLE phMonitor)
// Add it to the list.
InsertTailList(&pLocalmon->RegistryPorts, &pPort->Entry);
TRACE("InitializePrintMonitor2 Port : %s \n",debugstr_w(pPort->pwszPortName));
// Don't let the cleanup routine free this.
pPort = NULL;

View file

@ -139,7 +139,6 @@ _ClosePortHandles(PLOCALMON_PORT pPort)
DefineDosDeviceW(DDD_REMOVE_DEFINITION, pwszNonspooledPortName, NULL);
DllFreeSplMem(pwszNonspooledPortName);
}
DllFreeSplMem(pwszPortNameWithoutColon);
}
}
@ -1050,3 +1049,180 @@ Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
LocalmonAddPortEx( HANDLE hMonitor, LPWSTR pName, DWORD Level, LPBYTE lpBuffer, LPWSTR lpMonitorName )
{
PLOCALMON_HANDLE pLocalmon = (PLOCALMON_HANDLE)hMonitor;
PLOCALMON_PORT pPort;
HKEY hKey;
DWORD dwErrorCode, cbPortName;
PORT_INFO_1W * pi = (PORT_INFO_1W *) lpBuffer;
FIXME("LocalmonAddPortEx(%p, %lu, %p, %s) => %s\n", hMonitor, Level, lpBuffer, debugstr_w(lpMonitorName), debugstr_w(pi ? pi->pName : NULL));
// Sanity checks
if ( !pLocalmon )
{
dwErrorCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
if ( ( lpMonitorName == NULL ) ||
( lstrcmpiW( lpMonitorName, L"Local Port" ) != 0 ) ||
( pi == NULL ) ||
( pi->pName == NULL ) ||
( pi->pName[0] == '\0' ) )
{
ERR("Fail Monitor Port Name\n");
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if ( Level != 1 )
{
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
dwErrorCode = RegOpenKeyW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Ports", &hKey );
if ( dwErrorCode == ERROR_SUCCESS )
{
if ( DoesPortExist( pi->pName ) )
{
RegCloseKey( hKey) ;
FIXME("Port Exist => FALSE with %u\n", ERROR_INVALID_PARAMETER);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
cbPortName = (wcslen( pi->pName ) + 1) * sizeof(WCHAR);
// Create a new LOCALMON_PORT structure for it.
pPort = DllAllocSplMem(sizeof(LOCALMON_PORT) + cbPortName);
if (!pPort)
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
RegCloseKey( hKey );
goto Cleanup;
}
pPort->Sig = SIGLCMPORT;
pPort->hFile = INVALID_HANDLE_VALUE;
pPort->pLocalmon = pLocalmon;
pPort->pwszPortName = wcscpy( (PWSTR)(pPort+1), pi->pName );
// Insert it into the Registry list.
InsertTailList(&pLocalmon->RegistryPorts, &pPort->Entry);
dwErrorCode = RegSetValueExW( hKey, pi->pName, 0, REG_SZ, (const BYTE *) L"", sizeof(L"") );
RegCloseKey( hKey );
}
Cleanup:
if (dwErrorCode != ERROR_SUCCESS) SetLastError(ERROR_INVALID_PARAMETER);
FIXME("LocalmonAddPortEx => %u with %u\n", (dwErrorCode == ERROR_SUCCESS), GetLastError());
return (dwErrorCode == ERROR_SUCCESS);
}
// Fallback Throw Back code....
//
// This is pre-w2k support, seems to be moved into LocalUI.
//
//
BOOL WINAPI
LocalmonAddPort( HANDLE hMonitor, LPWSTR pName, HWND hWnd, LPWSTR pMonitorName )
{
DWORD res, cbPortName;
HKEY hroot;
PLOCALMON_HANDLE pLocalmon = (PLOCALMON_HANDLE)hMonitor;
PLOCALMON_PORT pPort;
WCHAR PortName[MAX_PATH] = {0}; // Need to use a Dialog to get name.
FIXME("LocalmonAddPort : %s\n", debugstr_w( (LPWSTR) pMonitorName ) );
res = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Ports", &hroot);
if (res == ERROR_SUCCESS)
{
if ( DoesPortExist( PortName ) )
{
RegCloseKey(hroot);
FIXME("=> %u\n", ERROR_ALREADY_EXISTS);
res = ERROR_ALREADY_EXISTS;
goto Cleanup;
}
cbPortName = (wcslen( PortName ) + 1) * sizeof(WCHAR);
// Create a new LOCALMON_PORT structure for it.
pPort = DllAllocSplMem(sizeof(LOCALMON_PORT) + cbPortName);
if (!pPort)
{
res = ERROR_NOT_ENOUGH_MEMORY;
RegCloseKey( hroot );
goto Cleanup;
}
pPort->Sig = SIGLCMPORT;
pPort->hFile = INVALID_HANDLE_VALUE;
pPort->pLocalmon = pLocalmon;
pPort->pwszPortName = wcscpy( (PWSTR)(pPort+1), PortName );
// Insert it into the Registry list.
InsertTailList(&pLocalmon->RegistryPorts, &pPort->Entry);
res = RegSetValueExW(hroot, PortName, 0, REG_SZ, (const BYTE *) L"", sizeof(L""));
RegCloseKey(hroot);
}
FIXME("=> %u\n", res);
Cleanup:
SetLastError(res);
return (res == ERROR_SUCCESS);
}
BOOL WINAPI
LocalmonConfigurePort( HANDLE hMonitor, LPWSTR pName, HWND hWnd, LPWSTR pPortName )
{
//// See ConfigurePortUI
FIXME("LocalmonConfigurePort : %s\n", debugstr_w( pPortName ) );
return FALSE;
}
BOOL WINAPI
LocalmonDeletePort( HANDLE hMonitor, LPWSTR pName, HWND hWnd, LPWSTR pPortName )
{
DWORD res;
HKEY hroot;
PLOCALMON_HANDLE pLocalmon = (PLOCALMON_HANDLE)hMonitor;
PLOCALMON_PORT pPort;
FIXME("LocalmonDeletePort : %s\n", debugstr_w( pPortName ) );
res = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Ports", &hroot);
if ( res == ERROR_SUCCESS )
{
res = RegDeleteValueW(hroot, pPortName );
RegCloseKey(hroot);
pPort = _FindPort( pLocalmon, pPortName );
if ( pPort )
{
EnterCriticalSection(&pPort->pLocalmon->Section);
RemoveEntryList(&pPort->Entry);
LeaveCriticalSection(&pPort->pLocalmon->Section);
DllFreeSplMem(pPort);
}
FIXME("=> %u with %u\n", res, GetLastError() );
}
SetLastError(res);
return (res == ERROR_SUCCESS);
}

View file

@ -27,6 +27,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(localmon);
#include "resource.h"
#define SIGLCMMON 'FrCN'
#define SIGLCMPORT 'FrHK'
// Structures
/**
* Describes the monitor handle returned by InitializePrintMonitor2.
@ -35,6 +38,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(localmon);
typedef struct _LOCALMON_HANDLE
{
CRITICAL_SECTION Section; /** Critical Section for modifying or reading the ports. */
DWORD Sig;
LIST_ENTRY FilePorts; /** Ports created when a document is printed on FILE: and the user entered a file name. */
LIST_ENTRY RegistryPorts; /** Valid ports loaded from the local registry. */
LIST_ENTRY XcvHandles; /** Xcv handles created with LocalmonXcvOpenPort. */
@ -48,6 +52,9 @@ LOCALMON_HANDLE, *PLOCALMON_HANDLE;
typedef struct _LOCALMON_PORT
{
LIST_ENTRY Entry;
PWSTR pwszPortName; /** The name of this port including the trailing colon. Empty for virtual file ports. */
PLOCALMON_HANDLE pLocalmon; /** Pointer to the parent LOCALMON_HANDLE structure. */
DWORD Sig;
enum {
PortType_Other = 0, /** Any port that doesn't belong into the other categories (default). */
PortType_FILE, /** A port created when a document is printed on FILE: and the user entered a file name. */
@ -59,9 +66,7 @@ typedef struct _LOCALMON_PORT
DWORD dwJobID; /** ID of the printing job we are processing (for later reporting progress using SetJobW). */
HANDLE hFile; /** Handle to the opened port or INVALID_HANDLE_VALUE if it isn't currently opened. */
HANDLE hPrinter; /** Handle to the printer for the job on this port (for using SetJobW). */
PLOCALMON_HANDLE pLocalmon; /** Pointer to the parent LOCALMON_HANDLE structure. */
PWSTR pwszMapping; /** The current mapping of the DOS Device corresponding to this port at the time _CreateNonspooledPort has been called. */
PWSTR pwszPortName; /** The name of this port including the trailing colon. Empty for virtual file ports. */
}
LOCALMON_PORT, *PLOCALMON_PORT;
@ -95,11 +100,16 @@ BOOL WINAPI LocalmonReadPort(HANDLE hPort, PBYTE pBuffer, DWORD cbBuffer, PDWORD
BOOL WINAPI LocalmonSetPortTimeOuts(HANDLE hPort, LPCOMMTIMEOUTS lpCTO, DWORD Reserved);
BOOL WINAPI LocalmonStartDocPort(HANDLE hPort, PWSTR pPrinterName, DWORD JobId, DWORD Level, PBYTE pDocInfo);
BOOL WINAPI LocalmonWritePort(HANDLE hPort, PBYTE pBuffer, DWORD cbBuf, PDWORD pcbWritten);
BOOL WINAPI LocalmonAddPort( HANDLE hMonitor, LPWSTR pName, HWND hWnd, LPWSTR pMonitorName );
BOOL WINAPI LocalmonAddPortEx( HANDLE hMonitor, LPWSTR pName, DWORD Level, LPBYTE lpBuffer, LPWSTR lpMonitorName );
BOOL WINAPI LocalmonConfigurePort( HANDLE hMonitor, LPWSTR pName, HWND hWnd, LPWSTR pPortName );
BOOL WINAPI LocalmonDeletePort( HANDLE hMonitor, LPWSTR pName, HWND hWnd, LPWSTR pPortName );
// tools.c
BOOL DoesPortExist(PCWSTR pwszPortName);
DWORD GetLPTTransmissionRetryTimeout(VOID);
DWORD GetPortNameWithoutColon(PCWSTR pwszPortName, PWSTR* ppwszPortNameWithoutColon);
DWORD GetTypeFromName(LPCWSTR name);
// xcv.c
BOOL WINAPI LocalmonXcvClosePort(HANDLE hXcv);

View file

@ -164,3 +164,97 @@ GetPortNameWithoutColon(PCWSTR pwszPortName, PWSTR* ppwszPortNameWithoutColon)
return ERROR_SUCCESS;
}
/**
* @name _IsNEPort
*
* Checks if the given port name is a virtual Ne port.
* A virtual Ne port may appear in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ports and can have the formats
* Ne00:, Ne01:, Ne-02:, Ne456:
* This check is extra picky to not cause false positives (like file name ports starting with "Ne").
*
* @param pwszPortName
* The port name to check.
*
* @return
* TRUE if this is definitely a virtual Ne port, FALSE if not.
*/
static __inline BOOL
_IsNEPort(PCWSTR pwszPortName)
{
PCWSTR p = pwszPortName;
// First character needs to be 'N' (uppercase or lowercase)
if (*p != L'N' && *p != L'n')
return FALSE;
// Next character needs to be 'E' (uppercase or lowercase)
p++;
if (*p != L'E' && *p != L'e')
return FALSE;
// An optional hyphen may follow now.
p++;
if (*p == L'-')
p++;
// Now an arbitrary number of digits may follow.
while (*p >= L'0' && *p <= L'9')
p++;
// Finally, the virtual Ne port must be terminated by a colon.
if (*p != ':')
return FALSE;
// If this is the end of the string, we have a virtual Ne port.
p++;
return (*p == L'\0');
}
DWORD
GetTypeFromName(LPCWSTR name)
{
HANDLE hfile;
if (!wcsncmp(name, L"LPT", ARRAYSIZE(L"LPT") - 1) )
return PORT_IS_LPT;
if (!wcsncmp(name, L"COM", ARRAYSIZE(L"COM") - 1) )
return PORT_IS_COM;
if (!lstrcmpW(name, L"FILE:") )
return PORT_IS_FILE;
// if (name[0] == '/')
// return PORT_IS_UNIXNAME;
// if (name[0] == '|')
// return PORT_IS_PIPE;
if ( _IsNEPort( name ) )
return PORT_IS_VNET;
if (!wcsncmp(name, L"XPS", ARRAYSIZE(L"XPS") - 1))
return PORT_IS_XPS;
/* Must be a file or a directory. Does the file exist ? */
hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
FIXME("%p for OPEN_EXISTING on %s\n", hfile, debugstr_w(name));
if (hfile == INVALID_HANDLE_VALUE)
{
/* Can we create the file? */
hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
FIXME("%p for OPEN_ALWAYS\n", hfile);
}
if (hfile != INVALID_HANDLE_VALUE)
{
CloseHandle(hfile); FIXME("PORT_IS_FILENAME %d\n",PORT_IS_FILENAME);
return PORT_IS_FILENAME;
}
FIXME("PORT_IS_UNKNOWN %d\n",PORT_IS_UNKNOWN);
/* We can't use the name. use GetLastError() for the reason */
return PORT_IS_UNKNOWN;
}

View file

@ -10,7 +10,77 @@
static DWORD
_HandleAddPort(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded)
{
return ERROR_CALL_NOT_IMPLEMENTED;
DWORD res, cbPortName;
HKEY hroot;
HKEY hToken = NULL;
PLOCALMON_PORT pPort;
PLOCALMON_HANDLE pLocalmon = pXcv->pLocalmon;
PWSTR PortName = (PWSTR)pInputData;
FIXME("LcmXcvAddPort : %s\n", debugstr_w( (LPWSTR) PortName ) );
if (!pLocalmon )
{
res = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
// This action can only happen at SERVER_ACCESS_ADMINISTER access level.
if (!(pXcv->GrantedAccess & SERVER_ACCESS_ADMINISTER))
{
res = ERROR_ACCESS_DENIED;
goto Cleanup;
}
// Switch to the SYSTEM context for modifying the registry.
hToken = RevertToPrinterSelf();
if (!hToken)
{
res = GetLastError();
ERR("RevertToPrinterSelf failed with error %lu!\n", res);
goto Cleanup;
}
res = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Ports", &hroot);
if (res == ERROR_SUCCESS)
{
if ( DoesPortExist( PortName ) )
{
RegCloseKey(hroot);
FIXME("=> %u\n", ERROR_ALREADY_EXISTS);
res = ERROR_ALREADY_EXISTS;
goto Cleanup;
}
cbPortName = (wcslen( PortName ) + 1) * sizeof(WCHAR);
// Create a new LOCALMON_PORT structure for it.
pPort = DllAllocSplMem(sizeof(LOCALMON_PORT) + cbPortName);
if (!pPort)
{
res = ERROR_NOT_ENOUGH_MEMORY;
RegCloseKey( hroot );
goto Cleanup;
}
memset( pPort, 0, sizeof(LOCALMON_PORT) + cbPortName );
pPort->hFile = INVALID_HANDLE_VALUE;
pPort->pLocalmon = pLocalmon;
pPort->pwszPortName = wcscpy( (PWSTR)(pPort+1), PortName );
// Insert it into the Registry list.
InsertTailList(&pLocalmon->RegistryPorts, &pPort->Entry);
res = RegSetValueExW(hroot, PortName, 0, REG_SZ, (const BYTE *) L"", sizeof(L""));
RegCloseKey(hroot);
}
FIXME("=> %u\n", res);
Cleanup:
if (hToken) ImpersonatePrinterClient(hToken);
SetLastError(res);
return res;
}
/**
@ -96,7 +166,79 @@ Cleanup:
static DWORD
_HandleDeletePort(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded)
{
return ERROR_CALL_NOT_IMPLEMENTED;
DWORD res;
HKEY hroot;
HKEY hToken = NULL;
PLOCALMON_HANDLE pLocalmon = pXcv->pLocalmon;
PLOCALMON_PORT pPort = NULL;
PLIST_ENTRY pEntry;
PWSTR pPortName = (PWSTR)pInputData;
FIXME("LcmXcvDeletePort : %s\n", debugstr_w( pPortName ) );
if (!pLocalmon )
{
res = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
// This action can only happen at SERVER_ACCESS_ADMINISTER access level.
if (!(pXcv->GrantedAccess & SERVER_ACCESS_ADMINISTER))
{
res = ERROR_ACCESS_DENIED;
goto Cleanup;
}
// Switch to the SYSTEM context for modifying the registry.
hToken = RevertToPrinterSelf();
if (!hToken)
{
res = GetLastError();
ERR("RevertToPrinterSelf failed with error %lu!\n", res);
goto Cleanup;
}
res = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Ports", &hroot);
if ( res == ERROR_SUCCESS )
{
res = RegDeleteValueW(hroot, pPortName );
RegCloseKey(hroot);
if ( res == ERROR_SUCCESS )
{
EnterCriticalSection(&pLocalmon->Section);
if (!IsListEmpty(&pLocalmon->RegistryPorts) )
{
for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink)
{
pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry);
if (wcscmp(pPort->pwszPortName, pPortName) == 0)
break;
}
}
LeaveCriticalSection(&pLocalmon->Section);
if ( pPort )
{
FIXME("LcmXcvDeletePort removed Port Entry\n");
EnterCriticalSection(&pPort->pLocalmon->Section);
RemoveEntryList(&pPort->Entry);
LeaveCriticalSection(&pPort->pLocalmon->Section);
DllFreeSplMem(pPort);
}
}
FIXME("LcmXcvDeletePort => %u with %u\n", res, GetLastError() );
}
Cleanup:
if (hToken) ImpersonatePrinterClient(hToken);
SetLastError(res);
return res;
}
/**
@ -202,7 +344,7 @@ _HandleMonitorUI(PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
const WCHAR wszMonitorUI[] = L"LocalUI.dll";
// Sanity checks
if (!pOutputData || !pcbOutputNeeded)
if (!pcbOutputNeeded)
return ERROR_INVALID_PARAMETER;
*pcbOutputNeeded = sizeof(wszMonitorUI);
@ -211,6 +353,9 @@ _HandleMonitorUI(PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
if (cbOutputData < *pcbOutputNeeded)
return ERROR_INSUFFICIENT_BUFFER;
if (!pOutputData)
return ERROR_INVALID_PARAMETER;
// Copy the string.
CopyMemory(pOutputData, wszMonitorUI, sizeof(wszMonitorUI));
return ERROR_SUCCESS;
@ -257,7 +402,21 @@ _HandlePortExists(PBYTE pInputData, PBYTE pOutputData, DWORD cbOutputData, PDWOR
static DWORD
_HandlePortIsValid(PBYTE pInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
{
return ERROR_CALL_NOT_IMPLEMENTED;
DWORD res;
TRACE("HandlePortIsValid : pInputData %s\n", debugstr_w( (LPWSTR) pInputData));
res = GetTypeFromName((LPCWSTR) pInputData);
TRACE("HandlePortIsValid : detected as %u\n", res);
/* names, that we have recognized, are valid */
if (res) return ERROR_SUCCESS;
TRACE("=> %u\n", GetLastError());
/* ERROR_ACCESS_DENIED, ERROR_PATH_NOT_FOUND or something else */
return GetLastError();
}
/**
@ -354,7 +513,9 @@ LocalmonXcvClosePort(HANDLE hXcv)
}
// Remove it from the list and free the memory.
LeaveCriticalSection(&pXcv->pLocalmon->Section);
RemoveEntryList(&pXcv->Entry);
LeaveCriticalSection(&pXcv->pLocalmon->Section);
DllFreeSplMem(pXcv);
SetLastError(ERROR_SUCCESS);
@ -364,7 +525,7 @@ LocalmonXcvClosePort(HANDLE hXcv)
DWORD WINAPI
LocalmonXcvDataPort(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
{
TRACE("LocalmonXcvDataPort(%p, %S, %p, %lu, %p, %lu, %p)\n", hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded);
FIXME("LocalmonXcvDataPort(%p, %S, %p, %lu, %p, %lu, %p)\n", hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded);
// Sanity checks
if (!pszDataName)

View file

@ -1,9 +1,12 @@
remove_definitions(-D_WIN32_WINNT=0x502)
add_definitions(-D_WIN32_WINNT=0x600)
spec2def(localspl.dll localspl.spec ADD_IMPORTLIB)
include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/skiplist)
list(APPEND SOURCE
forms.c
jobs.c
main.c
monitors.c
@ -15,7 +18,8 @@ list(APPEND SOURCE
printingthread.c
printprocessors.c
spoolfile.c
tools.c)
tools.c
xcv.c)
add_library(localspl MODULE
${SOURCE}
@ -25,6 +29,6 @@ add_library(localspl MODULE
set_module_type(localspl win32dll UNICODE)
target_link_libraries(localspl skiplist16 wine)
add_importlibs(localspl advapi32 netapi32 rpcrt4 secur32 spoolss msvcrt kernel32 ntdll)
add_importlibs(localspl user32 advapi32 advapi32_vista netapi32 rpcrt4 secur32 spoolss msvcrt kernel32 ntdll)
add_pch(localspl precomp.h SOURCE)
add_cd_file(TARGET localspl DESTINATION reactos/system32 FOR all)

View file

@ -0,0 +1,746 @@
/*
* PROJECT: ReactOS Spooler Router
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Functions for managing print Forms
* COPYRIGHT: Copyright 2020 ReactOS
*/
#include "precomp.h"
#define FORMINFOSIG '.2'
#define FORMMAXNAMESIZE CCHDEVICENAME-1
typedef struct _FORM_INFO_LIST
{
LIST_ENTRY List;
DWORD Sig;
DWORD Index;
FORM_INFO_2W;
} FORM_INFO_LIST, *PFORM_INFO_LIST;
LIST_ENTRY FormList;
static DWORD _dwLastForm;
// Local Constants
static DWORD dwFormInfo1Offsets[] = {
FIELD_OFFSET(FORM_INFO_1W, pName),
MAXDWORD
};
static DWORD dwFormInfo2Offsets[] = {
FIELD_OFFSET(FORM_INFO_2W, pName),
FIELD_OFFSET(FORM_INFO_2W, pKeyword),
FIELD_OFFSET(FORM_INFO_2W, pMuiDll),
FIELD_OFFSET(FORM_INFO_2W, pDisplayName),
MAXDWORD
};
// Built in Form names
WCHAR wszLetter[] = L"Letter";
WCHAR wszLetterSmall[] = L"Letter Small";
WCHAR wszTabloid[] = L"Tabloid";
WCHAR wszLedger[] = L"Ledger";
WCHAR wszLegal[] = L"Legal";
WCHAR wszStatement[] = L"Statement";
WCHAR wszExecutive[] = L"Executive";
WCHAR wszA3[] = L"A3";
WCHAR wszA4[] = L"A4";
WCHAR wszA4Small[] = L"A4 Small";
WCHAR wszA5[] = L"A5";
WCHAR wszB4JIS[] = L"B4 (JIS)";
WCHAR wszB5JIS[] = L"B5 (JIS)";
WCHAR wszFolio[] = L"Folio";
WCHAR wszQuarto[] = L"Quarto";
WCHAR wsz10x14[] = L"10 x 14";
WCHAR wsz11x17[] = L"11 x 17";
WCHAR wszNote[] = L"Note";
WCHAR wszEnvelope9[] = L"Envelope #9";
WCHAR wszEnvelope10[] = L"Envelope #10";
WCHAR wszEnvelope11[] = L"Envelope #11";
WCHAR wszEnvelope12[] = L"Envelope #12";
WCHAR wszEnvelope14[] = L"Envelope #14";
WCHAR wszCsizesheet[] = L"C size sheet";
WCHAR wszDsizesheet[] = L"D size sheet";
WCHAR wszEsizesheet[] = L"E size sheet";
WCHAR wszEnvelopeDL[] = L"Envelope DL";
WCHAR wszEnvelopeC5[] = L"Envelope C5";
WCHAR wszEnvelopeC3[] = L"Envelope C3";
WCHAR wszEnvelopeC4[] = L"Envelope C4";
WCHAR wszEnvelopeC6[] = L"Envelope C6";
WCHAR wszEnvelope65[] = L"Envelope 65";
WCHAR wszEnvelopeB4[] = L"Envelope B4";
WCHAR wszEnvelopeB5[] = L"Envelope B5";
WCHAR wszEnvelopeB6[] = L"Envelope B6";
WCHAR wszEnvelope[] = L"Envelope";
WCHAR wszEnvelopeMonarch[] = L"Envelope Monarch";
WCHAR wsz634Envelope[] = L"6 3/4 Envelope";
WCHAR wszUSStdFanfold[] = L"US Std Fanfold";
WCHAR wszGermanStdFanfold[] = L"German Std Fanfold";
WCHAR wszGermanLegalFanfold[] = L"German Legal Fanfold";
WCHAR wszB4ISO[] = L"B4 (ISO)";
WCHAR wszJapanesePostcard[] = L"Japanese Postcard";
WCHAR wsz9x11[] = L"9 x 11";
WCHAR wsz10x11[] = L"10 x 11";
WCHAR wsz15x11[] = L"15 x 11";
WCHAR wszEnvelopeInvite[] = L"Envelope Invite";
WCHAR wszReserved48[] = L"Reserved48";
WCHAR wszReserved49[] = L"Reserved49";
WCHAR wszLetterExtra[] = L"Letter Extra";
WCHAR wszLegalExtra[] = L"Legal Extra";
WCHAR wszTabloidExtra[] = L"Tabloid Extra";
WCHAR wszA4Extra[] = L"A4 Extra";
WCHAR wszLetterTransverse[] = L"Letter Transverse";
WCHAR wszA4Transverse[] = L"A4 Transverse";
WCHAR wszLetterExtraTransverse[] = L"Letter Extra Transverse";
WCHAR wszSuperA[] = L"Super A";
WCHAR wszSuperB[] = L"Super B";
WCHAR wszLetterPlus[] = L"Letter Plus";
WCHAR wszA4Plus[] = L"A4 Plus";
WCHAR wszA5Transverse[] = L"A5 Transverse";
WCHAR wszB5JISTransverse[] = L"B5 (JIS) Transverse";
WCHAR wszA3Extra[] = L"A3 Extra";
WCHAR wszA5Extra[] = L"A5 Extra";
WCHAR wszB5ISOExtra[] = L"B5 (ISO) Extra";
WCHAR wszA0[] = L"A0";
WCHAR wszA3Transverse[] = L"A3 Transverse";
WCHAR wszA3ExtraTransverse[] = L"A3 Extra Transverse";
WCHAR wszJapaneseDoublePostcard[] = L"Japanese Double Postcard";
WCHAR wszA1[] = L"A1";
WCHAR wszJapaneseEnvelopeKaku2[] = L"Japanese Envelope Kaku #2";
WCHAR wszJapaneseEnvelopeKaku3[] = L"Japanese Envelope Kaku #3";
WCHAR wszJapaneseEnvelopeChou3[] = L"Japanese Envelope Chou #3";
WCHAR wszJapaneseEnvelopeChou4[] = L"Japanese Envelope Chou #4";
WCHAR wszLetterRotated[] = L"Letter Rotated";
WCHAR wszA3Rotated[] = L"A3 Rotated";
WCHAR wszA4Rotated[] = L"A4 Rotated";
WCHAR wszA5Rotated[] = L"A5 Rotated";
WCHAR wszB4JISRotated[] = L"B4 (JIS) Rotated";
WCHAR wszB5JISRotated[] = L"B5 (JIS) Rotated";
WCHAR wszJapanesePostcardRotated[] = L"Japanese Postcard Rotated";
WCHAR wszDoubleJapanPostcardRotated[] = L"Double Japan Postcard Rotated";
WCHAR wsA6Rotatedz[] = L"A6 Rotated";
WCHAR wszJapanEnvelopeKaku2Rotated[] = L"Japan Envelope Kaku #2 Rotated";
WCHAR wszJapanEnvelopeKaku3Rotated[] = L"Japan Envelope Kaku #3 Rotated";
WCHAR wszJapanEnvelopeChou3Rotated[] = L"Japan Envelope Chou #3 Rotated";
WCHAR wszJapanEnvelopeChou4Rotated[] = L"Japan Envelope Chou #4 Rotated";
WCHAR wszB6JIS[] = L"B6 (JIS)";
WCHAR wszB6JISRotated[] = L"B6 (JIS) Rotated";
WCHAR wsz12x11[] = L"12 x 11";
WCHAR wszJapanEnvelopeYou4[] = L"Japan Envelope You #4";
WCHAR wszJapanEnvelopeYou4Rotated[] = L"Japan Envelope You #4 Rotated";
WCHAR wszPRC16K[] = L"PRC 16K";
WCHAR wszPRC32K[] = L"PRC 32K";
WCHAR wszPRC32KBig[] = L"PRC 32K(Big)";
WCHAR wszPRCEnvelope1[] = L"PRC Envelope #1";
WCHAR wszPRCEnvelope2[] = L"PRC Envelope #2";
WCHAR wszPRCEnvelope3[] = L"PRC Envelope #3";
WCHAR wszPRCEnvelope4[] = L"PRC Envelope #4";
WCHAR wszPRCEnvelope5[] = L"PRC Envelope #5";
WCHAR wszPRCEnvelope6[] = L"PRC Envelope #6";
WCHAR wszPRCEnvelope7[] = L"PRC Envelope #7";
WCHAR wszPRCEnvelope8[] = L"PRC Envelope #8";
WCHAR wszPRCEnvelope9[] = L"PRC Envelope #9";
WCHAR wszPRCEnvelope10[] = L"PRC Envelope #10";
WCHAR wszPRC16KRotated[] = L"PRC 16K Rotated";
WCHAR wszPRC32KRotated[] = L"PRC 32K Rotated";
WCHAR wszPRC32KBigRotated[] = L"PRC 32K(Big) Rotated";
WCHAR wszPRCEnvelope1Rotated[] = L"PRC Envelope #1 Rotated";
WCHAR wszPRCEnvelope2Rotated[] = L"PRC Envelope #2 Rotated";
WCHAR wszPRCEnvelope3Rotated[] = L"PRC Envelope #3 Rotated";
WCHAR wszPRCEnvelope4Rotated[] = L"PRC Envelope #4 Rotated";
WCHAR wszPRCEnvelope5Rotated[] = L"PRC Envelope #5 Rotated";
WCHAR wszPRCEnvelope6Rotated[] = L"PRC Envelope #6 Rotated";
WCHAR wszPRCEnvelope7Rotated[] = L"PRC Envelope #7 Rotated";
WCHAR wszPRCEnvelope8Rotated[] = L"PRC Envelope #8 Rotated";
WCHAR wszPRCEnvelope9Rotated[] = L"PRC Envelope #9 Rotated";
WCHAR wszPRCEnvelope10Rotated[] = L"PRC Envelope #10 Rotated";
// Built in Forms
FORM_INFO_1W BuiltInForms[] =
{
{ FORM_USER, wszLetter, {215900, 279400},{ 0, 0, 215900, 279400}},
{ FORM_USER, wszLetterSmall, {215900, 279400},{ 0, 0, 215900, 279400}},
{ FORM_USER, wszTabloid, {279400, 431800},{ 0, 0, 279400, 431800}},
{ FORM_USER, wszLedger, {431800, 279400},{ 0, 0, 431800, 279400}},
{ FORM_USER, wszLegal, {215900, 355600},{ 0, 0, 215900, 355600}},
{ FORM_USER, wszStatement, {139700, 215900},{ 0, 0, 139700, 215900}},
{ FORM_USER, wszExecutive, {184150, 266700},{ 0, 0, 184150, 266700}},
{ FORM_USER, wszA3, {297000, 420000},{ 0, 0, 297000, 420000}},
{ FORM_USER, wszA4, {210000, 297000},{ 0, 0, 210000, 297000}},
{ FORM_USER, wszA4Small, {210000, 297000},{ 0, 0, 210000, 297000}},
{ FORM_USER, wszA5, {148000, 210000},{ 0, 0, 148000, 210000}},
{ FORM_USER, wszB4JIS, {257000, 364000},{ 0, 0, 257000, 364000}},
{ FORM_USER, wszB5JIS, {182000, 257000},{ 0, 0, 182000, 257000}},
{ FORM_USER, wszFolio, {215900, 330200},{ 0, 0, 215900, 330200}},
{ FORM_USER, wszQuarto, {215000, 275000},{ 0, 0, 215000, 275000}},
{ FORM_USER, wsz10x14, {254000, 355600},{ 0, 0, 254000, 355600}},
{ FORM_USER, wsz11x17, {279400, 431800},{ 0, 0, 279400, 431800}},
{ FORM_USER, wszNote, {215900, 279400},{ 0, 0, 215900, 279400}},
{ FORM_USER, wszEnvelope9, { 98425, 225425},{ 0, 0, 98425, 225425}},
{ FORM_USER, wszEnvelope10, {104775, 241300},{ 0, 0, 104775, 241300}},
{ FORM_USER, wszEnvelope11, {114300, 263525},{ 0, 0, 114300, 263525}},
{ FORM_USER, wszEnvelope12, {120650, 279400},{ 0, 0, 120650, 279400}},
{ FORM_USER, wszEnvelope14, {127000, 292100},{ 0, 0, 127000, 292100}},
{ FORM_USER, wszCsizesheet, {431800, 558800},{ 0, 0, 431800, 558800}},
{ FORM_USER, wszDsizesheet, {558800, 863600},{ 0, 0, 558800, 863600}},
{ FORM_USER, wszEsizesheet, {863600,1117600},{ 0, 0, 863600,1117600}},
{ FORM_USER, wszEnvelopeDL, {110000, 220000},{ 0, 0, 110000, 220000}},
{ FORM_USER, wszEnvelopeC5, {162000, 229000},{ 0, 0, 162000, 229000}},
{ FORM_USER, wszEnvelopeC3, {324000, 458000},{ 0, 0, 324000, 458000}},
{ FORM_USER, wszEnvelopeC4, {229000, 324000},{ 0, 0, 229000, 324000}},
{ FORM_USER, wszEnvelopeC6, {114000, 162000},{ 0, 0, 114000, 162000}},
{ FORM_USER, wszEnvelope65, {114000, 229000},{ 0, 0, 114000, 229000}},
{ FORM_USER, wszEnvelopeB4, {250000, 353000},{ 0, 0, 250000, 353000}},
{ FORM_USER, wszEnvelopeB5, {176000, 250000},{ 0, 0, 176000, 250000}},
{ FORM_USER, wszEnvelopeB6, {176000, 125000},{ 0, 0, 176000, 125000}},
{ FORM_USER, wszEnvelope, {110000, 230000},{ 0, 0, 110000, 230000}},
{ FORM_USER, wszEnvelopeMonarch, { 98425, 190500},{ 0, 0, 98425, 190500}},
{ FORM_USER, wsz634Envelope, { 92075, 165100},{ 0, 0, 92075, 165100}},
{ FORM_USER, wszUSStdFanfold, {377825, 279400},{ 0, 0, 377825, 279400}},
{ FORM_USER, wszGermanStdFanfold, {215900, 304800},{ 0, 0, 215900, 304800}},
{ FORM_USER, wszGermanLegalFanfold, {215900, 330200},{ 0, 0, 215900, 330200}},
// add more, I'm lazy
{ FORM_USER, wszDoubleJapanPostcardRotated,{148000, 200000},{ 0, 0, 148000, 200000}},
//
{ FORM_USER, wszPRCEnvelope10Rotated, {458000, 324009},{ 0, 0, 458000, 324009}},
{ FORM_USER, 0, { 0, 0},{ 0, 0, 0, 0}}
};
//
// Form information Registry entry stucture, in correct format.
//
// Example : 11 x 17 REG_BINARY 68 43 04 00 b8 96 06 00 00 00 00 00 00 00 00 00 68 43 04 00 b8 96 06 00 01 00 00 00 02 00 00 00
// [ Size | ImageableArea | Index 1 + | Flags ] , is FORM_PRINTER.
//
typedef struct _REGISTRYFORMINFO
{
SIZEL Size;
RECTL ImageableArea;
DWORD Index;
DWORD Flags;
} REGISTRYFORMINFO, *PREGISTRYFORMINFO;
HKEY hFormCKey = NULL;
HKEY hFormsKey = NULL;
BOOL
InitializeFormList(VOID)
{
DWORD dwErrorCode;
PFORM_INFO_LIST pfil;
REGISTRYFORMINFO rfi;
FIXME("InitializeFormList\n");
dwErrorCode = (DWORD)RegCreateKeyExW( HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Control\\Print\\Forms",
0,
NULL,
REG_OPTION_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hFormCKey,
NULL ); // KEY_OPENED_EXISTING_KEY );
if ( dwErrorCode != ERROR_SUCCESS && dwErrorCode != ERROR_ALREADY_EXISTS )
{
ERR("RegCreateKeyExW failed for the Forms with error %lu!\n", dwErrorCode);
goto Cleanup;
}
// Open some registry keys and leave them open. We need them multiple times throughout the Local Spooler.
dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Print\\Forms", 0, KEY_ALL_ACCESS, &hFormsKey);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RegOpenKeyExW failed for \"Forms\" with error %lu!\n", dwErrorCode);
goto Cleanup;
}
_dwLastForm = 1;
InitializeListHead(&FormList);
{
int i = 0, Size;
while ( BuiltInForms[ i ].pName != NULL )
{
TRACE("InitializeFormList L s %S\n",BuiltInForms[ i ].pName );
Size = sizeof(FORM_INFO_LIST) + ((wcslen(BuiltInForms[ i ].pName) + 1) * sizeof(WCHAR));
pfil = DllAllocSplMem( Size );
pfil->pName = wcscpy( (PWSTR)(pfil+1), BuiltInForms[ i ].pName );
pfil->Flags = BuiltInForms[ i ].Flags;
pfil->Size = BuiltInForms[ i ].Size;
pfil->ImageableArea = BuiltInForms[ i ].ImageableArea;
pfil->Sig = FORMINFOSIG;
pfil->Index = _dwLastForm++;
pfil->pKeyword = NULL;
pfil->StringType = STRING_NONE;
pfil->pMuiDll = NULL;
pfil->dwResourceId = 0;
pfil->pDisplayName = NULL;
pfil->wLangId = 0;
InsertTailList( &FormList, &pfil->List );
rfi.Size = pfil->Size;
rfi.ImageableArea = pfil->ImageableArea;
rfi.Index = pfil->Index;
rfi.Flags = pfil->Flags;
dwErrorCode = RegSetValueExW( hFormsKey, pfil->pName, 0, REG_BINARY, (PBYTE)&rfi, sizeof( rfi ) );
if ( dwErrorCode == ERROR_SUCCESS )
{
TRACE("Init : RQVEW : %S added\n",pfil->pName);
}
i++;
}
}
Cleanup:
return TRUE;
}
PFORM_INFO_LIST
FASTCALL
FindForm( WCHAR * pFormName, WCHAR * pKeyword )
{
PLIST_ENTRY ListEntry;
PFORM_INFO_LIST pfil;
ListEntry = FormList.Flink;
while (ListEntry != &FormList)
{
pfil = CONTAINING_RECORD(ListEntry, FORM_INFO_LIST, List);
ListEntry = ListEntry->Flink;
if ( pFormName && !_wcsicmp( pfil->pName, pFormName ) )
return pfil;
if ( pKeyword && !_wcsicmp( (WCHAR*)pfil->pKeyword, pKeyword ) )
return pfil;
}
return NULL;
}
static void
_LocalGetFormLevel1(PFORM_INFO_LIST pfil, PFORM_INFO_1W* ppFormInfo, PBYTE* ppFormInfoEnd, PDWORD pcbNeeded)
{
DWORD n;
PCWSTR pwszStrings[1];
pwszStrings[0] = pfil->pName;
// Calculate the string lengths.
if (!ppFormInfo)
{
for (n = 0; n < _countof(pwszStrings); ++n)
{
*pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
}
*pcbNeeded += sizeof(FORM_INFO_1W);
return;
}
(*ppFormInfo)->Flags = pfil->Flags;
(*ppFormInfo)->Size = pfil->Size;
(*ppFormInfo)->ImageableArea = pfil->ImageableArea;
// Finally copy the structure and advance to the next one in the output buffer.
*ppFormInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppFormInfo), dwFormInfo1Offsets, *ppFormInfoEnd);
(*ppFormInfo)++;
}
static void
_LocalGetFormLevel2(PFORM_INFO_LIST pfil, PFORM_INFO_2W* ppFormInfo, PBYTE* ppFormInfoEnd, PDWORD pcbNeeded)
{
DWORD n;
PCWSTR pwszStrings[4];
pwszStrings[0] = pfil->pName;
pwszStrings[1] = (PCWSTR)pfil->pKeyword;
pwszStrings[2] = pfil->pMuiDll;
pwszStrings[3] = pfil->pDisplayName;
// Calculate the string lengths.
if (!ppFormInfo)
{
for (n = 0; n < _countof(pwszStrings); ++n)
{
if (pwszStrings[n])
{
*pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
}
}
*pcbNeeded += sizeof(FORM_INFO_2W);
return;
}
(*ppFormInfo)->Flags = pfil->Flags;
(*ppFormInfo)->Size = pfil->Size;
(*ppFormInfo)->ImageableArea = pfil->ImageableArea;
(*ppFormInfo)->StringType = pfil->StringType; //// If caller is remote, set STRING_LANGPAIR always;
(*ppFormInfo)->dwResourceId = pfil->dwResourceId;
// Finally copy the structure and advance to the next one in the output buffer.
*ppFormInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppFormInfo), dwFormInfo2Offsets, *ppFormInfoEnd);
(*ppFormInfo)++;
}
typedef void (*PLocalGetFormLevelFunc)(PFORM_INFO_LIST, PVOID, PBYTE*, PDWORD);
static const PLocalGetFormLevelFunc pfnGetFormLevels[] = {
NULL,
(PLocalGetFormLevelFunc)&_LocalGetFormLevel1,
(PLocalGetFormLevelFunc)&_LocalGetFormLevel2
};
//
// API Functions
//
BOOL WINAPI
LocalAddForm(HANDLE hPrinter, DWORD Level, PBYTE pForm)
{
DWORD dwErrorCode, Size, cbNeeded;
PFORM_INFO_LIST pfil;
PLOCAL_HANDLE pHandle;
REGISTRYFORMINFO rfi;
PFORM_INFO_1W pfi1w = (PFORM_INFO_1W)pForm;
PFORM_INFO_2W pfi2w = (PFORM_INFO_2W)pForm;
FIXME("AddForm(%p, %lu, %p)\n", hPrinter, Level, pForm);
// Check if this is a printer handle.
pHandle = (PLOCAL_HANDLE)hPrinter;
if (pHandle->HandleType != HandleType_Printer)
{
dwErrorCode = ERROR_INVALID_HANDLE;
goto Cleanup;
}
// Only support 1 & 2
if (Level < 1 || Level > 2)
{
// The caller supplied an invalid level.
dwErrorCode = ERROR_INVALID_LEVEL;
goto Cleanup;
}
pfil = FindForm( pfi1w->pName, NULL );
if ( pfil )
{
dwErrorCode = ERROR_FILE_EXISTS;
goto Cleanup;
}
dwErrorCode = RegQueryValueExW( hFormsKey, pfi1w->pName, NULL, NULL, NULL, &cbNeeded );
if ( dwErrorCode == ERROR_SUCCESS )
{
dwErrorCode = ERROR_FILE_EXISTS;
goto Cleanup;
}
if ( wcslen(pfi1w->pName) > FORMMAXNAMESIZE ) // Limit REG Name size.
{
dwErrorCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
Size = sizeof(FORM_INFO_LIST) + ((MAX_PATH + 1) * sizeof(WCHAR));
pfil = DllAllocSplMem( Size );
if ( !pfil )
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
pfil->Sig = FORMINFOSIG;
pfil->Index = _dwLastForm++;
pfil->pName = wcscpy( (PWSTR)(pfil+1), pfi1w->pName );
pfil->Flags = pfi1w->Flags;
pfil->Size = pfi1w->Size;
pfil->ImageableArea = pfi1w->ImageableArea;
pfil->StringType = STRING_NONE;
if ( Level > 1 )
{
pfil->pKeyword = pfi2w->pKeyword;
pfil->pMuiDll = pfi2w->pMuiDll;
pfil->pDisplayName = pfi2w->pDisplayName;
pfil->StringType = pfi2w->StringType;
pfil->dwResourceId = pfi2w->dwResourceId;
}
rfi.Size = pfil->Size;
rfi.ImageableArea = pfil->ImageableArea;
rfi.Index = pfil->Index;
rfi.Flags = pfil->Flags;
dwErrorCode = RegSetValueExW( hFormsKey, pfil->pName, 0, REG_BINARY, (PBYTE)&rfi, sizeof( rfi ) );
BroadcastChange(pHandle);
InsertTailList( &FormList, &pfil->List );
Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
LocalDeleteForm(HANDLE hPrinter, PWSTR pFormName)
{
DWORD dwErrorCode, cbNeeded;
PFORM_INFO_LIST pfil;
REGISTRYFORMINFO rfi;
PLOCAL_HANDLE pHandle;
FIXME("DeleteForm(%p, %S)\n", hPrinter, pFormName);
// Check if this is a printer handle.
pHandle = (PLOCAL_HANDLE)hPrinter;
if (pHandle->HandleType != HandleType_Printer)
{
dwErrorCode = ERROR_INVALID_HANDLE;
goto Cleanup;
}
pfil = FindForm( pFormName, NULL );
if ( !pfil )
{
dwErrorCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
dwErrorCode = RegQueryValueExW( hFormsKey, pFormName, NULL, NULL, (PBYTE)&rfi, &cbNeeded );
if ( dwErrorCode != ERROR_SUCCESS )
{
goto Cleanup;
}
dwErrorCode = RegDeleteValueW(hFormsKey, pFormName);
if ( dwErrorCode != ERROR_SUCCESS )
{
goto Cleanup;
}
RemoveEntryList(&pfil->List);
DllFreeSplMem(pfil);
BroadcastChange(pHandle);
dwErrorCode = ERROR_SUCCESS;
Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
LocalEnumForms(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
DWORD dwErrorCode;
PFORM_INFO_LIST pfil = NULL;
PBYTE pEnd = &pForm[cbBuf];
PLOCAL_HANDLE pHandle;
PLIST_ENTRY ListEntry;
FIXME("EnumForms(%p, %lu, %p, %lu, %p, %p)\n", hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned);
// Check if this is a printer handle.
pHandle = (PLOCAL_HANDLE)hPrinter;
if (pHandle->HandleType != HandleType_Printer)
{
dwErrorCode = ERROR_INVALID_HANDLE;
goto Cleanup;
}
// Only support 1 & 2
if (Level < 1 || Level > 2)
{
// The caller supplied an invalid level.
dwErrorCode = ERROR_INVALID_LEVEL;
goto Cleanup;
}
// Count the required buffer size.
*pcbNeeded = 0;
ListEntry = FormList.Flink;
if (IsListEmpty(ListEntry))
{
dwErrorCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
while ( ListEntry != &FormList )
{
pfil = CONTAINING_RECORD(ListEntry, FORM_INFO_LIST, List);
ListEntry = ListEntry->Flink;
pfnGetFormLevels[Level](pfil, NULL, NULL, pcbNeeded);
}
// Check if the supplied buffer is large enough.
if (cbBuf < *pcbNeeded)
{
ERR("Insuffisient Buffer size\n");
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
// Copy over the information.
pEnd = &pForm[*pcbNeeded];
ListEntry = FormList.Flink;
while ( ListEntry != &FormList )
{
pfil = CONTAINING_RECORD(ListEntry, FORM_INFO_LIST, List);
ListEntry = ListEntry->Flink;
pfnGetFormLevels[Level](pfil, &pForm, &pEnd, NULL);
(*pcReturned)++;
}
dwErrorCode = ERROR_SUCCESS;
Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
LocalGetForm(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded)
{
DWORD dwErrorCode;
PFORM_INFO_LIST pfil;
PBYTE pEnd = &pForm[cbBuf];
PLOCAL_HANDLE pHandle;
FIXME("GetForm(%p, %S, %lu, %p, %lu, %p)\n", hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded);
// Check if this is a printer handle.
pHandle = (PLOCAL_HANDLE)hPrinter;
if (pHandle->HandleType != HandleType_Printer)
{
dwErrorCode = ERROR_INVALID_HANDLE;
goto Cleanup;
}
// Only support 1 & 2
if (Level < 1 || Level > 2)
{
// The caller supplied an invalid level.
dwErrorCode = ERROR_INVALID_LEVEL;
goto Cleanup;
}
pfil = FindForm( pFormName, NULL );
if ( !pfil )
{
dwErrorCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
// Count the required buffer size.
*pcbNeeded = 0;
pfnGetFormLevels[Level](pfil, NULL, NULL, pcbNeeded);
// Check if the supplied buffer is large enough.
if (cbBuf < *pcbNeeded)
{
ERR("Insuffisient Buffer size\n");
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
// Copy over the information.
pEnd = &pForm[*pcbNeeded];
pfnGetFormLevels[Level](pfil, &pForm, &pEnd, NULL);
dwErrorCode = ERROR_SUCCESS;
Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
localSetForm(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm)
{
DWORD dwErrorCode, cbNeeded;
PFORM_INFO_LIST pfil;
REGISTRYFORMINFO rfi;
PLOCAL_HANDLE pHandle;
PFORM_INFO_1W pfi1w = (PFORM_INFO_1W)pForm;
PFORM_INFO_2W pfi2w = (PFORM_INFO_2W)pForm;
FIXME("SetFormW(%p, %S, %lu, %p)\n", hPrinter, pFormName, Level, pForm);
// Check if this is a printer handle.
pHandle = (PLOCAL_HANDLE)hPrinter;
if (pHandle->HandleType != HandleType_Printer)
{
dwErrorCode = ERROR_INVALID_HANDLE;
goto Cleanup;
}
// Only support 1 & 2
if (Level < 1 || Level > 2)
{
// The caller supplied an invalid level.
dwErrorCode = ERROR_INVALID_LEVEL;
goto Cleanup;
}
pfil = FindForm( pFormName, NULL );
if ( !pfil )
{
dwErrorCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
dwErrorCode = RegQueryValueExW( hFormsKey, pFormName, NULL, NULL, (PBYTE)&rfi, &cbNeeded) ;
if ( dwErrorCode != ERROR_SUCCESS )
{
goto Cleanup;
}
pfil->Flags = pfi1w->Flags;
pfil->Size = pfi1w->Size;
pfil->ImageableArea = pfi1w->ImageableArea;
if ( Level > 1 )
{
pfil->pKeyword = pfi2w->pKeyword;
pfil->pMuiDll = pfi2w->pMuiDll;
pfil->pDisplayName = pfi2w->pDisplayName;
pfil->StringType = pfi2w->StringType;
pfil->dwResourceId = pfi2w->dwResourceId;
}
rfi.Size = pfil->Size;
rfi.ImageableArea = pfil->ImageableArea;
rfi.Flags = pfil->Flags;
dwErrorCode = RegSetValueExW( hFormsKey, pfil->pName, 0, REG_BINARY, (PBYTE)&rfi, sizeof( rfi ) );
BroadcastChange(pHandle);
Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}

View file

@ -25,9 +25,9 @@ const DWORD dwSpoolerMinorVersion = 0;
const WCHAR wszDefaultDocumentName[] = L"Local Downlevel Document";
PCWSTR wszPrintProviderInfo[3] = {
L"Windows NT Local Printers", // Description
L"Windows NT Local Print Providor", // Name
L"Locally connected Printers", // Comment
L"Windows NT Local Printers" // Description
L"Locally connected Printers" // Comment
};
// Local Constants
@ -41,10 +41,10 @@ static const PRINTPROVIDOR _PrintProviderFunctions = {
NULL, // fpSetPrinter
LocalGetPrinter, // fpGetPrinter
LocalEnumPrinters, // fpEnumPrinters
NULL, // fpAddPrinterDriver
NULL, // fpEnumPrinterDrivers
LocalAddPrinterDriver, // fpAddPrinterDriver
LocalEnumPrinterDrivers, // fpEnumPrinterDrivers
LocalGetPrinterDriver, // fpGetPrinterDriver
NULL, // fpGetPrinterDriverDirectory
LocalGetPrinterDriverDirectory, // fpGetPrinterDriverDirectory
NULL, // fpDeletePrinterDriver
NULL, // fpAddPrintProcessor
LocalEnumPrintProcessors, // fpEnumPrintProcessors
@ -64,34 +64,34 @@ static const PRINTPROVIDOR _PrintProviderFunctions = {
LocalSetPrinterData, // fpSetPrinterData
NULL, // fpWaitForPrinterChange
LocalClosePrinter, // fpClosePrinter
NULL, // fpAddForm
NULL, // fpDeleteForm
NULL, // fpGetForm
NULL, // fpSetForm
NULL, // fpEnumForms
LocalAddForm, // fpAddForm
LocalDeleteForm, // fpDeleteForm
LocalGetForm, // fpGetForm
localSetForm, // fpSetForm
LocalEnumForms, // fpEnumForms
LocalEnumMonitors, // fpEnumMonitors
LocalEnumPorts, // fpEnumPorts
NULL, // fpAddPort
NULL, // fpConfigurePort
NULL, // fpDeletePort
LocalAddPort, // fpAddPort
LocalConfigurePort, // fpConfigurePort
LocalDeletePort, // fpDeletePort
NULL, // fpCreatePrinterIC
NULL, // fpPlayGdiScriptOnPrinterIC
NULL, // fpDeletePrinterIC
NULL, // fpAddPrinterConnection
NULL, // fpDeletePrinterConnection
NULL, // fpPrinterMessageBox
NULL, // fpAddMonitor
NULL, // fpDeleteMonitor
LocalPrinterMessageBox, // fpPrinterMessageBox
LocalAddMonitor, // fpAddMonitor
LocalDeleteMonitor, // fpDeleteMonitor
NULL, // fpResetPrinter
NULL, // fpGetPrinterDriverEx
LocalGetPrinterDriverEx, // fpGetPrinterDriverEx
NULL, // fpFindFirstPrinterChangeNotification
NULL, // fpFindClosePrinterChangeNotification
NULL, // fpAddPortEx
LocalAddPortEx, // fpAddPortEx
NULL, // fpShutDown
NULL, // fpRefreshPrinterChangeNotification
NULL, // fpOpenPrinterEx
NULL, // fpAddPrinterEx
NULL, // fpSetPort
LocalSetPort, // fpSetPort
NULL, // fpEnumPrinterData
NULL, // fpDeletePrinterData
NULL, // fpClusterSplOpen
@ -108,8 +108,8 @@ static const PRINTPROVIDOR _PrintProviderFunctions = {
NULL, // fpAddPerMachineConnection
NULL, // fpDeletePerMachineConnection
NULL, // fpEnumPerMachineConnections
NULL, // fpXcvData
NULL, // fpAddPrinterDriverEx
LocalXcvData, // fpXcvData
LocalAddPrinterDriverEx, // fpAddPrinterDriverEx
NULL, // fpSplReadPrinter
NULL, // fpDriverUnloadComplete
LocalGetSpoolFileInfo, // fpGetSpoolFileInfo
@ -218,6 +218,12 @@ _InitializeLocalSpooler(void)
if (!InitializeGlobalJobList())
goto Cleanup;
if (!InitializeFormList())
goto Cleanup;
if (!InitializePrinterDrivers())
goto Cleanup;
// Local Spooler Initialization finished successfully!
bReturnValue = TRUE;

View file

@ -46,6 +46,82 @@ FindPrintMonitor(PCWSTR pwszName)
return NULL;
}
static LONG WINAPI CreateKey(HANDLE hcKey, LPCWSTR pszSubKey, DWORD dwOptions, REGSAM samDesired, PSECURITY_ATTRIBUTES pSecurityAttributes, PHANDLE phckResult, PDWORD pdwDisposition, HANDLE hSpooler)
{
FIXME("stub\n");
return ERROR_CALL_NOT_IMPLEMENTED;
}
static LONG WINAPI OpenKey(HANDLE hcKey, LPCWSTR pszSubKey, REGSAM samDesired, PHANDLE phkResult, HANDLE hSpooler)
{
FIXME("stub\n");
return ERROR_CALL_NOT_IMPLEMENTED;
}
static LONG WINAPI CloseKey(HANDLE hcKey, HANDLE hSpooler)
{
FIXME("stub\n");
return ERROR_CALL_NOT_IMPLEMENTED;
}
static LONG WINAPI DeleteKey(HANDLE hcKey, LPCWSTR pszSubKey, HANDLE hSpooler)
{
FIXME("stub\n");
return ERROR_CALL_NOT_IMPLEMENTED;
}
static LONG WINAPI EnumKey(HANDLE hcKey, DWORD dwIndex, LPWSTR pszName, PDWORD pcchName, PFILETIME pftLastWriteTime, HANDLE hSpooler)
{
FIXME("stub\n");
return ERROR_CALL_NOT_IMPLEMENTED;
}
static LONG WINAPI QueryInfoKey(HANDLE hcKey, PDWORD pcSubKeys, PDWORD pcbKey, PDWORD pcValues, PDWORD pcbValue, PDWORD pcbData, PDWORD pcbSecurityDescriptor, PFILETIME pftLastWriteTime,
HANDLE hSpooler)
{
FIXME("stub\n");
return ERROR_CALL_NOT_IMPLEMENTED;
}
static LONG WINAPI SetValue(HANDLE hcKey, LPCWSTR pszValue, DWORD dwType, const BYTE* pData, DWORD cbData, HANDLE hSpooler)
{
FIXME("stub\n");
return ERROR_CALL_NOT_IMPLEMENTED;
}
static LONG WINAPI DeleteValue(HANDLE hcKey, LPCWSTR pszValue, HANDLE hSpooler)
{
FIXME("stub\n");
return ERROR_CALL_NOT_IMPLEMENTED;
}
static LONG WINAPI EnumValue(HANDLE hcKey, DWORD dwIndex, LPWSTR pszValue, PDWORD pcbValue, PDWORD pType, PBYTE pData, PDWORD pcbData, HANDLE hSpooler)
{
FIXME("stub\n");
return ERROR_CALL_NOT_IMPLEMENTED;
}
static LONG WINAPI QueryValue(HANDLE hcKey, LPCWSTR pszValue, PDWORD pType, PBYTE pData, PDWORD pcbData, HANDLE hSpooler)
{
FIXME("stub\n");
return ERROR_CALL_NOT_IMPLEMENTED;
}
static MONITORREG MonReg =
{
sizeof(MONITORREG),
CreateKey,
OpenKey,
CloseKey,
DeleteKey,
EnumKey,
QueryInfoKey,
SetValue,
DeleteValue,
EnumValue,
QueryValue
};
BOOL
InitializePrintMonitorList(void)
{
@ -124,6 +200,8 @@ InitializePrintMonitorList(void)
goto Cleanup;
}
memset( pPrintMonitor, 0, sizeof(LOCAL_PRINT_MONITOR));
// Allocate memory for the Print Monitor Name.
pPrintMonitor->pwszName = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR));
if (!pPrintMonitor->pwszName)
@ -163,6 +241,8 @@ InitializePrintMonitorList(void)
continue;
}
pPrintMonitor->hModule = hinstPrintMonitor;
// Try to find a Level 2 initialization routine first.
pfnInitializePrintMonitor2 = (PInitializePrintMonitor2)GetProcAddress(hinstPrintMonitor, "InitializePrintMonitor2");
if (pfnInitializePrintMonitor2)
@ -172,6 +252,8 @@ InitializePrintMonitorList(void)
MonitorInit.bLocal = TRUE;
// TODO: Fill the other fields.
MonitorInit.hckRegistryRoot = hKey;
MonitorInit.pMonitorReg = &MonReg;
// Call the Level 2 initialization routine.
pPrintMonitor->pMonitor = (PMONITOR2)pfnInitializePrintMonitor2(&MonitorInit, &pPrintMonitor->hMonitor);
@ -180,7 +262,7 @@ InitializePrintMonitorList(void)
ERR("InitializePrintMonitor2 failed for \"%S\" with error %lu!\n", pPrintMonitor->pwszFileName, GetLastError());
continue;
}
FIXME("InitializePrintMonitor2 loaded.\n");
pPrintMonitor->bIsLevel2 = TRUE;
}
else
@ -219,6 +301,8 @@ InitializePrintMonitorList(void)
// Add this Print Monitor to the list.
InsertTailList(&PrintMonitorList, &pPrintMonitor->Entry);
FIXME("InitializePrintMonitorList Handle %p\n",pPrintMonitor->hMonitor);
pPrintMonitor->refcount++;
// Don't let the cleanup routine free this.
pPrintMonitor = NULL;
@ -253,6 +337,7 @@ Cleanup:
return (dwErrorCode == ERROR_SUCCESS);
}
static void
_LocalGetMonitorLevel1(PLOCAL_PRINT_MONITOR pPrintMonitor, PMONITOR_INFO_1W* ppMonitorInfo, PBYTE* ppMonitorInfoEnd, PDWORD pcbNeeded)
{
@ -367,3 +452,354 @@ Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL
AddPrintMonitorList( LPCWSTR pName, LPWSTR DllName )
{
const WCHAR wszMonitorsPath[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors\\";
const DWORD cchMonitorsPath = _countof(wszMonitorsPath) - 1;
WCHAR wszRegRoot[MAX_PATH] = {0};
DWORD cchPrintMonitorName;
DWORD dwErrorCode;
HINSTANCE hinstPrintMonitor = NULL;
HKEY hKey = NULL;
MONITORINIT MonitorInit;
PInitializePrintMonitor pfnInitializePrintMonitor;
PInitializePrintMonitor2 pfnInitializePrintMonitor2;
PLOCAL_PRINT_MONITOR pPrintMonitor = NULL;
PWSTR pwszRegistryPath = NULL;
FIXME("AddPrintMonitorList( %S, %S)\n",pName, DllName);
StringCbCopyW(wszRegRoot, sizeof(wszRegRoot), wszMonitorsPath);
StringCbCatW(wszRegRoot, sizeof(wszRegRoot), pName);
// Open the key containing Print Monitors.
dwErrorCode = (DWORD)RegOpenKeyW( HKEY_LOCAL_MACHINE, wszRegRoot, &hKey );
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RegOpenKeyExW %S failed with status %lu!\n", wszRegRoot, dwErrorCode);
goto Cleanup;
}
// Create a new LOCAL_PRINT_MONITOR structure for it.
pPrintMonitor = DllAllocSplMem(sizeof(LOCAL_PRINT_MONITOR));
if (!pPrintMonitor)
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("DllAllocSplMem failed!\n");
goto Cleanup;
}
memset( pPrintMonitor, 0, sizeof(LOCAL_PRINT_MONITOR));
// Allocate memory for the Print Monitor Name.
pPrintMonitor->pwszName = AllocSplStr( pName );
if (!pPrintMonitor->pwszName)
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("DllAllocSplMem failed!\n");
goto Cleanup;
}
cchPrintMonitorName = wcslen(pPrintMonitor->pwszName);
if ( DllName == NULL )
{
DWORD namesize;
dwErrorCode = RegQueryValueExW( hKey, L"Driver", NULL, NULL, NULL, &namesize );
if ( dwErrorCode == ERROR_SUCCESS )
{
DllName = DllAllocSplMem(namesize);
RegQueryValueExW( hKey, L"Driver", NULL, NULL, (LPBYTE)DllName, &namesize );
pPrintMonitor->pwszFileName = DllName;
}
else
{
ERR("DllName not found\n");
goto Cleanup;
}
}
else
{
pPrintMonitor->pwszFileName = AllocSplStr( DllName );
}
// Try to load it.
hinstPrintMonitor = LoadLibraryW(pPrintMonitor->pwszFileName);
if (!hinstPrintMonitor)
{
ERR("LoadLibraryW failed for \"%S\" with error %lu!\n", pPrintMonitor->pwszFileName, GetLastError());
dwErrorCode = GetLastError();
goto Cleanup;
}
pPrintMonitor->hModule = hinstPrintMonitor;
// Try to find a Level 2 initialization routine first.
pfnInitializePrintMonitor2 = (PInitializePrintMonitor2)GetProcAddress(hinstPrintMonitor, "InitializePrintMonitor2");
if (pfnInitializePrintMonitor2)
{
// Prepare a MONITORINIT structure.
MonitorInit.cbSize = sizeof(MONITORINIT);
MonitorInit.bLocal = TRUE;
// TODO: Fill the other fields.
MonitorInit.hckRegistryRoot = hKey;
MonitorInit.pMonitorReg = &MonReg;
// Call the Level 2 initialization routine.
pPrintMonitor->pMonitor = (PMONITOR2)pfnInitializePrintMonitor2(&MonitorInit, &pPrintMonitor->hMonitor);
if (!pPrintMonitor->pMonitor)
{
ERR("InitializePrintMonitor2 failed for \"%S\" with error %lu!\n", pPrintMonitor->pwszFileName, GetLastError());
goto Cleanup;
}
pPrintMonitor->bIsLevel2 = TRUE;
}
else
{
// Try to find a Level 1 initialization routine then.
pfnInitializePrintMonitor = (PInitializePrintMonitor)GetProcAddress(hinstPrintMonitor, "InitializePrintMonitor");
if (pfnInitializePrintMonitor)
{
// Construct the registry path.
pwszRegistryPath = DllAllocSplMem((cchMonitorsPath + 1 + cchPrintMonitorName + 1) * sizeof(WCHAR));
if (!pwszRegistryPath)
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("DllAllocSplMem failed!\n");
goto Cleanup;
}
CopyMemory(pwszRegistryPath, wszMonitorsPath, cchMonitorsPath * sizeof(WCHAR));
pwszRegistryPath[cchMonitorsPath] = L'\\';
CopyMemory(&pwszRegistryPath[cchMonitorsPath + 1], pPrintMonitor->pwszName, (cchPrintMonitorName + 1) * sizeof(WCHAR));
// Call the Level 1 initialization routine.
pPrintMonitor->pMonitor = (LPMONITOREX)pfnInitializePrintMonitor(pwszRegistryPath);
if (!pPrintMonitor->pMonitor)
{
ERR("InitializePrintMonitor failed for \"%S\" with error %lu!\n", pPrintMonitor->pwszFileName, GetLastError());
goto Cleanup;
}
}
else
{
ERR("No initialization routine found for \"%S\"!\n", pPrintMonitor->pwszFileName);
dwErrorCode = ERROR_PROC_NOT_FOUND;
goto Cleanup;
}
}
// Add this Print Monitor to the list.
InsertTailList(&PrintMonitorList, &pPrintMonitor->Entry);
FIXME("AddPrintMonitorList Handle %p\n",pPrintMonitor->hMonitor);
pPrintMonitor->refcount++;
// Don't let the cleanup routine free this.
pPrintMonitor = NULL;
dwErrorCode = ERROR_SUCCESS;
Cleanup:
if (pwszRegistryPath)
DllFreeSplMem(pwszRegistryPath);
if (pPrintMonitor)
{
if (pPrintMonitor->pwszFileName)
DllFreeSplMem(pPrintMonitor->pwszFileName);
if (pPrintMonitor->pwszName)
DllFreeSplMem(pPrintMonitor->pwszName);
DllFreeSplMem(pPrintMonitor);
}
// Outside the loop
if (hKey)
RegCloseKey(hKey);
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
LocalAddMonitor(PWSTR pName, DWORD Level, PBYTE pMonitors)
{
PPRINTENV_T env;
LPMONITOR_INFO_2W mi2w;
HKEY hroot = NULL;
HKEY hentry = NULL;
DWORD disposition;
BOOL res = FALSE;
const WCHAR wszMonitorsPath[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors\\";
mi2w = (LPMONITOR_INFO_2W) pMonitors;
FIXME("LocalAddMonitor(%s, %d, %p): %s %s %s\n", debugstr_w(pName), Level, pMonitors,
debugstr_w(mi2w->pName), debugstr_w(mi2w->pEnvironment), debugstr_w(mi2w->pDLLName));
if (copy_servername_from_name(pName, NULL))
{
FIXME("server %s not supported\n", debugstr_w(pName));
SetLastError(ERROR_ACCESS_DENIED);
return FALSE;
}
if (!mi2w->pName || (!mi2w->pName[0]) )
{
FIXME("pName not valid : %s\n", debugstr_w(mi2w->pName));
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
env = validate_envW(mi2w->pEnvironment);
if (!env)
return FALSE; /* ERROR_INVALID_ENVIRONMENT */
if (!mi2w->pDLLName || (!mi2w->pDLLName[0]) )
{
FIXME("pDLLName not valid : %s\n", debugstr_w(mi2w->pDLLName));
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (RegCreateKeyW(HKEY_LOCAL_MACHINE, wszMonitorsPath, &hroot) != ERROR_SUCCESS) {
ERR("unable to create key %s\n", debugstr_w(wszMonitorsPath));
return FALSE;
}
if (RegCreateKeyExW(hroot, mi2w->pName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_QUERY_VALUE, NULL, &hentry, &disposition) == ERROR_SUCCESS)
{
/* Some installers set options for the port before calling AddMonitor.
We query the "Driver" entry to verify that the monitor is installed,
before we return an error.
When a user installs two print monitors at the same time with the
same name, a race condition is possible but silently ignored. */
DWORD namesize = 0;
if ((disposition == REG_OPENED_EXISTING_KEY) &&
(RegQueryValueExW(hentry, L"Driver", NULL, NULL, NULL, &namesize) == ERROR_SUCCESS))
{
FIXME("monitor %s already exists\n", debugstr_w(mi2w->pName));
/* 9x use ERROR_ALREADY_EXISTS */
SetLastError(ERROR_PRINT_MONITOR_ALREADY_INSTALLED);
}
else
{
INT len = (lstrlenW(mi2w->pDLLName) +1) * sizeof(WCHAR);
res = (RegSetValueExW(hentry, L"Driver", 0, REG_SZ, (LPBYTE) mi2w->pDLLName, len) == ERROR_SUCCESS);
/* Load and initialize the monitor. SetLastError() is called on failure */
res = AddPrintMonitorList( mi2w->pName, mi2w->pDLLName );
if ( !res )
{
RegDeleteKeyW(hroot, mi2w->pName);
}
else
SetLastError(ERROR_SUCCESS); /* Monitor installer depends on this */
}
RegCloseKey(hentry);
}
RegCloseKey(hroot);
return res;
}
BOOL WINAPI
LocalDeleteMonitor(PWSTR pName, PWSTR pEnvironment, PWSTR pMonitorName)
{
HKEY hroot = NULL;
LONG lres;
PLOCAL_PRINT_MONITOR pPrintMonitor;
const WCHAR wszMonitorsPath[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors\\";
FIXME("LocalDeleteMonitor(%s, %s, %s)\n",debugstr_w(pName),debugstr_w(pEnvironment),
debugstr_w(pMonitorName));
lres = copy_servername_from_name(pName, NULL);
if (lres)
{
FIXME("server %s not supported\n", debugstr_w(pName));
SetLastError(ERROR_INVALID_NAME);
return FALSE;
}
/* pEnvironment is ignored in Windows for the local Computer */
if (!pMonitorName || !pMonitorName[0])
{
ERR("pMonitorName %s is invalid\n", debugstr_w(pMonitorName));
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
pPrintMonitor = FindPrintMonitor( pMonitorName );
if ( pPrintMonitor )
{
if ( pPrintMonitor->refcount ) pPrintMonitor->refcount--;
if ( pPrintMonitor->refcount == 0 )
{ /* Unload the monitor if it's loaded */
RemoveEntryList(&pPrintMonitor->Entry);
if ( pPrintMonitor->bIsLevel2 )
{
PMONITOR2 pm2 = pPrintMonitor->pMonitor;
if ( pm2 && pm2->pfnShutdown )
{
pm2->pfnShutdown(pPrintMonitor->hMonitor);
}
}
if ( pPrintMonitor->hModule )
FreeLibrary(pPrintMonitor->hModule);
if (pPrintMonitor->pwszFileName)
DllFreeSplStr(pPrintMonitor->pwszFileName);
if (pPrintMonitor->pwszName)
DllFreeSplStr(pPrintMonitor->pwszName);
DllFreeSplMem(pPrintMonitor);
pPrintMonitor = NULL;
}
}
else
{
FIXME("Could not find %s\n", debugstr_w(pMonitorName));
}
if (RegCreateKeyW(HKEY_LOCAL_MACHINE, wszMonitorsPath, &hroot) != ERROR_SUCCESS)
{
ERR("unable to create key %s\n", debugstr_w(wszMonitorsPath));
return FALSE;
}
if (RegDeleteTreeW(hroot, pMonitorName) == ERROR_SUCCESS)
{
FIXME("%s deleted\n", debugstr_w(pMonitorName));
RegCloseKey(hroot);
return TRUE;
}
FIXME("%s does not exist\n", debugstr_w(pMonitorName));
RegCloseKey(hroot);
/* NT: ERROR_UNKNOWN_PRINT_MONITOR (3000), 9x: ERROR_INVALID_PARAMETER (87) */
SetLastError(ERROR_UNKNOWN_PRINT_MONITOR);
return FALSE;
}

View file

@ -33,6 +33,29 @@ FindPort(PCWSTR pwszName)
return NULL;
}
BOOL
CreatePortEntry( PCWSTR pwszName, PLOCAL_PRINT_MONITOR pPrintMonitor )
{
PLOCAL_PORT pPort;
DWORD cbPortName = (wcslen( pwszName ) + 1) * sizeof(WCHAR);
// Create a new LOCAL_PORT structure for it.
pPort = DllAllocSplMem(sizeof(LOCAL_PORT) + cbPortName);
if (!pPort)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
pPort->pPrintMonitor = pPrintMonitor;
pPort->pwszName = wcscpy( (PWSTR)(pPort+1), pwszName );
// Insert it into the list and advance to the next port.
InsertTailList(&_PortList, &pPort->Entry);
return TRUE;
}
BOOL
InitializePortList(void)
{
@ -189,3 +212,288 @@ LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNe
return bReturnValue;
}
BOOL WINAPI
LocalAddPortEx(PWSTR pName, DWORD Level, PBYTE lpBuffer, PWSTR lpMonitorName)
{
DWORD lres;
BOOL res = FALSE;
PLOCAL_PORT pPort;
PLOCAL_PRINT_MONITOR pPrintMonitor;
PORT_INFO_1W * pi = (PORT_INFO_1W *) lpBuffer;
FIXME("LocalAddPortEx(%S, %lu, %p, %S)\n", pName, Level, lpBuffer, lpMonitorName);
lres = copy_servername_from_name(pName, NULL);
if ( lres )
{
FIXME("server %s not supported\n", debugstr_w(pName));
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if ( Level != 1 )
{
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
if ((!pi) || (!lpMonitorName) || (!lpMonitorName[0]))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
pPrintMonitor = FindPrintMonitor( lpMonitorName );
if (!pPrintMonitor )
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
pPort = FindPort( pi->pName );
if ( pPort )
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnAddPortEx )
{
res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnAddPortEx(pPrintMonitor->hMonitor, pName, Level, lpBuffer, lpMonitorName);
}
else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnAddPortEx )
{
res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnAddPortEx(pName, Level, lpBuffer, lpMonitorName);
}
else
{
SetLastError(ERROR_INVALID_PARAMETER);
}
if ( res )
{
res = CreatePortEntry( pi->pName, pPrintMonitor );
}
return res;
}
//
// Local (AP, CP & DP) is still around, seems to be a backup if a failure was encountered.. New way, WinSpool->LocalUI->XcvDataW.
//
BOOL WINAPI
LocalAddPort(LPWSTR pName, HWND hWnd, LPWSTR pMonitorName)
{
DWORD lres;
BOOL res = FALSE;
PLOCAL_PRINT_MONITOR pPrintMonitor;
FIXME("LocalAddPort(%S, %p, %s)\n", pName, hWnd, debugstr_w(pMonitorName));
lres = copy_servername_from_name(pName, NULL);
if (lres)
{
FIXME("server %s not supported\n", debugstr_w(pName));
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
/* an empty Monitorname is Invalid */
if (!pMonitorName[0])
{
SetLastError(ERROR_NOT_SUPPORTED);
return FALSE;
}
pPrintMonitor = FindPrintMonitor( pMonitorName );
if (!pPrintMonitor )
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnAddPort )
{
res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnAddPort(pPrintMonitor->hMonitor, pName, hWnd, pMonitorName);
}
else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnAddPort )
{
res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnAddPort(pName, hWnd, pMonitorName);
}
else
{
SetLastError(ERROR_INVALID_PARAMETER);
}
if ( res )
{
DWORD cbNeeded, cReturned, i;
PPORT_INFO_1 pPorts;
//
// Play it safe,,, we know its Monitor2.... This is ReactOS.
//
if ( LocalEnumPorts( pName, 1, NULL, 0, &cbNeeded, &cReturned ) )
{
pPorts = DllAllocSplMem( cbNeeded );
if (pPorts)
{
if ( LocalEnumPorts( pName, 1, (PBYTE)pPorts, cbNeeded, &cbNeeded, &cReturned ) )
{
for ( i = 0; i < cReturned; i++ )
{
if ( !FindPort( pPorts[i].pName ) )
{
CreatePortEntry( pPorts[i].pName, pPrintMonitor );
}
}
}
DllFreeSplMem( pPorts );
}
}
}
return res;
}
BOOL WINAPI
LocalConfigurePort(PWSTR pName, HWND hWnd, PWSTR pPortName)
{
LONG lres;
DWORD res;
PLOCAL_PORT pPrintPort;
PLOCAL_PRINT_MONITOR pPrintMonitor;
FIXME("LocalConfigurePort(%S, %p, %S)\n", pName, hWnd, pPortName);
lres = copy_servername_from_name(pName, NULL);
if (lres)
{
FIXME("server %s not supported\n", debugstr_w(pName));
SetLastError(ERROR_INVALID_NAME);
return FALSE;
}
/* an empty Portname is Invalid, but can popup a Dialog */
if (!pPortName[0])
{
SetLastError(ERROR_NOT_SUPPORTED);
return FALSE;
}
pPrintPort = FindPort(pPortName);
if (!pPrintPort )
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
pPrintMonitor = pPrintPort->pPrintMonitor;
if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnConfigurePort )
{
res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnConfigurePort(pPrintMonitor->hMonitor, pName, hWnd, pPortName);
}
else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnConfigurePort )
{
res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnConfigurePort(pName, hWnd, pPortName);
}
else
{
SetLastError(ERROR_INVALID_PARAMETER);
}
return res;
}
BOOL WINAPI
LocalDeletePort(PWSTR pName, HWND hWnd, PWSTR pPortName)
{
LONG lres;
DWORD res = FALSE;
PLOCAL_PORT pPrintPort;
PLOCAL_PRINT_MONITOR pPrintMonitor;
FIXME("LocalDeletePort(%S, %p, %S)\n", pName, hWnd, pPortName);
lres = copy_servername_from_name(pName, NULL);
if (lres)
{
FIXME("server %s not supported\n", debugstr_w(pName));
SetLastError(ERROR_INVALID_NAME);
return FALSE;
}
if (!pPortName[0])
{
SetLastError(ERROR_NOT_SUPPORTED);
return FALSE;
}
pPrintPort = FindPort(pPortName);
if (!pPrintPort )
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
pPrintMonitor = pPrintPort->pPrintMonitor;
if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnDeletePort )
{
res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnDeletePort(pPrintMonitor->hMonitor, pName, hWnd, pPortName);
}
else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnDeletePort )
{
res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnDeletePort(pName, hWnd, pPortName);
}
RemoveEntryList(&pPrintPort->Entry);
DllFreeSplMem(pPrintPort);
return res;
}
BOOL WINAPI
LocalSetPort(PWSTR pName, PWSTR pPortName, DWORD dwLevel, PBYTE pPortInfo)
{
LONG lres;
DWORD res = 0;
PPORT_INFO_3W ppi3w = (PPORT_INFO_3W)pPortInfo;
PLOCAL_PORT pPrintPort;
TRACE("LocalSetPort(%S, %S, %lu, %p)\n", pName, pPortName, dwLevel, pPortInfo);
lres = copy_servername_from_name(pName, NULL);
if (lres)
{
FIXME("server %s not supported\n", debugstr_w(pName));
SetLastError(ERROR_INVALID_NAME);
return FALSE;
}
if ((dwLevel < 1) || (dwLevel > 2))
{
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
if ( !ppi3w )
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
pPrintPort = FindPort(pPortName);
if ( !pPrintPort )
{
SetLastError(ERROR_UNKNOWN_PORT);
return FALSE;
}
FIXME("Add Status Support to Local Ports!\n");
return res;
}

View file

@ -22,6 +22,7 @@
#include <winreg.h>
#include <winspool.h>
#include <winsplp.h>
#include <winddiui.h>
#include <dsrole.h>
#include <secext.h>
#include <ndk/rtlfuncs.h>
@ -49,6 +50,7 @@ typedef HANDLE (WINAPI *POpenPrintProcessor)(LPWSTR, PPRINTPROCESSOROPENDATA);
typedef BOOL (WINAPI *PPrintDocumentOnPrintProcessor)(HANDLE, LPWSTR);
typedef LPMONITOREX(WINAPI *PInitializePrintMonitor)(PWSTR);
typedef LPMONITOR2(WINAPI *PInitializePrintMonitor2)(PMONITORINIT, PHANDLE);
typedef PMONITORUI(WINAPI *PInitializePrintMonitorUI)(VOID);
// Forward declarations
typedef struct _LOCAL_HANDLE LOCAL_HANDLE, *PLOCAL_HANDLE;
@ -69,8 +71,10 @@ typedef struct _SHD_HEADER SHD_HEADER, *PSHD_HEADER;
struct _LOCAL_PRINT_MONITOR
{
LIST_ENTRY Entry;
DWORD refcount;
PWSTR pwszName; /** Name of the Print Monitor as read from the registry. */
PWSTR pwszFileName; /** DLL File Name of the Print Monitor. */
HMODULE hModule;
BOOL bIsLevel2; /** Whether this Print Monitor supplies an InitializePrintMonitor2 API (preferred) instead of InitializePrintMonitor. */
PVOID pMonitor; /** For bIsLevel2 == TRUE: LPMONITOR2 pointer returned by InitializePrintMonitor2.
For bIsLevel2 == FALSE: LPMONITOREX pointer returned by InitializePrintMonitor. */
@ -241,6 +245,14 @@ struct _SHD_HEADER
DWORD dwSPLSize;
};
// forms.c
BOOL InitializeFormList(VOID);
BOOL WINAPI LocalAddForm(HANDLE hPrinter, DWORD Level, PBYTE pForm);
BOOL WINAPI LocalDeleteForm(HANDLE hPrinter, PWSTR pFormName);
BOOL WINAPI LocalEnumForms(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned);
BOOL WINAPI LocalGetForm(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded);
BOOL WINAPI localSetForm(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm);
// jobs.c
extern SKIPLIST GlobalJobList;
DWORD WINAPI CreateJob(PLOCAL_PRINTER_HANDLE pPrinterHandle);
@ -275,11 +287,19 @@ extern LIST_ENTRY PrintMonitorList;
PLOCAL_PRINT_MONITOR FindPrintMonitor(PCWSTR pwszName);
BOOL InitializePrintMonitorList(void);
BOOL WINAPI LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned);
BOOL WINAPI LocalAddMonitor(PWSTR pName, DWORD Level, PBYTE pMonitors);
BOOL WINAPI LocalDeleteMonitor(PWSTR pName, PWSTR pEnvironment, PWSTR pMonitorName);
// ports.c
PLOCAL_PORT FindPort(PCWSTR pwszName);
BOOL InitializePortList(void);
BOOL WINAPI LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned);
BOOL WINAPI LocalAddPortEx(PWSTR pName, DWORD Level, PBYTE lpBuffer, PWSTR lpMonitorName);
BOOL WINAPI LocalAddPort(LPWSTR pName, HWND hWnd, LPWSTR pMonitorName);
BOOL WINAPI LocalConfigurePort(PWSTR pName, HWND hWnd, PWSTR pPortName);
BOOL WINAPI LocalDeletePort(PWSTR pName, HWND hWnd, PWSTR pPortName);
BOOL WINAPI LocalSetPort(PWSTR pName, PWSTR pPortName, DWORD dwLevel, PBYTE pPortInfo);
BOOL CreatePortEntry( PCWSTR pwszName, PLOCAL_PRINT_MONITOR pPrintMonitor );
// printerdata.c
DWORD WINAPI LocalGetPrinterData(HANDLE hPrinter, PWSTR pValueName, PDWORD pType, PBYTE pData, DWORD nSize, PDWORD pcbNeeded);
@ -287,9 +307,26 @@ DWORD WINAPI LocalGetPrinterDataEx(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pVal
DWORD WINAPI LocalSetPrinterData(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData);
DWORD WINAPI LocalSetPrinterDataEx(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData);
// printerdriver.c
// printerdrivers.c
BOOL InitializePrinterDrivers(VOID);
BOOL WINAPI LocalAddPrinterDriver(LPWSTR pName, DWORD level, LPBYTE pDriverInfo);
BOOL WINAPI LocalAddPrinterDriverEx(LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags);
BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded);
BOOL WINAPI LocalGetPrinterDriverDirectory(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverDirectory, DWORD cbBuf, PDWORD pcbNeeded);
BOOL WINAPI LocalGetPrinterDriverEx(HANDLE hPrinter,LPWSTR pEnvironment,DWORD Level,LPBYTE pDriverInfo,DWORD cbBuf,LPDWORD pcbNeeded,DWORD dwClientMajorVersion,DWORD dwClientMinorVersion,PDWORD pdwServerMajorVersion,PDWORD pdwServerMinorVersion );
BOOL WINAPI LocalEnumPrinterDrivers(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned);
// wine codes
typedef struct _PRINTENV_T
{
LPCWSTR envname;
LPCWSTR subdir;
DWORD driverversion;
LPCWSTR versionregpath;
LPCWSTR versionsubdir;
} PRINTENV_T, *PPRINTENV_T;
PPRINTENV_T validate_envW(LPCWSTR env);
// printers.c
extern SKIPLIST PrinterList;
@ -297,6 +334,7 @@ BOOL InitializePrinterList(void);
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);
BOOL WINAPI LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDefault);
DWORD WINAPI LocalPrinterMessageBox(HANDLE hPrinter, DWORD Error, HWND hWnd, LPWSTR pText, LPWSTR pCaption, DWORD dwType);
BOOL WINAPI LocalReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead);
DWORD WINAPI LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo);
BOOL WINAPI LocalStartPagePrinter(HANDLE hPrinter);
@ -304,6 +342,7 @@ BOOL WINAPI LocalWritePrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf, LPDWORD
BOOL WINAPI LocalEndPagePrinter(HANDLE hPrinter);
BOOL WINAPI LocalEndDocPrinter(HANDLE hPrinter);
BOOL WINAPI LocalClosePrinter(HANDLE hPrinter);
VOID BroadcastChange(PLOCAL_HANDLE pHandle);
// printingthread.c
DWORD WINAPI PrintingThreadProc(PLOCAL_JOB pJob);
@ -324,5 +363,11 @@ BOOL WINAPI LocalCloseSpoolFileHandle(HANDLE hPrinter);
// tools.c
PWSTR AllocAndRegQueryWSZ(HKEY hKey, PCWSTR pwszValueName);
PDEVMODEW DuplicateDevMode(PDEVMODEW pInput);
// wine codes
LONG copy_servername_from_name(LPCWSTR name, LPWSTR target);
// Xcv.c
BOOL WINAPI LocalXcvData(HANDLE hXcv, const WCHAR* pszDataName, BYTE* pInputData, DWORD cbInputData, BYTE* pOutputData, DWORD cbOutputData, DWORD* pcbOutputNeeded, DWORD* pdwStatus);
#endif

File diff suppressed because it is too large Load diff

View file

@ -346,6 +346,24 @@ Cleanup:
return (dwErrorCode == ERROR_SUCCESS);
}
VOID
BroadcastChange(PLOCAL_HANDLE pHandle)
{
PLOCAL_PRINTER pPrinter;
PSKIPLIST_NODE pNode;
DWORD cchMachineName = 0;
WCHAR wszMachineName[MAX_PATH] = {0}; // if not local, use Machine Name then Printer Name... pPrinter->pJob->pwszMachineName?
for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
{
pPrinter = (PLOCAL_PRINTER)pNode->Element;
StringCchCopyW( &wszMachineName[cchMachineName], sizeof(wszMachineName), pPrinter->pwszPrinterName );
PostMessageW( HWND_BROADCAST, WM_DEVMODECHANGE, 0, (LPARAM)&wszMachineName );
}
}
/**
* @name _LocalEnumPrintersCheckName
*
@ -607,7 +625,7 @@ _LocalGetPrinterLevel2(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_2W* ppPrinterInfo,
size_t cbParameters;
PWSTR p, Allocation;
PCWSTR pwszStrings[10];
FIXME("LocalGetPrinterLevel2\n");
// Calculate the string lengths.
cbDevMode = pPrinter->pDefaultDevMode->dmSize + pPrinter->pDefaultDevMode->dmDriverExtra;
cbPrinterName = (cchComputerName + wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
@ -626,6 +644,7 @@ _LocalGetPrinterLevel2(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_2W* ppPrinterInfo,
cbParameters = sizeof(wszEmpty);
*pcbNeeded += sizeof(PRINTER_INFO_2W) + cbDevMode + cbPrinterName + cbShareName + cbPortName + cbDriverName + cbComment + cbLocation + cbSepFile + cbPrintProcessor + cbDatatype + cbParameters;
FIXME("LocalGetPrinterLevel2 Needed %d\n",*pcbNeeded);
return;
}
@ -871,7 +890,7 @@ LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DW
WCHAR wszComputerName[2 + MAX_COMPUTERNAME_LENGTH + 1 + 1] = { 0 };
PLOCAL_PRINTER pPrinter;
TRACE("LocalEnumPrinters(%lu, %S, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
FIXME("LocalEnumPrinters(%lu, %S, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
// Do no sanity checks or assertions for pcbNeeded and pcReturned here.
// This is verified and required by localspl_apitest!
@ -1283,6 +1302,7 @@ _LocalOpenXcvHandle(PWSTR pwszParameter, PHANDLE phPrinter)
{
// The caller supplied a non-existing Monitor name.
dwErrorCode = ERROR_INVALID_NAME;
ERR("OpenXcvHandle failed on Monitor name! %lu\n", dwErrorCode);
goto Failure;
}
}
@ -1297,6 +1317,7 @@ _LocalOpenXcvHandle(PWSTR pwszParameter, PHANDLE phPrinter)
{
// The supplied port is unknown to all our Print Monitors.
dwErrorCode = ERROR_INVALID_NAME;
ERR("OpenXcvHandle failed on Port name! %lu\n", dwErrorCode);
goto Failure;
}
@ -1305,6 +1326,7 @@ _LocalOpenXcvHandle(PWSTR pwszParameter, PHANDLE phPrinter)
else
{
dwErrorCode = ERROR_INVALID_NAME;
ERR("OpenXcvHandle failed on bad name! %lu\n", dwErrorCode);
goto Failure;
}
@ -1318,6 +1340,7 @@ _LocalOpenXcvHandle(PWSTR pwszParameter, PHANDLE phPrinter)
{
// The XcvOpenPort function failed. Return its last error.
dwErrorCode = GetLastError();
ERR("XcvOpenPort function failed! %lu\n", dwErrorCode);
goto Failure;
}
@ -1348,6 +1371,7 @@ _LocalOpenXcvHandle(PWSTR pwszParameter, PHANDLE phPrinter)
// Return it.
*phPrinter = (HANDLE)pHandle;
ERR("OpenXcvHandle Success! %p\n", pXcvHandle);
return ERROR_SUCCESS;
Failure:
@ -1360,6 +1384,16 @@ Failure:
return dwErrorCode;
}
//
// Dead API
//
DWORD WINAPI
LocalPrinterMessageBox(HANDLE hPrinter, DWORD Error, HWND hWnd, LPWSTR pText, LPWSTR pCaption, DWORD dwType)
{
SetLastError(ERROR_INVALID_HANDLE); // Yes....
return 0;
}
BOOL WINAPI
LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDefault)
{
@ -1475,6 +1509,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
// "\\COMPUTERNAME\, XcvMonitor Local Port"
// ", XcvPort LPT1:"
// "\\COMPUTERNAME\, XcvPort LPT1:"
FIXME("OpenXcvHandle : %S\n",pwszSecondParameter);
dwErrorCode = _LocalOpenXcvHandle(pwszSecondParameter, phPrinter);
}
else
@ -1890,6 +1925,7 @@ Cleanup:
static void
_LocalClosePortHandle(PLOCAL_PORT_HANDLE pPortHandle)
{
FIXME("LocalClosePortHandle\n");
// Call the monitor's ClosePort function.
if (pPortHandle->pPort->pPrintMonitor->bIsLevel2)
((PMONITOR2)pPortHandle->pPort->pPrintMonitor->pMonitor)->pfnClosePort(pPortHandle->hPort);
@ -1900,6 +1936,7 @@ _LocalClosePortHandle(PLOCAL_PORT_HANDLE pPortHandle)
static void
_LocalClosePrinterHandle(PLOCAL_PRINTER_HANDLE pPrinterHandle)
{
FIXME("LocalClosePrinterHandle\n");
// Terminate any started job.
if (pPrinterHandle->pJob)
FreeJob(pPrinterHandle->pJob);
@ -1924,7 +1961,7 @@ LocalClosePrinter(HANDLE hPrinter)
{
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
TRACE("LocalClosePrinter(%p)\n", hPrinter);
FIXME("LocalClosePrinter(%p)\n", hPrinter);
if (!pHandle)
{
@ -1948,12 +1985,12 @@ LocalClosePrinter(HANDLE hPrinter)
{
_LocalCloseXcvHandle(pHandle->pSpecificHandle);
}
FIXME("LocalClosePrinter 1\n");
// Free memory for the handle and the specific handle (if any).
if (pHandle->pSpecificHandle)
DllFreeSplMem(pHandle->pSpecificHandle);
FIXME("LocalClosePrinter 2\n");
DllFreeSplMem(pHandle);
FIXME("LocalClosePrinter 3\n");
return TRUE;
}

View file

@ -75,3 +75,56 @@ DuplicateDevMode(PDEVMODEW pInput)
return pOutput;
}
/******************************************************************
* copy_servername_from_name (internal)
*
* for an external server, the serverpart from the name is copied.
*
* RETURNS
* the length (in WCHAR) of the serverpart (0 for the local computer)
* (-length), when the name is too long
*
*/
LONG copy_servername_from_name(LPCWSTR name, LPWSTR target)
{
LPCWSTR server;
LPWSTR ptr;
WCHAR buffer[MAX_COMPUTERNAME_LENGTH +1];
DWORD len;
DWORD serverlen;
if (target) *target = '\0';
if (name == NULL) return 0;
if ((name[0] != '\\') || (name[1] != '\\')) return 0;
server = &name[2];
/* skip over both backslash, find separator '\' */
ptr = wcschr(server, '\\');
serverlen = (ptr) ? ptr - server : lstrlenW(server);
/* servername is empty */
if (serverlen == 0) return 0;
FIXME("found %s\n", debugstr_wn(server, serverlen));
if (serverlen > MAX_COMPUTERNAME_LENGTH) return -serverlen;
if (target)
{
memcpy(target, server, serverlen * sizeof(WCHAR));
target[serverlen] = '\0';
}
len = ARRAYSIZE(buffer);
if (GetComputerNameW(buffer, &len))
{
if ((serverlen == len) && (wcsnicmp(server, buffer, len) == 0))
{
/* The requested Servername is our computername */
return 0;
}
}
return serverlen;
}

View file

@ -0,0 +1,199 @@
/*
* PROJECT: ReactOS Print Spooler Service
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Xcv* functions
* COPYRIGHT: Copyright 2020 ReactOS
*/
#include "precomp.h"
static DWORD
_HandleAddPort(HANDLE hXcv, PBYTE pInputData, PDWORD pcbOutputNeeded, DWORD* pdwStatus)
{
DWORD res;
PLOCAL_PRINT_MONITOR pPrintMonitor;
PLOCAL_XCV_HANDLE pXcv;
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hXcv;
PWSTR pPortName = (PWSTR)pInputData;
FIXME("LocalXcvAddPort : %s\n", debugstr_w( pPortName ) );
// Check if this is a printer handle.
if (pHandle->HandleType != HandleType_Xcv)
{
ERR("LocalXcvAddPort : Invalid XCV Handle\n");
res = ERROR_INVALID_HANDLE;
goto Cleanup;
}
pXcv = (PLOCAL_XCV_HANDLE)pHandle->pSpecificHandle;
pPrintMonitor = pXcv->pPrintMonitor;
if (!pPrintMonitor )
{
res = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
// Sanity checks
if (!pInputData || !pcbOutputNeeded)
{
res = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
pPrintMonitor->refcount++;
if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnXcvDataPort )
{
res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnXcvDataPort(pXcv->hXcv, L"AddPort", pInputData, 0, NULL, 0, pcbOutputNeeded);
}
else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnXcvDataPort )
{
res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnXcvDataPort(pXcv->hXcv, L"AddPort", pInputData, 0, NULL, 0, pcbOutputNeeded);
}
pPrintMonitor->refcount--;
if ( res == ERROR_SUCCESS )
{
CreatePortEntry( pPortName, pPrintMonitor );
}
FIXME("=> %u\n", res);
Cleanup:
if (pdwStatus) *pdwStatus = res;
return res;
}
static DWORD
_HandleDeletePort(HANDLE hXcv, PBYTE pInputData, PDWORD pcbOutputNeeded, DWORD* pdwStatus)
{
DWORD res;
PLOCAL_PRINT_MONITOR pPrintMonitor;
PLOCAL_XCV_HANDLE pXcv;
PLOCAL_PORT pPort;
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hXcv;
PWSTR pPortName = (PWSTR)pInputData;
FIXME("LocalXcvDeletePort : %s\n", debugstr_w( pPortName ) );
// Check if this is a printer handle.
if (pHandle->HandleType != HandleType_Xcv)
{
ERR("LocalXcvDeletePort : Invalid XCV Handle\n");
res = ERROR_INVALID_HANDLE;
goto Cleanup;
}
pXcv = (PLOCAL_XCV_HANDLE)pHandle->pSpecificHandle;
pPrintMonitor = pXcv->pPrintMonitor;
if (!pPrintMonitor )
{
res = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
// Sanity checks
if (!pInputData || !pcbOutputNeeded)
{
res = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
pPrintMonitor->refcount++;
//
// Call back to monitor, update the Registry and Registry List.
//
if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnXcvDataPort )
{
res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnXcvDataPort(pXcv->hXcv, L"DeletePort", pInputData, 0, NULL, 0, pcbOutputNeeded);
}
else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnXcvDataPort )
{
res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnXcvDataPort(pXcv->hXcv, L"DeletePort", pInputData, 0, NULL, 0, pcbOutputNeeded);
}
pPrintMonitor->refcount--;
//
// Now find and remove Local Port data.
//
if ( res == ERROR_SUCCESS )
{
pPort = FindPort( pPortName );
if (pPort )
{
FIXME("LocalXcvDeletePort removed Port Entry\n");
RemoveEntryList(&pPort->Entry);
DllFreeSplMem(pPort);
}
FIXME("=> %u with %u\n", res, GetLastError() );
}
Cleanup:
if (pdwStatus) *pdwStatus = res;
return res;
}
BOOL WINAPI
LocalXcvData(HANDLE hXcv, const WCHAR* pszDataName, BYTE* pInputData, DWORD cbInputData, BYTE* pOutputData, DWORD cbOutputData, DWORD* pcbOutputNeeded, DWORD* pdwStatus)
{
DWORD res;
PLOCAL_PRINT_MONITOR pPrintMonitor;
PLOCAL_XCV_HANDLE pXcv;
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hXcv;
FIXME("LocalXcvData(%p, %S, %p, %lu, %p, %lu, %p)\n", hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded);
// Sanity checks
if (!pszDataName)
{
res = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
// Call the appropriate handler for the requested data name.
if (wcscmp(pszDataName, L"AddPort") == 0)
return _HandleAddPort(hXcv, pInputData, pcbOutputNeeded, pdwStatus);
if (wcscmp(pszDataName, L"DeletePort") == 0)
return _HandleDeletePort(hXcv, pInputData, pcbOutputNeeded, pdwStatus);
//
// After the two Intercept Handlers, defer call back to Monitor.
//
// Check if this is a printer handle.
if (pHandle->HandleType != HandleType_Xcv)
{
ERR("LocalXcvData : Invalid XCV Handle\n");
res = ERROR_INVALID_HANDLE;
goto Cleanup;
}
pXcv = (PLOCAL_XCV_HANDLE)pHandle->pSpecificHandle;
pPrintMonitor = pXcv->pPrintMonitor;
if (!pPrintMonitor )
{
res = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
pPrintMonitor->refcount++;
if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnXcvDataPort )
{
res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnXcvDataPort(pXcv->hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded);
}
else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnXcvDataPort )
{
res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnXcvDataPort(pXcv->hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded);
}
pPrintMonitor->refcount--;
Cleanup:
SetLastError(res);
if (pdwStatus) *pdwStatus = res;
return res;
}