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.
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];
"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);
(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);
}
/* EnumPrinterDriversA returns the same number of bytes as EnumPrinterDriversW */
- if (!on_win9x && pEnumPrinterDriversW)
+ if (pEnumPrinterDriversW)
{
DWORD double_needed;
DWORD double_returned;
/* 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);
}
if (!pSetDefaultPrinterA) return;
- /* only supported on win2k and above */
+ /* only supported on win2k and above */
/* backup the original value */
org_value[0] = '\0';
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);
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;
}
}
/* 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);
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",
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();
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();
#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;
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;
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;
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;
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;
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;
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;
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;
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;
#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;
__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
#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
#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
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 */
DWORD _RpcDeleteMonitor(
[in, unique] WINSPOOL_HANDLE pName,
[in, string, unique] WCHAR* pEnvironment,
- [in, string] WCHAR* pMonitorName
+ [in, string, unique] WCHAR* pMonitorName
);
/* Function 0x30 */
/* 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
/* 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 */
[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 */
/* 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,
/* 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,
/* 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,
/* 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
/* 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,
#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
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)
--- /dev/null
+/*
+ * 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);
+}
#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)
{
DWORD cbCallBuffer;
DWORD cbNeeded;
DWORD dwReturned;
+ DWORD dwErrorCode = MAXDWORD;
PBYTE pCallBuffer;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
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;
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);
}
#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)
{
DWORD cbCallBuffer;
DWORD cbNeeded;
DWORD dwReturned;
+ DWORD dwErrorCode = MAXDWORD;
PBYTE pCallBuffer;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
{
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;
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();
+ }
+
+ 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();
}
- return bReturnValue;
+ SetLastError(dwErrorCode);
+ return (dwErrorCode == ERROR_SUCCESS);
}
#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)
{
--- /dev/null
+/*
+ * 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);
+}
#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)
BOOL bReturnValue;
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+ FIXME("ClosePrinter %p\n",hPrinter);
+
// Sanity checks.
if (!pHandle)
{
// 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)
{
DWORD dwErrorCode = MAXDWORD;
DWORD dwReturned;
PBYTE pCallBuffer;
+ BOOL Ret = FALSE;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
// 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;
}
BOOL WINAPI
-GetPrinterDriverW(HANDLE hPrinter, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded)
+GetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD cbBuf, PDWORD pcbNeeded)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
return FALSE;
}
- return pHandle->pPrintProvider->PrintProvider.fpGetPrinterDriver(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
+ return pHandle->pPrintProvider->PrintProvider.fpGetPrinter(pHandle->hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
}
-BOOL WINAPI
-GetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD cbBuf, PDWORD 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;
return FALSE;
}
- return pHandle->pPrintProvider->PrintProvider.fpGetPrinter(pHandle->hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
+ return pHandle->pPrintProvider->PrintProvider.fpPrinterMessageBox(pHandle->hPrinter, Error, hWnd, pText, pCaption, dwType);
}
BOOL WINAPI
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)
{
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hXcv;
+ FIXME("XcvDataW( %p, %S,,,)\n",hXcv, pszDataName);
+
// Sanity checks.
if (!pHandle)
{
*/
#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)
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);
{
// 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);
}
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);
--- /dev/null
+/*
+ * 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;
+}
-@ 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
@ 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)
@ 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)
@ 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)
@ stub PartialReplyPrinterChangeNotification
@ stub PlayGdiScriptOnPrinterIC
@ stub PrinterHandleRundown
-@ stub PrinterMessageBoxW
+@ stdcall PrinterMessageBoxW(ptr long ptr wstr wstr long)
@ stub ProvidorFindClosePrinterChangeNotification
@ stub ProvidorFindFirstPrinterChangeNotification
@ stub pszDbgAllocMsgA
@ stub ReplyClosePrinter
@ stub ReplyOpenPrinter
@ stub ReplyPrinterChangeNotification
-@ stub ResetPrinterW
+@ stdcall -stub ResetPrinterW(ptr ptr)
@ stdcall RevertToPrinterSelf()
@ stub RouterAllocBidiMem
@ stub RouterAllocBidiResponseContainer
@ 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
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
*/
#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;
}
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
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
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;
}
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
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)
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
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)
{
- UNIMPLEMENTED;
- return ERROR_INVALID_FUNCTION;
+ 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
+ {
+ dwErrorCode = GetLastError();
+ }
+
+ RpcRevertToSelf();
+ UndoAlignRpcPtr(pDriver, pDriverAligned, cbBuf, pcbNeeded);
+
+ return dwErrorCode;
}
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;
}
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
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
}
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
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
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;
}
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
--- /dev/null
+@ 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)
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;
}
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);
{
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;
{
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);
{
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:
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:
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;
}
}
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));
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);
}
{
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)
{
ERR("_RpcAddMonitor failed with exception code %lu!\n", dwErrorCode);
}
RpcEndExcept;
-
+FIXME("AddMonitorW Error Code %lu\n", dwErrorCode);
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
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);
}
{
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
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);
#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;
// 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;
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;
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)
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;
}
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;
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 )
{
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
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;
}
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
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)
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;
}
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
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)
{
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);
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
{
// 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);
res = DeletePrinterDataW( hPrinter, valuenameW );
- HeapFree(GetProcessHeap(), 0, valuenameW);
+ if (valuenameW) HeapFree(GetProcessHeap(), 0, valuenameW);
return res;
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;
}
res = DeletePrinterKeyW( hPrinter, keynameW );
- HeapFree(GetProcessHeap(), 0, keynameW);
+ if (keynameW) HeapFree(GetProcessHeap(), 0, keynameW);
return res;
}
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)
#include "precomp.h"
#include <marshalling/printerdrivers.h>
+
extern const WCHAR wszCurrentEnvironment[];
static int multi_sz_lenA(const char *str)
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;
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;
}
case 4:
{
-
PDRIVER_INFO_4W pdi4w = (PDRIVER_INFO_4W)pDriverInfo;
if ( pdi == NULL ) pdi = HeapAlloc(hProcessHeap, 0, sizeof(WINSPOOL_DRIVER_INFO_4));
BOOL WINAPI
DeletePrinterDriverExA(PSTR pName, PSTR pEnvironment, PSTR pDriverName, DWORD dwDeleteFlag, DWORD dwVersionFlag)
{
+ DWORD dwErrorCode;
UNICODE_STRING NameW, EnvW, DriverW;
BOOL ret;
ret = DeletePrinterDriverExW(NameW.Buffer, EnvW.Buffer, DriverW.Buffer, dwDeleteFlag, dwVersionFlag);
+ dwErrorCode = GetLastError();
+
RtlFreeUnicodeString(&DriverW);
RtlFreeUnicodeString(&EnvW);
RtlFreeUnicodeString(&NameW);
+ SetLastError(dwErrorCode);
return ret;
}
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++ )
}
}
}
+ dwErrorCode = ERROR_SUCCESS;
}
Cleanup:
RtlFreeUnicodeString(&pNameW);
RtlFreeUnicodeString(&pEnvironmentW);
-
+ SetLastError(dwErrorCode);
+ FIXME("EnumPrinterDriversA Exit %d Err %d\n",ret,GetLastError());
return ret;
}
{
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;
}
Cleanup:
- SetLastError(dwErrorCode);
+ SetLastError(dwErrorCode); FIXME("EnumPrinterDriversW Exit Err %d\n",dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
if (Level < 1 || Level == 7 || Level > 8)
{
dwErrorCode = ERROR_INVALID_LEVEL;
- ERR("Invalid Level!\n");
+ ERR("Invalid Level! %d\n",Level);
goto Cleanup;
}
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;
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;
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;
}
RpcEndExcept;
+Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
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;
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;
}
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)
{
dwReturnValue = pHandle->dwJobID;
if ( !pHandle->bTrayIcon )
{
- FIXME("Notify Tray Icon\n");
+ UpdateTrayIcon( hPrinter, pHandle->dwJobID );
}
}
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);
}
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);
*/
#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.
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");
+ }
+}
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)
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 }
}
};
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 }
}
};
&PrinterDriver4Marshalling,
&PrinterDriver5Marshalling,
&PrinterDriver6Marshalling,
+ NULL,
&PrinterDriver8Marshalling,
};
#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
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);
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
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
PLOCALMON_HANDLE pLocalmon;
PLOCALMON_PORT pPort;
PLOCALMON_XCV pXcv;
+ PLIST_ENTRY pEntry;
TRACE("LocalmonShutdown(%p)\n", hMonitor);
pLocalmon = (PLOCALMON_HANDLE)hMonitor;
+ if ( pLocalmon->Sig != SIGLCMMON )
+ {
+ ERR("LocalmonShutdown : Invalid Monitor Handle\n",hMonitor);
+ return;
+ }
+
// Close all virtual file ports.
- while (!IsListEmpty(&pLocalmon->FilePorts))
+ if (!IsListEmpty(&pLocalmon->FilePorts))
{
- pPort = CONTAINING_RECORD(&pLocalmon->FilePorts.Flink, LOCALMON_PORT, Entry);
- LocalmonClosePort((HANDLE)pPort);
+ 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.
// Create a new LOCALMON_HANDLE structure.
pLocalmon = DllAllocSplMem(sizeof(LOCALMON_HANDLE));
+ pLocalmon->Sig = SIGLCMMON;
InitializeCriticalSection(&pLocalmon->Section);
InitializeListHead(&pLocalmon->FilePorts);
InitializeListHead(&pLocalmon->RegistryPorts);
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;
// 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;
DefineDosDeviceW(DDD_REMOVE_DEFINITION, pwszNonspooledPortName, NULL);
DllFreeSplMem(pwszNonspooledPortName);
}
-
DllFreeSplMem(pwszPortNameWithoutColon);
}
}
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);
+}
#include "resource.h"
+#define SIGLCMMON 'FrCN'
+#define SIGLCMPORT 'FrHK'
+
// Structures
/**
* Describes the monitor handle returned by InitializePrintMonitor2.
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. */
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. */
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;
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);
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;
+}
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;
}
/**
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;
}
/**
const WCHAR wszMonitorUI[] = L"LocalUI.dll";
// Sanity checks
- if (!pOutputData || !pcbOutputNeeded)
+ if (!pcbOutputNeeded)
return ERROR_INVALID_PARAMETER;
*pcbOutputNeeded = sizeof(wszMonitorUI);
if (cbOutputData < *pcbOutputNeeded)
return ERROR_INSUFFICIENT_BUFFER;
+ if (!pOutputData)
+ return ERROR_INVALID_PARAMETER;
+
// Copy the string.
CopyMemory(pOutputData, wszMonitorUI, sizeof(wszMonitorUI));
return ERROR_SUCCESS;
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();
}
/**
}
// 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);
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)
+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
printingthread.c
printprocessors.c
spoolfile.c
- tools.c)
+ tools.c
+ xcv.c)
add_library(localspl MODULE
${SOURCE}
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)
--- /dev/null
+/*
+ * 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);
+}
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
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
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
NULL, // fpAddPerMachineConnection
NULL, // fpDeletePerMachineConnection
NULL, // fpEnumPerMachineConnections
- NULL, // fpXcvData
- NULL, // fpAddPrinterDriverEx
+ LocalXcvData, // fpXcvData
+ LocalAddPrinterDriverEx, // fpAddPrinterDriverEx
NULL, // fpSplReadPrinter
NULL, // fpDriverUnloadComplete
LocalGetSpoolFileInfo, // fpGetSpoolFileInfo
if (!InitializeGlobalJobList())
goto Cleanup;
+ if (!InitializeFormList())
+ goto Cleanup;
+
+ if (!InitializePrinterDrivers())
+ goto Cleanup;
+
// Local Spooler Initialization finished successfully!
bReturnValue = TRUE;
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)
{
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)
continue;
}
+ pPrintMonitor->hModule = hinstPrintMonitor;
+
// Try to find a Level 2 initialization routine first.
pfnInitializePrintMonitor2 = (PInitializePrintMonitor2)GetProcAddress(hinstPrintMonitor, "InitializePrintMonitor2");
if (pfnInitializePrintMonitor2)
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);
ERR("InitializePrintMonitor2 failed for \"%S\" with error %lu!\n", pPrintMonitor->pwszFileName, GetLastError());
continue;
}
-
+ FIXME("InitializePrintMonitor2 loaded.\n");
pPrintMonitor->bIsLevel2 = TRUE;
}
else
// 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;
return (dwErrorCode == ERROR_SUCCESS);
}
+
static void
_LocalGetMonitorLevel1(PLOCAL_PRINT_MONITOR pPrintMonitor, PMONITOR_INFO_1W* ppMonitorInfo, PBYTE* ppMonitorInfoEnd, PDWORD pcbNeeded)
{
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;
+}
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)
{
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;
+}
#include <winreg.h>
#include <winspool.h>
#include <winsplp.h>
+#include <winddiui.h>
#include <dsrole.h>
#include <secext.h>
#include <ndk/rtlfuncs.h>
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;
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. */
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);
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);
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;
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);
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);
// 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
#include "precomp.h"
#include <strsafe.h>
+typedef struct {
+ WCHAR src[MAX_PATH+MAX_PATH];
+ WCHAR dst[MAX_PATH+MAX_PATH];
+ DWORD srclen;
+ DWORD dstlen;
+ DWORD copyflags;
+ BOOL lazy;
+} apd_data_t;
+
+static const WCHAR backslashW[] = {'\\',0};
+static const WCHAR configuration_fileW[] = {'C','o','n','f','i','g','u','r','a','t','i','o','n',' ','F','i','l','e',0};
+static const WCHAR datatypeW[] = {'D','a','t','a','t','y','p','e',0};
+static const WCHAR data_fileW[] = {'D','a','t','a',' ','F','i','l','e',0};
+static const WCHAR dependent_filesW[] = {'D','e','p','e','n','d','e','n','t',' ','F','i','l','e','s',0};
+static const WCHAR driverW[] = {'D','r','i','v','e','r',0};
+static const WCHAR emptyW[] = {0};
+static const WCHAR fmt_driversW[] = { 'S','y','s','t','e','m','\\',
+ 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
+ 'c','o','n','t','r','o','l','\\',
+ 'P','r','i','n','t','\\',
+ 'E','n','v','i','r','o','n','m','e','n','t','s','\\',
+ '%','s','\\','D','r','i','v','e','r','s','%','s',0 };
+static const WCHAR monitorW[] = {'M','o','n','i','t','o','r',0};
+static const WCHAR previous_namesW[] = {'P','r','e','v','i','o','u','s',' ','N','a','m','e','s',0};
+
+static const WCHAR versionW[] = {'V','e','r','s','i','o','n',0};
+
+static const WCHAR spoolW[] = {'\\','s','p','o','o','l',0};
+static const WCHAR driversW[] = {'\\','d','r','i','v','e','r','s','\\',0};
+static const WCHAR ia64_envnameW[] = {'W','i','n','d','o','w','s',' ','I','A','6','4',0};
+static const WCHAR ia64_subdirW[] = {'i','a','6','4',0};
+static const WCHAR version3_regpathW[] = {'\\','V','e','r','s','i','o','n','-','3',0};
+static const WCHAR version3_subdirW[] = {'\\','3',0};
+static const WCHAR version0_regpathW[] = {'\\','V','e','r','s','i','o','n','-','0',0};
+static const WCHAR version0_subdirW[] = {'\\','0',0};
+static const WCHAR help_fileW[] = {'H','e','l','p',' ','F','i','l','e',0};
+static const WCHAR x64_envnameW[] = {'W','i','n','d','o','w','s',' ','x','6','4',0};
+static const WCHAR x64_subdirW[] = {'x','6','4',0};
+static const WCHAR x86_envnameW[] = {'W','i','n','d','o','w','s',' ','N','T',' ','x','8','6',0};
+static const WCHAR x86_subdirW[] = {'w','3','2','x','8','6',0};
+static const WCHAR win40_envnameW[] = {'W','i','n','d','o','w','s',' ','4','.','0',0};
+static const WCHAR win40_subdirW[] = {'w','i','n','4','0',0};
+
+static PRINTENV_T env_ia64 = {ia64_envnameW, ia64_subdirW, 3, version3_regpathW, version3_subdirW};
+
+static PRINTENV_T env_x86 = {x86_envnameW, x86_subdirW, 3, version3_regpathW, version3_subdirW};
+
+static PRINTENV_T env_x64 = {x64_envnameW, x64_subdirW, 3, version3_regpathW, version3_subdirW};
+
+static PRINTENV_T env_win40 = {win40_envnameW, win40_subdirW, 0, version0_regpathW, version0_subdirW};
+
+static PPRINTENV_T all_printenv[] = {&env_x86, &env_x64, &env_ia64, &env_win40};
+
+static const DWORD di_sizeof[] = {0, sizeof(DRIVER_INFO_1W), sizeof(DRIVER_INFO_2W),
+ sizeof(DRIVER_INFO_3W), sizeof(DRIVER_INFO_4W),
+ sizeof(DRIVER_INFO_5W), sizeof(DRIVER_INFO_6W),
+ 0, sizeof(DRIVER_INFO_8W)};
+
+static WCHAR wszScratchPad[MAX_PATH] = L"";
+
static WCHAR wszLocalSplFile[MAX_PATH] = L"";
static WCHAR wszPrintUiFile[MAX_PATH] = L"";
+static WCHAR wszDriverPath[MAX_PATH] = L"";
-static BOOL
-DoInitPrinterDriversInternal(void)
+BOOL
+InitializePrinterDrivers(VOID)
{
WCHAR szSysDir[MAX_PATH];
+ DWORD cbBuf;
if (wszLocalSplFile[0] && wszPrintUiFile[0])
return TRUE;
StringCbCopyW(wszPrintUiFile, sizeof(wszPrintUiFile), szSysDir);
StringCbCatW(wszPrintUiFile, sizeof(wszPrintUiFile), L"\\printui.dll");
+ if (!LocalGetPrinterDriverDirectory( NULL, (PWSTR)wszCurrentEnvironment, 1, (PBYTE)szSysDir, cbBuf, &cbBuf ) )
+ {
+ ERR("LocalGetPrinterDriverDirectory failed\n");
+ return FALSE;
+ }
+
+ StringCbCopyW(wszDriverPath, sizeof(wszDriverPath), szSysDir);
+ StringCbCatW(wszDriverPath, sizeof(wszDriverPath), version3_subdirW);
+ StringCbCatW(wszDriverPath, sizeof(wszDriverPath), backslashW);
+
+ // HAX! need to get it from the Reg Key L"Driver"!
+ StringCbCatW(wszDriverPath, sizeof(wszDriverPath), L"UniDrv.dll");
+
+ FIXME("DriverPath : %S\n",wszDriverPath);
+
return TRUE;
}
MAXDWORD
};
+static DWORD dwDriverInfo6Offsets[] = {
+ FIELD_OFFSET(DRIVER_INFO_6W, pName),
+ FIELD_OFFSET(DRIVER_INFO_6W, pEnvironment),
+ FIELD_OFFSET(DRIVER_INFO_6W, pDriverPath),
+ FIELD_OFFSET(DRIVER_INFO_6W, pDataFile),
+ FIELD_OFFSET(DRIVER_INFO_6W, pConfigFile),
+ FIELD_OFFSET(DRIVER_INFO_6W, pHelpFile),
+ FIELD_OFFSET(DRIVER_INFO_6W, pDependentFiles),
+ FIELD_OFFSET(DRIVER_INFO_6W, pMonitorName),
+ FIELD_OFFSET(DRIVER_INFO_6W, pDefaultDataType),
+ FIELD_OFFSET(DRIVER_INFO_6W, pszzPreviousNames),
+ FIELD_OFFSET(DRIVER_INFO_6W, pszMfgName),
+ FIELD_OFFSET(DRIVER_INFO_6W, pszOEMUrl),
+ FIELD_OFFSET(DRIVER_INFO_6W, pszHardwareID),
+ FIELD_OFFSET(DRIVER_INFO_6W, pszProvider),
+ MAXDWORD
+};
+
+static DWORD dwDriverInfo8Offsets[] = {
+ FIELD_OFFSET(DRIVER_INFO_8W, pName),
+ FIELD_OFFSET(DRIVER_INFO_8W, pEnvironment),
+ FIELD_OFFSET(DRIVER_INFO_8W, pDriverPath),
+ FIELD_OFFSET(DRIVER_INFO_8W, pDataFile),
+ FIELD_OFFSET(DRIVER_INFO_8W, pConfigFile),
+ FIELD_OFFSET(DRIVER_INFO_8W, pHelpFile),
+ FIELD_OFFSET(DRIVER_INFO_8W, pDependentFiles),
+ FIELD_OFFSET(DRIVER_INFO_8W, pMonitorName),
+ FIELD_OFFSET(DRIVER_INFO_8W, pDefaultDataType),
+ FIELD_OFFSET(DRIVER_INFO_8W, pszzPreviousNames),
+ FIELD_OFFSET(DRIVER_INFO_8W, pszMfgName),
+ FIELD_OFFSET(DRIVER_INFO_8W, pszOEMUrl),
+ FIELD_OFFSET(DRIVER_INFO_8W, pszHardwareID),
+ FIELD_OFFSET(DRIVER_INFO_8W, pszProvider),
+ FIELD_OFFSET(DRIVER_INFO_8W, pszPrintProcessor),
+ FIELD_OFFSET(DRIVER_INFO_8W, pszVendorSetup),
+ FIELD_OFFSET(DRIVER_INFO_8W, pszzColorProfiles),
+ FIELD_OFFSET(DRIVER_INFO_8W, pszInfPath),
+ FIELD_OFFSET(DRIVER_INFO_8W, pszzCoreDriverDependencies),
+ MAXDWORD
+};
+
static void
ToMultiSz(LPWSTR pString)
{
}
}
-
static void
-_LocalGetPrinterDriverLevel1(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_1W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
+_LocalGetPrinterDriverLevel1(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_1W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
{
DWORD n;
PCWSTR pwszStrings[1];
/* This value is only here to send something, I have not verified if it is actually correct */
- pwszStrings[0] = pHandle->pPrinter->pwszPrinterDriver;
+ pwszStrings[0] = pPrinter->pwszPrinterDriver;
// Calculate the string lengths.
if (!ppDriverInfo)
}
static void
-_LocalGetPrinterDriverLevel2(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_2W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
+_LocalGetPrinterDriverLevel2(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_2W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
{
DWORD n;
PCWSTR pwszStrings[5];
- pwszStrings[0] = pHandle->pPrinter->pwszPrinterDriver; // pName
+ pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName
pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
- pwszStrings[2] = wszLocalSplFile; // pDriverPath
+ pwszStrings[2] = wszDriverPath; // pDriverPath
pwszStrings[3] = wszLocalSplFile; // pDataFile
- pwszStrings[4] = wszLocalSplFile; // pConfigFile
+ pwszStrings[4] = wszPrintUiFile; // pConfigFile
// Calculate the string lengths.
if (!ppDriverInfo)
{
for (n = 0; n < _countof(pwszStrings); ++n)
{
- *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
+ if (pwszStrings[n])
+ {
+ *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
+ }
}
*pcbNeeded += sizeof(DRIVER_INFO_2W);
}
static void
-_LocalGetPrinterDriverLevel3(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_3W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
+_LocalGetPrinterDriverLevel3(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_3W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
{
DWORD n;
PCWSTR pwszStrings[9];
- pwszStrings[0] = pHandle->pPrinter->pwszPrinterDriver; // pName
+ pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName
pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
- pwszStrings[2] = wszLocalSplFile; // pDriverPath
+ pwszStrings[2] = wszDriverPath; // pDriverPath
pwszStrings[3] = wszLocalSplFile; // pDataFile
pwszStrings[4] = wszPrintUiFile; // pConfigFile
pwszStrings[5] = L""; // pHelpFile
pwszStrings[6] = L"localspl.dll|printui.dll|"; // pDependentFiles, | is separator and terminator!
- pwszStrings[7] = NULL; // pMonitorName
- pwszStrings[8] = NULL; // pDefaultDataType
+ pwszStrings[7] = NULL;
+ if (pPrinter->pPort && pPrinter->pPort->pPrintMonitor)
+ {
+ pwszStrings[7] = pPrinter->pPort->pPrintMonitor->pwszName;
+ }
+ pwszStrings[8] = pPrinter->pwszDefaultDatatype;
// Calculate the string lengths.
}
static void
-_LocalGetPrinterDriverLevel4(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_4W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
+_LocalGetPrinterDriverLevel4(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_4W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
{
DWORD n;
PCWSTR pwszStrings[10];
- pwszStrings[0] = pHandle->pPrinter->pwszPrinterDriver; // pName
+ pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName
pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
- pwszStrings[2] = wszLocalSplFile; // pDriverPath
+ pwszStrings[2] = wszDriverPath; // pDriverPath
pwszStrings[3] = wszLocalSplFile; // pDataFile
pwszStrings[4] = wszPrintUiFile; // pConfigFile
pwszStrings[5] = L""; // pHelpFile
pwszStrings[6] = L"localspl.dll|printui.dll|"; // pDependentFiles, | is separator and terminator!
- pwszStrings[7] = NULL; // pMonitorName
- pwszStrings[8] = NULL; // pDefaultDataType
- pwszStrings[9] = NULL; // pszzPreviousNames
+ pwszStrings[7] = NULL;
+ if (pPrinter->pPort && pPrinter->pPort->pPrintMonitor)
+ {
+ pwszStrings[7] = pPrinter->pPort->pPrintMonitor->pwszName;
+ }
+ pwszStrings[8] = pPrinter->pwszDefaultDatatype;
+ pwszStrings[9] = NULL; // pszzPreviousNames
// Calculate the string lengths.
if (!ppDriverInfo)
}
static void
-_LocalGetPrinterDriverLevel5(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_5W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
+_LocalGetPrinterDriverLevel5(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_5W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
{
DWORD n;
PCWSTR pwszStrings[5];
- pwszStrings[0] = pHandle->pPrinter->pwszPrinterDriver; // pName
+ pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName
pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
- pwszStrings[2] = wszLocalSplFile; // pDriverPath UniDrv.dll
+ pwszStrings[2] = wszDriverPath; // pDriverPath UniDrv.dll
pwszStrings[3] = wszLocalSplFile; // pDataFile.ppd
pwszStrings[4] = wszPrintUiFile; // pConfigFile UniDrvUI.dll
(*ppDriverInfo)++;
}
+
+static void
+_LocalGetPrinterDriverLevel6(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_6W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
+{
+ DWORD n;
+ PCWSTR pwszStrings[14];
+
+ StringCbCopyW(wszScratchPad, sizeof(wszPrintProviderInfo[1]), wszPrintProviderInfo[1]); // Provider Name
+
+ pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName
+ pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
+ pwszStrings[2] = wszDriverPath; // pDriverPath
+ pwszStrings[3] = wszLocalSplFile; // pDataFile
+ pwszStrings[4] = wszPrintUiFile; // pConfigFile
+ pwszStrings[5] = L""; // pHelpFile
+ pwszStrings[6] = L"localspl.dll|printui.dll|"; // pDependentFiles, | is separator and terminator!
+ pwszStrings[7] = NULL;
+ if (pPrinter->pPort && pPrinter->pPort->pPrintMonitor)
+ {
+ pwszStrings[7] = pPrinter->pPort->pPrintMonitor->pwszName;
+ }
+ pwszStrings[8] = pPrinter->pwszDefaultDatatype;
+ pwszStrings[9] = NULL; // pszzPreviousNames
+ pwszStrings[10] = NULL; // pszMfgName
+ pwszStrings[11] = NULL; // pszOEMUrl
+ pwszStrings[12] = NULL; // pszHardwareID
+ pwszStrings[13] = wszScratchPad;
+
+ // Calculate the string lengths.
+ if (!ppDriverInfo)
+ {
+ for (n = 0; n < _countof(pwszStrings); ++n)
+ {
+ if (pwszStrings[n])
+ {
+ *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
+ }
+ }
+
+ *pcbNeeded += sizeof(DRIVER_INFO_6W);
+ return;
+ }
+
+ (*ppDriverInfo)->cVersion = 3;
+
+ // Finally copy the structure and advance to the next one in the output buffer.
+ *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo6Offsets, *ppDriverInfoEnd);
+ ToMultiSz((*ppDriverInfo)->pDependentFiles);
+ (*ppDriverInfo)++;
+}
+
+static void
+_LocalGetPrinterDriverLevel8(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_8W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
+{
+ DWORD n;
+ PCWSTR pwszStrings[19];
+
+ StringCbCopyW(wszScratchPad, sizeof(wszPrintProviderInfo[1]), wszPrintProviderInfo[1]); // Provider Name
+
+ pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName
+ pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
+ pwszStrings[2] = wszDriverPath; // pDriverPath
+ pwszStrings[3] = wszLocalSplFile; // pDataFile
+ pwszStrings[4] = wszPrintUiFile; // pConfigFile
+ pwszStrings[5] = L""; // pHelpFile
+ pwszStrings[6] = L"localspl.dll|printui.dll|"; // pDependentFiles, | is separator and terminator!
+ pwszStrings[7] = NULL;
+ if (pPrinter->pPort && pPrinter->pPort->pPrintMonitor)
+ {
+ pwszStrings[7] = pPrinter->pPort->pPrintMonitor->pwszName;
+ }
+ pwszStrings[8] = pPrinter->pwszDefaultDatatype;
+ pwszStrings[9] = NULL; // pszzPreviousNames
+ pwszStrings[10] = NULL; // pszMfgName
+ pwszStrings[11] = NULL; // pszOEMUrl
+ pwszStrings[12] = NULL; // pszHardwareID
+ pwszStrings[13] = wszScratchPad;
+ pwszStrings[14] = NULL;
+ if ( pPrinter->pPrintProcessor )
+ {
+ pwszStrings[14] = pPrinter->pPrintProcessor->pwszName;
+ }
+ pwszStrings[15] = NULL; // pszVendorSetup
+ pwszStrings[16] = NULL; // pszzColorProfiles
+ pwszStrings[17] = NULL; // pszInfPath
+ pwszStrings[18] = NULL; // pszzCoreDriverDependencies
+
+ // Calculate the string lengths.
+ if (!ppDriverInfo)
+ {
+ for (n = 0; n < _countof(pwszStrings); ++n)
+ {
+ if (pwszStrings[n])
+ {
+ *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
+ }
+ }
+
+ *pcbNeeded += sizeof(DRIVER_INFO_8W);
+ return;
+ }
+
+ (*ppDriverInfo)->cVersion = 3;
+
+ // Finally copy the structure and advance to the next one in the output buffer.
+ *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo8Offsets, *ppDriverInfoEnd);
+ ToMultiSz((*ppDriverInfo)->pDependentFiles);
+ (*ppDriverInfo)++;
+}
+
+typedef void (*PLocalPrinterDriverLevelFunc)(PLOCAL_PRINTER, PVOID, PBYTE*, PDWORD);
+
+static const PLocalPrinterDriverLevelFunc pfnPrinterDriverLevels[] = {
+ NULL,
+ (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel1,
+ (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel2,
+ (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel3,
+ (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel4,
+ (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel5,
+ (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel6,
+ NULL,
+ (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel8
+};
+
BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
{
DWORD dwErrorCode;
TRACE("LocalGetPrinterDriver(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
- DoInitPrinterDriversInternal();
-
// Check if this is a printer handle.
pHandle = (PLOCAL_HANDLE)hPrinter;
if (pHandle->HandleType != HandleType_Printer)
pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle;
- // Only support 5 levels for now
- if (Level > 5)
+ // Only support 8 levels and not 7
+ if (Level < 1 || Level == 7 || Level > 8)
{
// The caller supplied an invalid level.
dwErrorCode = ERROR_INVALID_LEVEL;
// Count the required buffer size.
*pcbNeeded = 0;
- if (Level == 1)
- _LocalGetPrinterDriverLevel1(pPrinterHandle, NULL, NULL, pcbNeeded);
- else if (Level == 2)
- _LocalGetPrinterDriverLevel2(pPrinterHandle, NULL, NULL, pcbNeeded);
- else if (Level == 3)
- _LocalGetPrinterDriverLevel3(pPrinterHandle, NULL, NULL, pcbNeeded);
- else if (Level == 4)
- _LocalGetPrinterDriverLevel4(pPrinterHandle, NULL, NULL, pcbNeeded);
- else if (Level == 5)
- _LocalGetPrinterDriverLevel5(pPrinterHandle, NULL, NULL, pcbNeeded);
+ pfnPrinterDriverLevels[Level](pPrinterHandle->pPrinter, 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 = &pDriverInfo[*pcbNeeded];
- if (Level == 1)
- _LocalGetPrinterDriverLevel1(pPrinterHandle, (PDRIVER_INFO_1W*)&pDriverInfo, &pEnd, NULL);
- else if (Level == 2)
- _LocalGetPrinterDriverLevel2(pPrinterHandle, (PDRIVER_INFO_2W*)&pDriverInfo, &pEnd, NULL);
- else if (Level == 3)
- _LocalGetPrinterDriverLevel3(pPrinterHandle, (PDRIVER_INFO_3W*)&pDriverInfo, &pEnd, NULL);
- else if (Level == 4)
- _LocalGetPrinterDriverLevel4(pPrinterHandle, (PDRIVER_INFO_4W*)&pDriverInfo, &pEnd, NULL);
- else if (Level == 5)
- _LocalGetPrinterDriverLevel5(pPrinterHandle, (PDRIVER_INFO_5W*)&pDriverInfo, &pEnd, NULL);
+ pfnPrinterDriverLevels[Level](pPrinterHandle->pPrinter, &pDriverInfo, &pEnd, NULL);
dwErrorCode = ERROR_SUCCESS;
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
+
+BOOL WINAPI LocalGetPrinterDriverEx(
+ HANDLE hPrinter,
+ LPWSTR pEnvironment,
+ DWORD Level,
+ LPBYTE pDriverInfo,
+ DWORD cbBuf,
+ LPDWORD pcbNeeded,
+ DWORD dwClientMajorVersion,
+ DWORD dwClientMinorVersion,
+ PDWORD pdwServerMajorVersion,
+ PDWORD pdwServerMinorVersion )
+{
+ FIXME("LocalGetPrinterDriverEx(%p, %lu, %lu, %p, %lu, %p, %lu, %lu, %p, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, dwClientMajorVersion, dwClientMinorVersion, pdwServerMajorVersion, pdwServerMinorVersion);
+ //// HACK-plement
+ return LocalGetPrinterDriver( hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded );
+}
+
+BOOL WINAPI
+LocalEnumPrinterDrivers(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
+{
+ DWORD dwErrorCode;
+ PSKIPLIST_NODE pNode;
+ PBYTE pEnd;
+ PLOCAL_PRINTER pPrinter;
+
+ FIXME("LocalEnumPrinterDrivers(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned);
+
+ // Only support 8 levels and not 7
+ if (Level < 1 || Level == 7 || Level > 8)
+ {
+ // The caller supplied an invalid level.
+ dwErrorCode = ERROR_INVALID_LEVEL;
+ goto Cleanup;
+ }
+
+ // Count the required buffer size.
+ *pcbNeeded = 0;
+
+ // Count the required buffer size and the number of printers.
+ for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
+ {
+ pPrinter = (PLOCAL_PRINTER)pNode->Element;
+
+ pfnPrinterDriverLevels[Level](pPrinter, NULL, NULL, pcbNeeded);
+ }
+
+ // Check if the supplied buffer is large enough.
+ if (cbBuf < *pcbNeeded)
+ {
+ dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
+ goto Cleanup;
+ }
+
+ // Copy over the Printer information.
+ pEnd = &pDriverInfo[*pcbNeeded];
+
+ for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
+ {
+ pPrinter = (PLOCAL_PRINTER)pNode->Element;
+
+ pfnPrinterDriverLevels[Level](pPrinter, &pDriverInfo, &pEnd, NULL);
+ (*pcReturned)++;
+ }
+
+ dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+ SetLastError(dwErrorCode);
+ return (dwErrorCode == ERROR_SUCCESS);
+}
+
+/******************************************************************
+ * Return the number of bytes for an multi_sz string.
+ * The result includes all \0s
+ * (specifically the extra \0, that is needed as multi_sz terminator).
+ */
+static int multi_sz_lenW(const WCHAR *str)
+{
+ const WCHAR *ptr = str;
+ if (!str) return 0;
+ do
+ {
+ ptr += lstrlenW(ptr) + 1;
+ } while (*ptr);
+
+ return (ptr - str + 1) * sizeof(WCHAR);
+}
+
+
+/******************************************************************
+ * validate_envW [internal]
+ *
+ * validate the user-supplied printing-environment
+ *
+ * PARAMS
+ * env [I] PTR to Environment-String or NULL
+ *
+ * RETURNS
+ * Success: PTR to printenv_t
+ * Failure: NULL and ERROR_INVALID_ENVIRONMENT
+ *
+ * NOTES
+ * An empty string is handled the same way as NULL.
+ *
+ */
+PPRINTENV_T validate_envW(LPCWSTR env)
+{
+ PPRINTENV_T result = NULL;
+ unsigned int i;
+
+ TRACE("(%s)\n", debugstr_w(env));
+ if (env && env[0])
+ {
+ for (i = 0; i < ARRAYSIZE(all_printenv); i++)
+ {
+ if (lstrcmpiW(env, all_printenv[i]->envname) == 0)
+ {
+ result = all_printenv[i];
+ break;
+ }
+ }
+ if (result == NULL)
+ {
+ FIXME("unsupported Environment: %s\n", debugstr_w(env));
+ SetLastError(ERROR_INVALID_ENVIRONMENT);
+ }
+ /* on win9x, only "Windows 4.0" is allowed, but we ignore this */
+ }
+ else
+ {
+ result = (GetVersion() & 0x80000000) ? &env_win40 : &env_x86;
+ }
+
+ TRACE("=> using %p: %s\n", result, debugstr_w(result ? result->envname : NULL));
+ return result;
+}
+
+/*****************************************************************************
+ * open_driver_reg [internal]
+ *
+ * opens the registry for the printer drivers depending on the given input
+ * variable pEnvironment
+ *
+ * RETURNS:
+ * Success: the opened hkey
+ * Failure: NULL
+ */
+HKEY open_driver_reg(LPCWSTR pEnvironment)
+{
+ HKEY retval = NULL;
+ LPWSTR buffer;
+ const PRINTENV_T * env;
+
+ TRACE("(%s)\n", debugstr_w(pEnvironment));
+
+ env = validate_envW(pEnvironment);
+ if (!env) return NULL;
+
+ buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(fmt_driversW) +
+ (lstrlenW(env->envname) + lstrlenW(env->versionregpath)) * sizeof(WCHAR));
+
+ if (buffer)
+ {
+ wsprintfW(buffer, fmt_driversW, env->envname, env->versionregpath);
+ RegCreateKeyW(HKEY_LOCAL_MACHINE, buffer, &retval);
+ HeapFree(GetProcessHeap(), 0, buffer);
+ }
+ return retval;
+}
+
+
+/******************************************************************************
+ * LocalGetPrintProcessorDirectory [exported through PRINTPROVIDOR]
+ *
+ * Return the PATH for the Print-Processors
+ *
+ * PARAMS
+ * pName [I] Servername or NULL (this computer)
+ * pEnvironment [I] Printing-Environment or NULL (Default)
+ * level [I] Structure-Level (must be 1)
+ * pPPInfo [O] PTR to Buffer that receives the Result
+ * cbBuf [I] Size of Buffer at pPPInfo
+ * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPPInfo
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE and in pcbNeeded the Bytes required for pPPInfo, if cbBuf is too small
+ *
+ * Native Values returned in pPPInfo on Success for this computer:
+ *| NT(Windows x64): "%winsysdir%\\spool\\PRTPROCS\\x64"
+ *| NT(Windows NT x86): "%winsysdir%\\spool\\PRTPROCS\\w32x86"
+ *| NT(Windows 4.0): "%winsysdir%\\spool\\PRTPROCS\\win40"
+ *
+ * "%winsysdir%" is the Value from GetSystemDirectoryW()
+ *
+ */
+BOOL WINAPI LocalGetPrinterDriverDirectory(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverDirectory, DWORD cbBuf, PDWORD pcbNeeded)
+{
+ DWORD needed;
+ const PRINTENV_T * env = NULL;
+ WCHAR * const dir = (WCHAR *)pDriverDirectory;
+
+ FIXME("LocalGetPrinterDriverDirectory(%S, %S, %lu, %p, %lu, %p)\n", pName, pEnvironment, Level, pDriverDirectory, cbBuf, pcbNeeded);
+
+ if (pName != NULL && pName[0])
+ {
+ FIXME("server %s not supported\n", debugstr_w(pName));
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ env = validate_envW(pEnvironment);
+ if (!env) return FALSE; /* pEnvironment invalid or unsupported */
+
+ /* GetSystemDirectoryW returns number of WCHAR including the '\0' */
+ needed = GetSystemDirectoryW(NULL, 0);
+ /* add the Size for the Subdirectories */
+ needed += lstrlenW(spoolW);
+ needed += lstrlenW(driversW);
+ needed += lstrlenW(env->subdir);
+ needed *= sizeof(WCHAR); /* return-value is size in Bytes */
+
+ *pcbNeeded = needed;
+
+ if (needed > cbBuf)
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+ }
+
+ if (dir == NULL)
+ {
+ /* ERROR_INVALID_USER_BUFFER is NT, ERROR_INVALID_PARAMETER is win9x */
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ return FALSE;
+ }
+
+ GetSystemDirectoryW( dir, cbBuf / sizeof(WCHAR) );
+ /* add the Subdirectories */
+ lstrcatW( dir, spoolW );
+ CreateDirectoryW( dir, NULL );
+ lstrcatW( dir, driversW );
+ CreateDirectoryW( dir, NULL );
+ lstrcatW( dir, env->subdir );
+ CreateDirectoryW( dir, NULL );
+
+ FIXME( "=> %s\n", debugstr_w( dir ) );
+ return TRUE;
+}
+
+/******************************************************************
+ * apd_copyfile [internal]
+ *
+ * Copy a file from the driverdirectory to the versioned directory
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ */
+static BOOL apd_copyfile( WCHAR *pathname, WCHAR *file_part, apd_data_t *apd )
+{
+ WCHAR *srcname;
+ BOOL res;
+
+ apd->src[apd->srclen] = '\0';
+ apd->dst[apd->dstlen] = '\0';
+
+ if (!pathname || !pathname[0]) {
+ /* nothing to copy */
+ return TRUE;
+ }
+
+ if (apd->copyflags & APD_COPY_FROM_DIRECTORY)
+ srcname = pathname;
+ else
+ {
+ srcname = apd->src;
+ lstrcatW( srcname, file_part );
+ }
+ lstrcatW( apd->dst, file_part );
+
+ FIXME("%s => %s\n", debugstr_w(srcname), debugstr_w(apd->dst));
+
+ /* FIXME: handle APD_COPY_NEW_FILES */
+ res = CopyFileW(srcname, apd->dst, FALSE);
+ FIXME("got %d with %u\n", res, GetLastError());
+
+ return apd->lazy || res;
+}
+
+/******************************************************************
+ * driver_load [internal]
+ *
+ * load a driver user interface dll
+ *
+ * On failure, NULL is returned
+ *
+ */
+
+static HMODULE driver_load(const PRINTENV_T * env, LPWSTR dllname)
+{
+ WCHAR fullname[MAX_PATH];
+ HMODULE hui;
+ DWORD len;
+
+ FIXME("(%p, %s)\n", env, debugstr_w(dllname));
+
+ /* build the driverdir */
+ len = sizeof(fullname) - (lstrlenW(env->versionsubdir) + 1 + lstrlenW(dllname) + 1) * sizeof(WCHAR);
+
+ if (!LocalGetPrinterDriverDirectory(NULL, (LPWSTR) env->envname, 1, (LPBYTE) fullname, len, &len))
+ {
+ /* Should never fail */
+ SetLastError(ERROR_BUFFER_OVERFLOW);
+ return NULL;
+ }
+
+ lstrcatW(fullname, env->versionsubdir);
+ lstrcatW(fullname, backslashW);
+ lstrcatW(fullname, dllname);
+
+ hui = LoadLibraryW(fullname);
+ FIXME("%p: LoadLibrary(%s) %d\n", hui, debugstr_w(fullname), GetLastError());
+
+ return hui;
+}
+
+static inline WCHAR *get_file_part( WCHAR *name )
+{
+ WCHAR *ptr = wcsrchr( name, '\\' );
+ if (ptr) return ptr + 1;
+ return name;
+}
+
+/******************************************************************************
+ * myAddPrinterDriverEx [internal]
+ *
+ * Install a Printer Driver with the Option to upgrade / downgrade the Files
+ * and a special mode with lazy error checking.
+ *
+ */
+BOOL myAddPrinterDriverEx(DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags, BOOL lazy)
+{
+ const PRINTENV_T *env;
+ apd_data_t apd;
+ DRIVER_INFO_8W di;
+ BOOL (WINAPI *pDrvDriverEvent)(DWORD, DWORD, LPBYTE, LPARAM);
+ HMODULE hui;
+ WCHAR *file;
+ HKEY hroot;
+ HKEY hdrv;
+ DWORD disposition;
+ DWORD len;
+ LONG lres;
+ BOOL res;
+
+ /* we need to set all entries in the Registry, independent from the Level of
+ DRIVER_INFO, that the caller supplied */
+
+ ZeroMemory(&di, sizeof(di));
+ if (pDriverInfo && (level < ARRAYSIZE(di_sizeof)))
+ {
+ memcpy(&di, pDriverInfo, di_sizeof[level]);
+ }
+
+ /* dump the most used infos */
+ FIXME("%p: .cVersion : 0x%x/%d\n", pDriverInfo, di.cVersion, di.cVersion);
+ FIXME("%p: .pName : %s\n", di.pName, debugstr_w(di.pName));
+ FIXME("%p: .pEnvironment: %s\n", di.pEnvironment, debugstr_w(di.pEnvironment));
+ FIXME("%p: .pDriverPath : %s\n", di.pDriverPath, debugstr_w(di.pDriverPath));
+ FIXME("%p: .pDataFile : %s\n", di.pDataFile, debugstr_w(di.pDataFile));
+ FIXME("%p: .pConfigFile : %s\n", di.pConfigFile, debugstr_w(di.pConfigFile));
+ FIXME("%p: .pHelpFile : %s\n", di.pHelpFile, debugstr_w(di.pHelpFile));
+ /* dump only the first of the additional Files */
+ FIXME("%p: .pDependentFiles: %s\n", di.pDependentFiles, debugstr_w(di.pDependentFiles));
+
+
+ /* check environment */
+ env = validate_envW(di.pEnvironment);
+ if (env == NULL) return FALSE; /* ERROR_INVALID_ENVIRONMENT */
+
+ /* fill the copy-data / get the driverdir */
+ len = sizeof(apd.src) - sizeof(version3_subdirW) - sizeof(WCHAR);
+ if (!LocalGetPrinterDriverDirectory(NULL, (LPWSTR) env->envname, 1, (LPBYTE) apd.src, len, &len))
+ {
+ /* Should never fail */
+ return FALSE;
+ }
+ memcpy(apd.dst, apd.src, len);
+ lstrcatW(apd.src, backslashW);
+ apd.srclen = lstrlenW(apd.src);
+ lstrcatW(apd.dst, env->versionsubdir);
+ lstrcatW(apd.dst, backslashW);
+ apd.dstlen = lstrlenW(apd.dst);
+ apd.copyflags = dwFileCopyFlags;
+ apd.lazy = lazy;
+ CreateDirectoryW(apd.src, NULL);
+ CreateDirectoryW(apd.dst, NULL);
+
+ hroot = open_driver_reg(env->envname);
+ if (!hroot)
+ {
+ ERR("Can't create Drivers key\n");
+ return FALSE;
+ }
+
+ /* Fill the Registry for the Driver */
+ if ((lres = RegCreateKeyExW(hroot, di.pName, 0, NULL, REG_OPTION_NON_VOLATILE,
+ KEY_WRITE | KEY_QUERY_VALUE, NULL,
+ &hdrv, &disposition)) != ERROR_SUCCESS)
+ {
+ ERR("can't create driver %s: %u\n", debugstr_w(di.pName), lres);
+ RegCloseKey(hroot);
+ SetLastError(lres);
+ return FALSE;
+ }
+ RegCloseKey(hroot);
+
+ /* Verified with the Adobe PS Driver, that w2k does not use di.Version */
+ RegSetValueExW(hdrv, versionW, 0, REG_DWORD, (const BYTE*) &env->driverversion,
+ sizeof(DWORD));
+
+ file = get_file_part( di.pDriverPath );
+ RegSetValueExW( hdrv, driverW, 0, REG_SZ, (LPBYTE)file, (lstrlenW( file ) + 1) * sizeof(WCHAR) );
+ apd_copyfile( di.pDriverPath, file, &apd );
+
+ file = get_file_part( di.pDataFile );
+ RegSetValueExW( hdrv, data_fileW, 0, REG_SZ, (LPBYTE)file, (lstrlenW( file ) + 1) * sizeof(WCHAR) );
+ apd_copyfile( di.pDataFile, file, &apd );
+
+ file = get_file_part( di.pConfigFile );
+ RegSetValueExW( hdrv, configuration_fileW, 0, REG_SZ, (LPBYTE)file, (lstrlenW( file ) + 1) * sizeof(WCHAR) );
+ apd_copyfile( di.pConfigFile, file, &apd );
+
+ /* settings for level 3 */
+ if (di.pHelpFile)
+ {
+ file = get_file_part( di.pHelpFile );
+ RegSetValueExW( hdrv, help_fileW, 0, REG_SZ, (LPBYTE)file, (lstrlenW( file ) + 1) * sizeof(WCHAR) );
+ apd_copyfile( di.pHelpFile, file, &apd );
+ }
+ else
+ RegSetValueExW( hdrv, help_fileW, 0, REG_SZ, (const BYTE*)emptyW, sizeof(emptyW) );
+
+ if (di.pDependentFiles && *di.pDependentFiles)
+ {
+ WCHAR *reg, *reg_ptr, *in_ptr;
+ reg = reg_ptr = HeapAlloc( GetProcessHeap(), 0, multi_sz_lenW( di.pDependentFiles ) );
+
+ for (in_ptr = di.pDependentFiles; *in_ptr; in_ptr += lstrlenW( in_ptr ) + 1)
+ {
+ file = get_file_part( in_ptr );
+ len = lstrlenW( file ) + 1;
+ memcpy( reg_ptr, file, len * sizeof(WCHAR) );
+ reg_ptr += len;
+ apd_copyfile( in_ptr, file, &apd );
+ }
+ *reg_ptr = 0;
+
+ RegSetValueExW( hdrv, dependent_filesW, 0, REG_MULTI_SZ, (LPBYTE)reg, (reg_ptr - reg + 1) * sizeof(WCHAR) );
+ HeapFree( GetProcessHeap(), 0, reg );
+ }
+ else
+ RegSetValueExW(hdrv, dependent_filesW, 0, REG_MULTI_SZ, (const BYTE*)emptyW, sizeof(emptyW));
+
+ /* The language-Monitor was already copied by the caller to "%SystemRoot%\system32" */
+ if (di.pMonitorName)
+ RegSetValueExW(hdrv, monitorW, 0, REG_SZ, (LPBYTE) di.pMonitorName,
+ (lstrlenW(di.pMonitorName)+1)* sizeof(WCHAR));
+ else
+ RegSetValueExW(hdrv, monitorW, 0, REG_SZ, (const BYTE*)emptyW, sizeof(emptyW));
+
+ if (di.pDefaultDataType)
+ RegSetValueExW(hdrv, datatypeW, 0, REG_SZ, (LPBYTE) di.pDefaultDataType,
+ (lstrlenW(di.pDefaultDataType)+1)* sizeof(WCHAR));
+ else
+ RegSetValueExW(hdrv, datatypeW, 0, REG_SZ, (const BYTE*)emptyW, sizeof(emptyW));
+
+ /* settings for level 4 */
+ if (di.pszzPreviousNames)
+ RegSetValueExW(hdrv, previous_namesW, 0, REG_MULTI_SZ, (LPBYTE) di.pszzPreviousNames,
+ multi_sz_lenW(di.pszzPreviousNames));
+ else
+ RegSetValueExW(hdrv, previous_namesW, 0, REG_MULTI_SZ, (const BYTE*)emptyW, sizeof(emptyW));
+
+ if (level > 5) FIXME("level %u for Driver %s is incomplete\n", level, debugstr_w(di.pName));
+
+ RegCloseKey(hdrv);
+
+ //
+ // Locate driver and send the event.
+ //
+
+ hui = driver_load(env, di.pConfigFile);
+
+ pDrvDriverEvent = (void *)GetProcAddress(hui, "DrvDriverEvent");
+
+ if (hui && pDrvDriverEvent)
+ {
+ /* Support for DrvDriverEvent is optional */
+ TRACE("DRIVER_EVENT_INITIALIZE for %s (%s)\n", debugstr_w(di.pName), debugstr_w(di.pConfigFile));
+ /* MSDN: level for DRIVER_INFO is 1 to 3 */
+ res = pDrvDriverEvent(DRIVER_EVENT_INITIALIZE, 3, (LPBYTE) &di, 0);
+ TRACE("got %d from DRIVER_EVENT_INITIALIZE\n", res);
+ }
+ FreeLibrary(hui);
+
+ FIXME("=> TRUE with %u\n", GetLastError());
+ return TRUE;
+}
+
+/******************************************************************************
+ * AddPrinterDriverEx [exported through PRINTPROVIDOR]
+ *
+ * Install a Printer Driver with the Option to upgrade / downgrade the Files
+ *
+ * PARAMS
+ * pName [I] Servername or NULL (local Computer)
+ * level [I] Level for the supplied DRIVER_INFO_*W struct
+ * pDriverInfo [I] PTR to DRIVER_INFO_*W struct with the Driver Parameter
+ * dwFileCopyFlags [I] How to Copy / Upgrade / Downgrade the needed Files
+ *
+ * RESULTS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ */
+BOOL WINAPI LocalAddPrinterDriverEx(LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags)
+{
+ LONG lres;
+
+ TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo, dwFileCopyFlags);
+
+ lres = copy_servername_from_name(pName, NULL);
+
+ if (lres)
+ {
+ FIXME("server %s not supported\n", debugstr_w(pName));
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+
+ if ((dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY) != APD_COPY_ALL_FILES)
+ {
+ TRACE("Flags 0x%x ignored (using APD_COPY_ALL_FILES)\n", dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY);
+ }
+
+ return myAddPrinterDriverEx(level, pDriverInfo, dwFileCopyFlags, TRUE);
+}
+
+BOOL WINAPI LocalAddPrinterDriver(LPWSTR pName, DWORD level, LPBYTE pDriverInfo)
+{
+ LONG lres;
+
+ TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo);
+
+ lres = copy_servername_from_name(pName, NULL);
+
+ if (lres)
+ {
+ FIXME("server %s not supported\n", debugstr_w(pName));
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+
+ // Should be APD_COPY_NEW_FILES. Cheap wine.
+
+ return myAddPrinterDriverEx(level, pDriverInfo, APD_COPY_NEW_FILES, TRUE);
+}
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
*
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);
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;
}
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!
{
// The caller supplied a non-existing Monitor name.
dwErrorCode = ERROR_INVALID_NAME;
+ ERR("OpenXcvHandle failed on Monitor name! %lu\n", dwErrorCode);
goto Failure;
}
}
{
// 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;
}
else
{
dwErrorCode = ERROR_INVALID_NAME;
+ ERR("OpenXcvHandle failed on bad name! %lu\n", dwErrorCode);
goto Failure;
}
{
// The XcvOpenPort function failed. Return its last error.
dwErrorCode = GetLastError();
+ ERR("XcvOpenPort function failed! %lu\n", dwErrorCode);
goto Failure;
}
// Return it.
*phPrinter = (HANDLE)pHandle;
+ ERR("OpenXcvHandle Success! %p\n", pXcvHandle);
return ERROR_SUCCESS;
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)
{
// "\\COMPUTERNAME\, XcvMonitor Local Port"
// ", XcvPort LPT1:"
// "\\COMPUTERNAME\, XcvPort LPT1:"
+ FIXME("OpenXcvHandle : %S\n",pwszSecondParameter);
dwErrorCode = _LocalOpenXcvHandle(pwszSecondParameter, phPrinter);
}
else
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);
static void
_LocalClosePrinterHandle(PLOCAL_PRINTER_HANDLE pPrinterHandle)
{
+ FIXME("LocalClosePrinterHandle\n");
// Terminate any started job.
if (pPrinterHandle->pJob)
FreeJob(pPrinterHandle->pJob);
{
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
- TRACE("LocalClosePrinter(%p)\n", hPrinter);
+ FIXME("LocalClosePrinter(%p)\n", hPrinter);
if (!pHandle)
{
{
_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;
}
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;
+}
--- /dev/null
+/*
+ * 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 )
+ {