[Printing] Update and Add Functions
authorJames Tabor <james.tabor@reactos.org>
Wed, 26 Aug 2020 22:12:20 +0000 (17:12 -0500)
committerJames Tabor <james.tabor@reactos.org>
Wed, 26 Aug 2020 22:12:20 +0000 (17:12 -0500)
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.

54 files changed:
modules/rostests/winetests/winspool/info.c
sdk/include/psdk/winspool.h
sdk/include/reactos/idl/winspool.idl
sdk/include/reactos/undocshell.h
win32ss/printing/base/spoolss/CMakeLists.txt
win32ss/printing/base/spoolss/forms.c [new file with mode: 0644]
win32ss/printing/base/spoolss/monitors.c
win32ss/printing/base/spoolss/ports.c
win32ss/printing/base/spoolss/printerdata.c
win32ss/printing/base/spoolss/printerdrivers.c [new file with mode: 0644]
win32ss/printing/base/spoolss/printers.c
win32ss/printing/base/spoolss/printprocessors.c
win32ss/printing/base/spoolss/printproviders.c [new file with mode: 0644]
win32ss/printing/base/spoolss/spoolss.spec
win32ss/printing/base/spoolsv/CMakeLists.txt
win32ss/printing/base/spoolsv/forms.c
win32ss/printing/base/spoolsv/monitors.c
win32ss/printing/base/spoolsv/ports.c
win32ss/printing/base/spoolsv/printerdrivers.c
win32ss/printing/base/spoolsv/printers.c
win32ss/printing/base/spoolsv/printprocessors.c
win32ss/printing/base/spoolsv/printproviders.c
win32ss/printing/base/spoolsv/rpcstubs.c
win32ss/printing/base/spoolsv/spoolsv.spec [new file with mode: 0644]
win32ss/printing/base/spoolsv/xcv.c
win32ss/printing/base/winspool/forms.c
win32ss/printing/base/winspool/jobs.c
win32ss/printing/base/winspool/monitors.c
win32ss/printing/base/winspool/ports.c
win32ss/printing/base/winspool/precomp.h
win32ss/printing/base/winspool/printerdata.c
win32ss/printing/base/winspool/printerdrivers.c
win32ss/printing/base/winspool/printers.c
win32ss/printing/base/winspool/printprocessors.c
win32ss/printing/base/winspool/utils.c
win32ss/printing/base/winspool/winspool.spec
win32ss/printing/include/marshalling/forms.h
win32ss/printing/include/marshalling/printerdrivers.h
win32ss/printing/include/spoolss.h
win32ss/printing/monitors/localmon/main.c
win32ss/printing/monitors/localmon/ports.c
win32ss/printing/monitors/localmon/precomp.h
win32ss/printing/monitors/localmon/tools.c
win32ss/printing/monitors/localmon/xcv.c
win32ss/printing/providers/localspl/CMakeLists.txt
win32ss/printing/providers/localspl/forms.c [new file with mode: 0644]
win32ss/printing/providers/localspl/main.c
win32ss/printing/providers/localspl/monitors.c
win32ss/printing/providers/localspl/ports.c
win32ss/printing/providers/localspl/precomp.h
win32ss/printing/providers/localspl/printerdrivers.c
win32ss/printing/providers/localspl/printers.c
win32ss/printing/providers/localspl/tools.c
win32ss/printing/providers/localspl/xcv.c [new file with mode: 0644]

index 475c13d..53aa67b 100644 (file)
@@ -120,22 +120,6 @@ static BOOL is_access_denied(DWORD res, DWORD lasterror)
     return FALSE;
 }
 
-static BOOL on_win9x = FALSE;
-
-static BOOL check_win9x(void)
-{
-    if (pGetPrinterW)
-    {
-        SetLastError(0xdeadbeef);
-        pGetPrinterW(NULL, 0, NULL, 0, NULL);
-        return (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED);
-    }
-    else
-    {
-        return TRUE;
-    }
-}
-
 static void find_default_printer(VOID)
 {
     static  char    buffer[DEFAULT_PRINTER_SIZE];
@@ -333,8 +317,6 @@ static void test_AddMonitor(void)
         "returned %d with %d (expected '0' with ERROR_INVALID_LEVEL)\n",
         res, GetLastError());
 
-    if (0)
-    {
     /* This test crashes win9x on vmware (works with win9x on qemu 0.8.1) */
     SetLastError(MAGIC_DEAD);
     res = AddMonitorA(NULL, 2, NULL);
@@ -344,7 +326,6 @@ static void test_AddMonitor(void)
          (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)), 
         "returned %d with %d (expected '0' with: MAGIC_DEAD or "
         "ERROR_PRIVILEGE_NOT_HELD)\n", res, GetLastError());
-    }
 
     ZeroMemory(&mi2a, sizeof(MONITOR_INFO_2A));
     SetLastError(MAGIC_DEAD);
@@ -1219,7 +1200,7 @@ static void test_EnumPrinterDrivers(void)
         }
 
         /* EnumPrinterDriversA returns the same number of bytes as EnumPrinterDriversW */
-        if (!on_win9x && pEnumPrinterDriversW)
+        if (pEnumPrinterDriversW)
         {
             DWORD double_needed;
             DWORD double_returned;
@@ -1407,15 +1388,14 @@ static void test_EnumPrintProcessors(void)
 
 
     /* failure-Codes for NULL */
-    if (0) {
-        /* this test crashes on win98se */
-        SetLastError(0xdeadbeef);
-        pcbNeeded = 0xdeadbeef;
-        pcReturned = 0xdeadbeef;
-        res = EnumPrintProcessorsA(NULL, NULL, 1, NULL, cbBuf, &pcbNeeded, &pcReturned);
-        ok( !res && (GetLastError() == ERROR_INVALID_USER_BUFFER) ,
-            "got %u with %u (expected '0' with ERROR_INVALID_USER_BUFFER)\n",
-            res, GetLastError());
+    SetLastError(0xdeadbeef);
+    pcbNeeded = 0xdeadbeef;
+    pcReturned = 0xdeadbeef;
+    res = EnumPrintProcessorsA(NULL, NULL, 1, NULL, cbBuf, &pcbNeeded, &pcReturned);
+    todo_wine {
+    ok( !res && (GetLastError() == ERROR_INVALID_USER_BUFFER) ,
+        "got %u with %u (expected '0' with ERROR_INVALID_USER_BUFFER)\n",
+        res, GetLastError());
     }
 
     SetLastError(0xdeadbeef);
@@ -1982,7 +1962,7 @@ static void test_SetDefaultPrinter(void)
     }
 
     if (!pSetDefaultPrinterA)  return;
-       /* only supported on win2k and above */
+    /* only supported on win2k and above */
 
     /* backup the original value */
     org_value[0] = '\0';
@@ -2356,7 +2336,7 @@ static void test_GetPrinter(void)
         ok(needed > 0,"not expected needed buffer size %d\n", needed);
 
         /* GetPrinterA returns the same number of bytes as GetPrinterW */
-        if (!on_win9x && !ret && pGetPrinterW && level != 6 && level != 7)
+        if (!ret && pGetPrinterW && level != 6 && level != 7)
         {
             DWORD double_needed;
             ret = pGetPrinterW(hprn, level, NULL, 0, &double_needed);
@@ -2408,9 +2388,6 @@ static void test_GetPrinterData(void)
     res = OpenPrinterA(NULL, &hprn, NULL);
     if (!res)
     {
-        /* printserver not available on win9x */
-        if (!on_win9x)
-            win_skip("Unable to open the printserver: %d\n", GetLastError());
         return;
     }
 
@@ -2593,7 +2570,7 @@ static void test_GetPrinterDriver(void)
         }
 
         /* GetPrinterDriverA returns the same number of bytes as GetPrinterDriverW */
-        if (!on_win9x && !ret && pGetPrinterDriverW)
+        if (!ret && pGetPrinterDriverW)
         {
             DWORD double_needed;
             ret = pGetPrinterDriverW(hprn, NULL, level, NULL, 0, &double_needed);
@@ -2961,7 +2938,7 @@ static void test_OpenPrinter_defaults(void)
     ret = GetJobA( printer, add_job->JobId, 2, (BYTE *)job_info, needed, &needed );
     ok( ret, "GetJobA() failed le=%d\n", GetLastError() );
 
-todo_wine
+    todo_wine
     ok( job_info->pDevMode != NULL, "got NULL DEVMODEA\n");
     if (job_info->pDevMode)
         ok( job_info->pDevMode->u1.s1.dmPaperSize == default_size, "got %d default %d\n",
@@ -3081,10 +3058,6 @@ START_TEST(info)
     pSetDefaultPrinterA = (void *) GetProcAddress(hwinspool, "SetDefaultPrinterA");
     pXcvDataW = (void *) GetProcAddress(hwinspool, "XcvDataW");
 
-    on_win9x = check_win9x();
-    if (on_win9x)
-        win_skip("Several W-functions are not available on Win9x/WinMe\n");
-
     find_default_printer();
     find_local_server();
     find_tempfile();
@@ -3101,20 +3074,10 @@ START_TEST(info)
     test_EnumForms(NULL);
     if (default_printer) test_EnumForms(default_printer);
     test_EnumMonitors();
-
-    if (!winetest_interactive)
-        skip("ROSTESTS-211: Skipping test_EnumPorts().\n");
-    else
-        test_EnumPorts();
-
+    test_EnumPorts();
     test_EnumPrinterDrivers();
     test_EnumPrinters();
-
-    if (!winetest_interactive)
-        skip("ROSTESTS-211: Skipping test_EnumPrintProcessors().\n");
-    else
-        test_EnumPrintProcessors();
-
+    test_EnumPrintProcessors();
     test_GetDefaultPrinter();
     test_GetPrinterDriverDirectory();
     test_GetPrintProcessorDirectory();
index 6c4d838..5bbbd26 100644 (file)
@@ -351,55 +351,55 @@ extern "C" {
 
 #define JOB_POSITION_UNSPECIFIED 0
 
-  typedef struct _ADDJOB_INFO_1A {
+typedef struct _ADDJOB_INFO_1A {
     LPSTR Path;
     DWORD JobId;
-  } ADDJOB_INFO_1A,*PADDJOB_INFO_1A,*LPADDJOB_INFO_1A;
+} ADDJOB_INFO_1A,*PADDJOB_INFO_1A,*LPADDJOB_INFO_1A;
 
-  typedef struct _ADDJOB_INFO_1W {
+typedef struct _ADDJOB_INFO_1W {
     LPWSTR Path;
     DWORD JobId;
-  } ADDJOB_INFO_1W,*PADDJOB_INFO_1W,*LPADDJOB_INFO_1W;
+} ADDJOB_INFO_1W,*PADDJOB_INFO_1W,*LPADDJOB_INFO_1W;
 
-  __MINGW_TYPEDEF_AW(ADDJOB_INFO_1)
-  __MINGW_TYPEDEF_AW(PADDJOB_INFO_1)
-  __MINGW_TYPEDEF_AW(LPADDJOB_INFO_1)
+__MINGW_TYPEDEF_AW(ADDJOB_INFO_1)
+__MINGW_TYPEDEF_AW(PADDJOB_INFO_1)
+__MINGW_TYPEDEF_AW(LPADDJOB_INFO_1)
 
-  typedef struct _DRIVER_INFO_1A {
+typedef struct _DRIVER_INFO_1A {
     LPSTR pName;
-  } DRIVER_INFO_1A,*PDRIVER_INFO_1A,*LPDRIVER_INFO_1A;
+} DRIVER_INFO_1A,*PDRIVER_INFO_1A,*LPDRIVER_INFO_1A;
 
-  typedef struct _DRIVER_INFO_1W {
+typedef struct _DRIVER_INFO_1W {
     LPWSTR pName;
-  } DRIVER_INFO_1W,*PDRIVER_INFO_1W,*LPDRIVER_INFO_1W;
+} DRIVER_INFO_1W,*PDRIVER_INFO_1W,*LPDRIVER_INFO_1W;
 
-  __MINGW_TYPEDEF_AW(DRIVER_INFO_1)
-  __MINGW_TYPEDEF_AW(PDRIVER_INFO_1)
-  __MINGW_TYPEDEF_AW(LPDRIVER_INFO_1)
+__MINGW_TYPEDEF_AW(DRIVER_INFO_1)
+__MINGW_TYPEDEF_AW(PDRIVER_INFO_1)
+__MINGW_TYPEDEF_AW(LPDRIVER_INFO_1)
 
-  typedef struct _DRIVER_INFO_2A {
+typedef struct _DRIVER_INFO_2A {
     DWORD cVersion;
     LPSTR pName;
     LPSTR pEnvironment;
     LPSTR pDriverPath;
     LPSTR pDataFile;
     LPSTR pConfigFile;
-  } DRIVER_INFO_2A,*PDRIVER_INFO_2A,*LPDRIVER_INFO_2A;
+} DRIVER_INFO_2A,*PDRIVER_INFO_2A,*LPDRIVER_INFO_2A;
 
-  typedef struct _DRIVER_INFO_2W {
+typedef struct _DRIVER_INFO_2W {
     DWORD cVersion;
     LPWSTR pName;
     LPWSTR pEnvironment;
     LPWSTR pDriverPath;
     LPWSTR pDataFile;
     LPWSTR pConfigFile;
-  } DRIVER_INFO_2W,*PDRIVER_INFO_2W,*LPDRIVER_INFO_2W;
+} DRIVER_INFO_2W,*PDRIVER_INFO_2W,*LPDRIVER_INFO_2W;
 
-  __MINGW_TYPEDEF_AW(DRIVER_INFO_2)
-  __MINGW_TYPEDEF_AW(PDRIVER_INFO_2)
-  __MINGW_TYPEDEF_AW(LPDRIVER_INFO_2)
+__MINGW_TYPEDEF_AW(DRIVER_INFO_2)
+__MINGW_TYPEDEF_AW(PDRIVER_INFO_2)
+__MINGW_TYPEDEF_AW(LPDRIVER_INFO_2)
 
-  typedef struct _DRIVER_INFO_3A {
+typedef struct _DRIVER_INFO_3A {
     DWORD cVersion;
     LPSTR pName;
     LPSTR pEnvironment;
@@ -410,9 +410,9 @@ extern "C" {
     LPSTR pDependentFiles;
     LPSTR pMonitorName;
     LPSTR pDefaultDataType;
-  } DRIVER_INFO_3A,*PDRIVER_INFO_3A,*LPDRIVER_INFO_3A;
+} DRIVER_INFO_3A,*PDRIVER_INFO_3A,*LPDRIVER_INFO_3A;
 
-  typedef struct _DRIVER_INFO_3W {
+typedef struct _DRIVER_INFO_3W {
     DWORD cVersion;
     LPWSTR pName;
     LPWSTR pEnvironment;
@@ -423,13 +423,13 @@ extern "C" {
     LPWSTR pDependentFiles;
     LPWSTR pMonitorName;
     LPWSTR pDefaultDataType;
-  } DRIVER_INFO_3W,*PDRIVER_INFO_3W,*LPDRIVER_INFO_3W;
+} DRIVER_INFO_3W,*PDRIVER_INFO_3W,*LPDRIVER_INFO_3W;
 
-  __MINGW_TYPEDEF_AW(DRIVER_INFO_3)
-  __MINGW_TYPEDEF_AW(PDRIVER_INFO_3)
-  __MINGW_TYPEDEF_AW(LPDRIVER_INFO_3)
+__MINGW_TYPEDEF_AW(DRIVER_INFO_3)
+__MINGW_TYPEDEF_AW(PDRIVER_INFO_3)
+__MINGW_TYPEDEF_AW(LPDRIVER_INFO_3)
 
-  typedef struct _DRIVER_INFO_4A {
+typedef struct _DRIVER_INFO_4A {
     DWORD cVersion;
     LPSTR pName;
     LPSTR pEnvironment;
@@ -441,9 +441,9 @@ extern "C" {
     LPSTR pMonitorName;
     LPSTR pDefaultDataType;
     LPSTR pszzPreviousNames;
-  } DRIVER_INFO_4A,*PDRIVER_INFO_4A,*LPDRIVER_INFO_4A;
+} DRIVER_INFO_4A,*PDRIVER_INFO_4A,*LPDRIVER_INFO_4A;
 
-  typedef struct _DRIVER_INFO_4W {
+typedef struct _DRIVER_INFO_4W {
     DWORD cVersion;
     LPWSTR pName;
     LPWSTR pEnvironment;
@@ -455,13 +455,13 @@ extern "C" {
     LPWSTR pMonitorName;
     LPWSTR pDefaultDataType;
     LPWSTR pszzPreviousNames;
-  } DRIVER_INFO_4W,*PDRIVER_INFO_4W,*LPDRIVER_INFO_4W;
+} DRIVER_INFO_4W,*PDRIVER_INFO_4W,*LPDRIVER_INFO_4W;
 
-  __MINGW_TYPEDEF_AW(DRIVER_INFO_4)
-  __MINGW_TYPEDEF_AW(PDRIVER_INFO_4)
-  __MINGW_TYPEDEF_AW(LPDRIVER_INFO_4)
+__MINGW_TYPEDEF_AW(DRIVER_INFO_4)
+__MINGW_TYPEDEF_AW(PDRIVER_INFO_4)
+__MINGW_TYPEDEF_AW(LPDRIVER_INFO_4)
 
-  typedef struct _DRIVER_INFO_5A {
+typedef struct _DRIVER_INFO_5A {
     DWORD cVersion;
     LPSTR pName;
     LPSTR pEnvironment;
@@ -471,9 +471,9 @@ extern "C" {
     DWORD dwDriverAttributes;
     DWORD dwConfigVersion;
     DWORD dwDriverVersion;
-  } DRIVER_INFO_5A,*PDRIVER_INFO_5A,*LPDRIVER_INFO_5A;
+} DRIVER_INFO_5A,*PDRIVER_INFO_5A,*LPDRIVER_INFO_5A;
 
-  typedef struct _DRIVER_INFO_5W {
+typedef struct _DRIVER_INFO_5W {
     DWORD cVersion;
     LPWSTR pName;
     LPWSTR pEnvironment;
@@ -483,13 +483,13 @@ extern "C" {
     DWORD dwDriverAttributes;
     DWORD dwConfigVersion;
     DWORD dwDriverVersion;
-  } DRIVER_INFO_5W,*PDRIVER_INFO_5W,*LPDRIVER_INFO_5W;
+} DRIVER_INFO_5W,*PDRIVER_INFO_5W,*LPDRIVER_INFO_5W;
 
-  __MINGW_TYPEDEF_AW(DRIVER_INFO_5)
-  __MINGW_TYPEDEF_AW(PDRIVER_INFO_5)
-  __MINGW_TYPEDEF_AW(LPDRIVER_INFO_5)
+__MINGW_TYPEDEF_AW(DRIVER_INFO_5)
+__MINGW_TYPEDEF_AW(PDRIVER_INFO_5)
+__MINGW_TYPEDEF_AW(LPDRIVER_INFO_5)
 
-  typedef struct _DRIVER_INFO_6A {
+typedef struct _DRIVER_INFO_6A {
     DWORD cVersion;
     LPSTR pName;
     LPSTR pEnvironment;
@@ -507,9 +507,9 @@ extern "C" {
     LPSTR pszOEMUrl;
     LPSTR pszHardwareID;
     LPSTR pszProvider;
-  } DRIVER_INFO_6A,*PDRIVER_INFO_6A,*LPDRIVER_INFO_6A;
+} DRIVER_INFO_6A,*PDRIVER_INFO_6A,*LPDRIVER_INFO_6A;
 
-  typedef struct _DRIVER_INFO_6W {
+typedef struct _DRIVER_INFO_6W {
     DWORD cVersion;
     LPWSTR pName;
     LPWSTR pEnvironment;
@@ -527,11 +527,11 @@ extern "C" {
     LPWSTR pszOEMUrl;
     LPWSTR pszHardwareID;
     LPWSTR pszProvider;
-  } DRIVER_INFO_6W,*PDRIVER_INFO_6W,*LPDRIVER_INFO_6W;
+} DRIVER_INFO_6W,*PDRIVER_INFO_6W,*LPDRIVER_INFO_6W;
 
-  __MINGW_TYPEDEF_AW(DRIVER_INFO_6)
-  __MINGW_TYPEDEF_AW(PDRIVER_INFO_6)
-  __MINGW_TYPEDEF_AW(LPDRIVER_INFO_6)
+__MINGW_TYPEDEF_AW(DRIVER_INFO_6)
+__MINGW_TYPEDEF_AW(PDRIVER_INFO_6)
+__MINGW_TYPEDEF_AW(LPDRIVER_INFO_6)
 
 typedef struct _DRIVER_INFO_8W {
   DWORD     cVersion;
@@ -606,39 +606,39 @@ __MINGW_TYPEDEF_AW(LPDRIVER_INFO_8)
 #define APD_COPY_NEW_FILES 0x00000008
 #define APD_COPY_FROM_DIRECTORY 0x00000010
 
-  typedef struct _DOC_INFO_1A {
+typedef struct _DOC_INFO_1A {
     LPSTR pDocName;
     LPSTR pOutputFile;
     LPSTR pDatatype;
-  } DOC_INFO_1A,*PDOC_INFO_1A,*LPDOC_INFO_1A;
+} DOC_INFO_1A,*PDOC_INFO_1A,*LPDOC_INFO_1A;
 
-  typedef struct _DOC_INFO_1W {
+typedef struct _DOC_INFO_1W {
     LPWSTR pDocName;
     LPWSTR pOutputFile;
     LPWSTR pDatatype;
-  } DOC_INFO_1W,*PDOC_INFO_1W,*LPDOC_INFO_1W;
+} DOC_INFO_1W,*PDOC_INFO_1W,*LPDOC_INFO_1W;
 
-  __MINGW_TYPEDEF_AW(DOC_INFO_1)
-  __MINGW_TYPEDEF_AW(PDOC_INFO_1)
-  __MINGW_TYPEDEF_AW(LPDOC_INFO_1)
+__MINGW_TYPEDEF_AW(DOC_INFO_1)
+__MINGW_TYPEDEF_AW(PDOC_INFO_1)
+__MINGW_TYPEDEF_AW(LPDOC_INFO_1)
 
-  typedef struct _FORM_INFO_1A {
+typedef struct _FORM_INFO_1A {
     DWORD Flags;
     LPSTR pName;
     SIZEL Size;
     RECTL ImageableArea;
-  } FORM_INFO_1A,*PFORM_INFO_1A,*LPFORM_INFO_1A;
+} FORM_INFO_1A,*PFORM_INFO_1A,*LPFORM_INFO_1A;
 
-  typedef struct _FORM_INFO_1W {
+typedef struct _FORM_INFO_1W {
     DWORD Flags;
     LPWSTR pName;
     SIZEL Size;
     RECTL ImageableArea;
-  } FORM_INFO_1W,*PFORM_INFO_1W,*LPFORM_INFO_1W;
+} FORM_INFO_1W,*PFORM_INFO_1W,*LPFORM_INFO_1W;
 
-  __MINGW_TYPEDEF_AW(FORM_INFO_1)
-  __MINGW_TYPEDEF_AW(PFORM_INFO_1)
-  __MINGW_TYPEDEF_AW(LPFORM_INFO_1)
+__MINGW_TYPEDEF_AW(FORM_INFO_1)
+__MINGW_TYPEDEF_AW(PFORM_INFO_1)
+__MINGW_TYPEDEF_AW(LPFORM_INFO_1)
 
 typedef struct _FORM_INFO_2A {
   DWORD   Flags;
@@ -669,46 +669,50 @@ typedef struct _FORM_INFO_2W {
 __MINGW_TYPEDEF_AW(FORM_INFO_2)
 __MINGW_TYPEDEF_AW(PFORM_INFO_2)
 
-  typedef struct _DOC_INFO_2A {
+#define  STRING_NONE     0x00000001
+#define  STRING_MUIDLL   0x00000002
+#define  STRING_LANGPAIR 0x00000004
+
+typedef struct _DOC_INFO_2A {
     LPSTR pDocName;
     LPSTR pOutputFile;
     LPSTR pDatatype;
     DWORD dwMode;
     DWORD JobId;
-  } DOC_INFO_2A,*PDOC_INFO_2A,*LPDOC_INFO_2A;
+} DOC_INFO_2A,*PDOC_INFO_2A,*LPDOC_INFO_2A;
 
-  typedef struct _DOC_INFO_2W {
+typedef struct _DOC_INFO_2W {
     LPWSTR pDocName;
     LPWSTR pOutputFile;
     LPWSTR pDatatype;
     DWORD dwMode;
     DWORD JobId;
-  } DOC_INFO_2W,*PDOC_INFO_2W,*LPDOC_INFO_2W;
+} DOC_INFO_2W,*PDOC_INFO_2W,*LPDOC_INFO_2W;
 
-  __MINGW_TYPEDEF_AW(DOC_INFO_2)
-  __MINGW_TYPEDEF_AW(PDOC_INFO_2)
-  __MINGW_TYPEDEF_AW(LPDOC_INFO_2)
+__MINGW_TYPEDEF_AW(DOC_INFO_2)
+__MINGW_TYPEDEF_AW(PDOC_INFO_2)
+__MINGW_TYPEDEF_AW(LPDOC_INFO_2)
 
 #define DI_CHANNEL 1
 #define DI_READ_SPOOL_JOB 3
 
-  typedef struct _DOC_INFO_3A {
+typedef struct _DOC_INFO_3A {
     LPSTR pDocName;
     LPSTR pOutputFile;
     LPSTR pDatatype;
     DWORD dwFlags;
-  } DOC_INFO_3A,*PDOC_INFO_3A,*LPDOC_INFO_3A;
+} DOC_INFO_3A,*PDOC_INFO_3A,*LPDOC_INFO_3A;
 
-  typedef struct _DOC_INFO_3W {
+typedef struct _DOC_INFO_3W {
     LPWSTR pDocName;
     LPWSTR pOutputFile;
     LPWSTR pDatatype;
     DWORD dwFlags;
-  } DOC_INFO_3W,*PDOC_INFO_3W,*LPDOC_INFO_3W;
+} DOC_INFO_3W,*PDOC_INFO_3W,*LPDOC_INFO_3W;
 
-  __MINGW_TYPEDEF_AW(DOC_INFO_3)
-  __MINGW_TYPEDEF_AW(PDOC_INFO_3)
-  __MINGW_TYPEDEF_AW(LPDOC_INFO_3)
+__MINGW_TYPEDEF_AW(DOC_INFO_3)
+__MINGW_TYPEDEF_AW(PDOC_INFO_3)
+__MINGW_TYPEDEF_AW(LPDOC_INFO_3)
 
 #define DI_MEMORYMAP_WRITE 0x00000001
 
@@ -716,79 +720,79 @@ __MINGW_TYPEDEF_AW(PFORM_INFO_2)
 #define FORM_BUILTIN 0x00000001
 #define FORM_PRINTER 0x00000002
 
-  typedef struct _PRINTPROCESSOR_INFO_1A {
+typedef struct _PRINTPROCESSOR_INFO_1A {
     LPSTR pName;
-  } PRINTPROCESSOR_INFO_1A,*PPRINTPROCESSOR_INFO_1A,*LPPRINTPROCESSOR_INFO_1A;
+} PRINTPROCESSOR_INFO_1A,*PPRINTPROCESSOR_INFO_1A,*LPPRINTPROCESSOR_INFO_1A;
 
-  typedef struct _PRINTPROCESSOR_INFO_1W {
+typedef struct _PRINTPROCESSOR_INFO_1W {
     LPWSTR pName;
-  } PRINTPROCESSOR_INFO_1W,*PPRINTPROCESSOR_INFO_1W,*LPPRINTPROCESSOR_INFO_1W;
+} PRINTPROCESSOR_INFO_1W,*PPRINTPROCESSOR_INFO_1W,*LPPRINTPROCESSOR_INFO_1W;
 
-  __MINGW_TYPEDEF_AW(PRINTPROCESSOR_INFO_1)
-  __MINGW_TYPEDEF_AW(PPRINTPROCESSOR_INFO_1)
-  __MINGW_TYPEDEF_AW(LPPRINTPROCESSOR_INFO_1)
+__MINGW_TYPEDEF_AW(PRINTPROCESSOR_INFO_1)
+__MINGW_TYPEDEF_AW(PPRINTPROCESSOR_INFO_1)
+__MINGW_TYPEDEF_AW(LPPRINTPROCESSOR_INFO_1)
 
-  typedef struct _PRINTPROCESSOR_CAPS_1 {
+typedef struct _PRINTPROCESSOR_CAPS_1 {
     DWORD dwLevel;
     DWORD dwNupOptions;
     DWORD dwPageOrderFlags;
     DWORD dwNumberOfCopies;
-  } PRINTPROCESSOR_CAPS_1,*PPRINTPROCESSOR_CAPS_1;
+} PRINTPROCESSOR_CAPS_1,*PPRINTPROCESSOR_CAPS_1;
 
 #define NORMAL_PRINT 0x00000000
 #define REVERSE_PRINT 0x00000001
 
-  typedef struct _PORT_INFO_1A {
+typedef struct _PORT_INFO_1A {
     LPSTR pName;
-  } PORT_INFO_1A,*PPORT_INFO_1A,*LPPORT_INFO_1A;
-  typedef struct _PORT_INFO_1W {
+} PORT_INFO_1A,*PPORT_INFO_1A,*LPPORT_INFO_1A;
+typedef struct _PORT_INFO_1W {
     LPWSTR pName;
-  } PORT_INFO_1W,*PPORT_INFO_1W,*LPPORT_INFO_1W;
+} PORT_INFO_1W,*PPORT_INFO_1W,*LPPORT_INFO_1W;
 
-  __MINGW_TYPEDEF_AW(PORT_INFO_1)
-  __MINGW_TYPEDEF_AW(PPORT_INFO_1)
-  __MINGW_TYPEDEF_AW(LPPORT_INFO_1)
+__MINGW_TYPEDEF_AW(PORT_INFO_1)
+__MINGW_TYPEDEF_AW(PPORT_INFO_1)
+__MINGW_TYPEDEF_AW(LPPORT_INFO_1)
 
-  typedef struct _PORT_INFO_2A {
+typedef struct _PORT_INFO_2A {
     LPSTR pPortName;
     LPSTR pMonitorName;
     LPSTR pDescription;
     DWORD fPortType;
     DWORD Reserved;
-  } PORT_INFO_2A,*PPORT_INFO_2A,*LPPORT_INFO_2A;
+} PORT_INFO_2A,*PPORT_INFO_2A,*LPPORT_INFO_2A;
 
-  typedef struct _PORT_INFO_2W {
+typedef struct _PORT_INFO_2W {
     LPWSTR pPortName;
     LPWSTR pMonitorName;
     LPWSTR pDescription;
     DWORD fPortType;
     DWORD Reserved;
-  } PORT_INFO_2W,*PPORT_INFO_2W,*LPPORT_INFO_2W;
+} PORT_INFO_2W,*PPORT_INFO_2W,*LPPORT_INFO_2W;
 
-  __MINGW_TYPEDEF_AW(PORT_INFO_2)
-  __MINGW_TYPEDEF_AW(PPORT_INFO_2)
-  __MINGW_TYPEDEF_AW(LPPORT_INFO_2)
+__MINGW_TYPEDEF_AW(PORT_INFO_2)
+__MINGW_TYPEDEF_AW(PPORT_INFO_2)
+__MINGW_TYPEDEF_AW(LPPORT_INFO_2)
 
 #define PORT_TYPE_WRITE 0x0001
 #define PORT_TYPE_READ 0x0002
 #define PORT_TYPE_REDIRECTED 0x0004
 #define PORT_TYPE_NET_ATTACHED 0x0008
 
-  typedef struct _PORT_INFO_3A {
+typedef struct _PORT_INFO_3A {
     DWORD dwStatus;
     LPSTR pszStatus;
     DWORD dwSeverity;
-  } PORT_INFO_3A,*PPORT_INFO_3A,*LPPORT_INFO_3A;
+} PORT_INFO_3A,*PPORT_INFO_3A,*LPPORT_INFO_3A;
 
-  typedef struct _PORT_INFO_3W {
+typedef struct _PORT_INFO_3W {
     DWORD dwStatus;
     LPWSTR pszStatus;
     DWORD dwSeverity;
-  } PORT_INFO_3W,*PPORT_INFO_3W,*LPPORT_INFO_3W;
+} PORT_INFO_3W,*PPORT_INFO_3W,*LPPORT_INFO_3W;
 
-  __MINGW_TYPEDEF_AW(PORT_INFO_3)
-  __MINGW_TYPEDEF_AW(PPORT_INFO_3)
-  __MINGW_TYPEDEF_AW(LPPORT_INFO_3)
+__MINGW_TYPEDEF_AW(PORT_INFO_3)
+__MINGW_TYPEDEF_AW(PPORT_INFO_3)
+__MINGW_TYPEDEF_AW(LPPORT_INFO_3)
 
 #define PORT_STATUS_TYPE_ERROR 1
 #define PORT_STATUS_TYPE_WARNING 2
@@ -807,86 +811,86 @@ __MINGW_TYPEDEF_AW(PFORM_INFO_2)
 #define PORT_STATUS_WARMING_UP 11
 #define PORT_STATUS_POWER_SAVE 12
 
-  typedef struct _MONITOR_INFO_1A{
+typedef struct _MONITOR_INFO_1A{
     LPSTR pName;
-  } MONITOR_INFO_1A,*PMONITOR_INFO_1A,*LPMONITOR_INFO_1A;
+} MONITOR_INFO_1A,*PMONITOR_INFO_1A,*LPMONITOR_INFO_1A;
 
-  typedef struct _MONITOR_INFO_1W{
+typedef struct _MONITOR_INFO_1W{
     LPWSTR pName;
-  } MONITOR_INFO_1W,*PMONITOR_INFO_1W,*LPMONITOR_INFO_1W;
+} MONITOR_INFO_1W,*PMONITOR_INFO_1W,*LPMONITOR_INFO_1W;
 
-  __MINGW_TYPEDEF_AW(MONITOR_INFO_1)
-  __MINGW_TYPEDEF_AW(PMONITOR_INFO_1)
-  __MINGW_TYPEDEF_AW(LPMONITOR_INFO_1)
+__MINGW_TYPEDEF_AW(MONITOR_INFO_1)
+__MINGW_TYPEDEF_AW(PMONITOR_INFO_1)
+__MINGW_TYPEDEF_AW(LPMONITOR_INFO_1)
 
-  typedef struct _MONITOR_INFO_2A {
+typedef struct _MONITOR_INFO_2A {
     LPSTR pName;
     LPSTR pEnvironment;
     LPSTR pDLLName;
-  } MONITOR_INFO_2A,*PMONITOR_INFO_2A,*LPMONITOR_INFO_2A;
+} MONITOR_INFO_2A,*PMONITOR_INFO_2A,*LPMONITOR_INFO_2A;
 
-  typedef struct _MONITOR_INFO_2W {
+typedef struct _MONITOR_INFO_2W {
     LPWSTR pName;
     LPWSTR pEnvironment;
     LPWSTR pDLLName;
-  } MONITOR_INFO_2W,*PMONITOR_INFO_2W,*LPMONITOR_INFO_2W;
+} MONITOR_INFO_2W,*PMONITOR_INFO_2W,*LPMONITOR_INFO_2W;
 
-  __MINGW_TYPEDEF_AW(MONITOR_INFO_2)
-  __MINGW_TYPEDEF_AW(PMONITOR_INFO_2)
-  __MINGW_TYPEDEF_AW(LPMONITOR_INFO_2)
+__MINGW_TYPEDEF_AW(MONITOR_INFO_2)
+__MINGW_TYPEDEF_AW(PMONITOR_INFO_2)
+__MINGW_TYPEDEF_AW(LPMONITOR_INFO_2)
 
-  typedef struct _DATATYPES_INFO_1A {
+typedef struct _DATATYPES_INFO_1A {
     LPSTR pName;
-  } DATATYPES_INFO_1A,*PDATATYPES_INFO_1A,*LPDATATYPES_INFO_1A;
+} DATATYPES_INFO_1A,*PDATATYPES_INFO_1A,*LPDATATYPES_INFO_1A;
 
-  typedef struct _DATATYPES_INFO_1W {
+typedef struct _DATATYPES_INFO_1W {
     LPWSTR pName;
-  } DATATYPES_INFO_1W,*PDATATYPES_INFO_1W,*LPDATATYPES_INFO_1W;
+} DATATYPES_INFO_1W,*PDATATYPES_INFO_1W,*LPDATATYPES_INFO_1W;
 
-  __MINGW_TYPEDEF_AW(DATATYPES_INFO_1)
-  __MINGW_TYPEDEF_AW(PDATATYPES_INFO_1)
-  __MINGW_TYPEDEF_AW(LPDATATYPES_INFO_1)
+__MINGW_TYPEDEF_AW(DATATYPES_INFO_1)
+__MINGW_TYPEDEF_AW(PDATATYPES_INFO_1)
+__MINGW_TYPEDEF_AW(LPDATATYPES_INFO_1)
 
-  typedef struct _PRINTER_DEFAULTSA {
+typedef struct _PRINTER_DEFAULTSA {
     LPSTR pDatatype;
     LPDEVMODEA pDevMode;
     ACCESS_MASK DesiredAccess;
-  } PRINTER_DEFAULTSA,*PPRINTER_DEFAULTSA,*LPPRINTER_DEFAULTSA;
+} PRINTER_DEFAULTSA,*PPRINTER_DEFAULTSA,*LPPRINTER_DEFAULTSA;
 
-  typedef struct _PRINTER_DEFAULTSW {
+typedef struct _PRINTER_DEFAULTSW {
     LPWSTR pDatatype;
     LPDEVMODEW pDevMode;
     ACCESS_MASK DesiredAccess;
-  } PRINTER_DEFAULTSW,*PPRINTER_DEFAULTSW,*LPPRINTER_DEFAULTSW;
+} PRINTER_DEFAULTSW,*PPRINTER_DEFAULTSW,*LPPRINTER_DEFAULTSW;
 
-  __MINGW_TYPEDEF_AW(PRINTER_DEFAULTS)
-  __MINGW_TYPEDEF_AW(PPRINTER_DEFAULTS)
-  __MINGW_TYPEDEF_AW(LPPRINTER_DEFAULTS)
+__MINGW_TYPEDEF_AW(PRINTER_DEFAULTS)
+__MINGW_TYPEDEF_AW(PPRINTER_DEFAULTS)
+__MINGW_TYPEDEF_AW(LPPRINTER_DEFAULTS)
 
-  typedef struct _PRINTER_ENUM_VALUESA {
+typedef struct _PRINTER_ENUM_VALUESA {
     LPSTR pValueName;
     DWORD cbValueName;
     DWORD dwType;
     LPBYTE pData;
     DWORD cbData;
-  } PRINTER_ENUM_VALUESA,*PPRINTER_ENUM_VALUESA,*LPPRINTER_ENUM_VALUESA;
+} PRINTER_ENUM_VALUESA,*PPRINTER_ENUM_VALUESA,*LPPRINTER_ENUM_VALUESA;
 
-  typedef struct _PRINTER_ENUM_VALUESW {
+typedef struct _PRINTER_ENUM_VALUESW {
     LPWSTR pValueName;
     DWORD cbValueName;
     DWORD dwType;
     LPBYTE pData;
     DWORD cbData;
-  } PRINTER_ENUM_VALUESW,*PPRINTER_ENUM_VALUESW,*LPPRINTER_ENUM_VALUESW;
+} PRINTER_ENUM_VALUESW,*PPRINTER_ENUM_VALUESW,*LPPRINTER_ENUM_VALUESW;
 
-  __MINGW_TYPEDEF_AW(PRINTER_ENUM_VALUES)
-  __MINGW_TYPEDEF_AW(PPRINTER_ENUM_VALUES)
-  __MINGW_TYPEDEF_AW(LPPRINTER_ENUM_VALUES)
+__MINGW_TYPEDEF_AW(PRINTER_ENUM_VALUES)
+__MINGW_TYPEDEF_AW(PPRINTER_ENUM_VALUES)
+__MINGW_TYPEDEF_AW(LPPRINTER_ENUM_VALUES)
 
 #define EnumPrinters __MINGW_NAME_AW(EnumPrinters)
 
-  WINBOOL WINAPI EnumPrintersA(DWORD Flags,LPSTR Name,DWORD Level,LPBYTE pPrinterEnum,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned);
-  WINBOOL WINAPI EnumPrintersW(DWORD Flags,LPWSTR Name,DWORD Level,LPBYTE pPrinterEnum,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned);
+WINBOOL WINAPI EnumPrintersA(DWORD Flags,LPSTR Name,DWORD Level,LPBYTE pPrinterEnum,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned);
+WINBOOL WINAPI EnumPrintersW(DWORD Flags,LPWSTR Name,DWORD Level,LPBYTE pPrinterEnum,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned);
 
 #define PRINTER_ENUM_DEFAULT 0x00000001
 #define PRINTER_ENUM_LOCAL 0x00000002
index 63c7527..f52528e 100644 (file)
@@ -1173,14 +1173,14 @@ interface winspool {
     DWORD _RpcAddPort(
         [in, unique] WINSPOOL_HANDLE pName,
         [in] ULONG_PTR hWnd,
-        [in] WCHAR* pMonitorName
+        [in, string] WCHAR* pMonitorName
     );
 
     /* Function 0x26 */
     DWORD _RpcConfigurePort(
         [in, unique] WINSPOOL_HANDLE pName,
         [in] ULONG_PTR hWnd,
-        [in] WCHAR* pPortName
+        [in, string] WCHAR* pPortName
     );
 
     /* Function 0x27 */
@@ -1242,7 +1242,7 @@ interface winspool {
     DWORD _RpcDeleteMonitor(
         [in, unique] WINSPOOL_HANDLE pName,
         [in, string, unique] WCHAR* pEnvironment,
-        [in, string] WCHAR* pMonitorName
+        [in, string, unique] WCHAR* pMonitorName
     );
 
     /* Function 0x30 */
@@ -1342,7 +1342,7 @@ interface winspool {
 
     /* Function 0x3D */
     DWORD _RpcAddPortEx(
-        [in] WINSPOOL_HANDLE pName,
+        [in, unique] WINSPOOL_HANDLE pName,
         [in] WINSPOOL_PORT_CONTAINER* pPortContainer,
         [in] WINSPOOL_PORT_VAR_CONTAINER* pPortVarContainer,
         [in, string] WCHAR* pMonitorName
@@ -1362,9 +1362,12 @@ interface winspool {
     /* Function 0x3F */
     DWORD _RpcSpoolerInit();
 
-    /* Function 0x40 (TODO) */
+    /* Function 0x40 */
     DWORD _RpcResetPrinterEx(
-        /* TODO */
+        [in] WINSPOOL_PRINTER_HANDLE hPrinter,
+        [in, string, unique] WCHAR* pDatatype,
+        [in] WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer,
+        [in] DWORD dwFlags
     );
 
     /* Function 0x41 */
@@ -1514,9 +1517,13 @@ interface winspool {
         [in, string] const WCHAR* pKeyName
     );
 
-    /* Function 0x53 (TODO) */
+    /* Function 0x53 */
     DWORD _RpcSeekPrinter(
-        /* TODO */
+        [in] WINSPOOL_PRINTER_HANDLE hPrinter,
+        [in] LARGE_INTEGER liDistanceToMove,
+        [out] PLARGE_INTEGER pliNewPointer,
+        [in] DWORD dwMoveMethod,
+        [in] BOOL bWrite
     );
 
     /* Function 0x54 */
@@ -1553,7 +1560,7 @@ interface winspool {
 
     /* Function 0x58 */
     DWORD _RpcXcvData(
-        [in] WINSPOOL_PRINTER_HANDLE hXcv,
+        [in, unique] WINSPOOL_PRINTER_HANDLE hXcv,
         [in, string]  const WCHAR* pszDataName,
         [in, size_is(cbInputData)] BYTE* pInputData,
         [in] DWORD cbInputData,
@@ -1577,7 +1584,7 @@ interface winspool {
 
     /* Function 0x5B */
     DWORD _RpcGetSpoolFileInfo(
-        [in] WINSPOOL_PRINTER_HANDLE hPrinter,
+        [in, unique] WINSPOOL_PRINTER_HANDLE hPrinter,
         [in] WINSPOOL_HANDLE hProcessHandle,
         [in] DWORD Level,
         [in] WINSPOOL_FILE_INFO_1* pFileInfo,
@@ -1587,8 +1594,8 @@ interface winspool {
 
     /* Function 0x5C */
     DWORD _RpcCommitSpoolData(
-        [in] WINSPOOL_PRINTER_HANDLE hPrinter,
-        [in] WINSPOOL_HANDLE hProcessHandle,
+        [in, unique] WINSPOOL_PRINTER_HANDLE hPrinter,
+        [in, unique] WINSPOOL_HANDLE hProcessHandle,
         [in] DWORD cbCommit,
         [in] DWORD Level,
         [in] WINSPOOL_FILE_INFO_1* pFileInfo,
@@ -1598,7 +1605,7 @@ interface winspool {
 
     /* Function 0x5D */
     DWORD _RpcGetSpoolFileInfo2(
-        [in] WINSPOOL_PRINTER_HANDLE hPrinter,
+        [in, unique] WINSPOOL_PRINTER_HANDLE hPrinter,
         [in] DWORD dwProcessId,
         [in] DWORD Level,
         [in] WINSPOOL_FILE_INFO_CONTAINER* pFileInfoContainer
@@ -1615,12 +1622,12 @@ interface winspool {
 
     /* Function 0x5F */
     DWORD _RpcCloseSpoolFileHandle(
-        [in] WINSPOOL_PRINTER_HANDLE hPrinter
+        [in, unique] WINSPOOL_PRINTER_HANDLE hPrinter
     );
 
     /* Function 0x60 */
     DWORD _RpcFlushPrinter(
-        [in] WINSPOOL_PRINTER_HANDLE hPrinter,
+        [in, unique] WINSPOOL_PRINTER_HANDLE hPrinter,
         [in, size_is(cbBuf)] BYTE* pBuf,
         [in] DWORD cbBuf,
         [out] DWORD* pcWritten,
index 4e55a38..a173174 100644 (file)
@@ -105,6 +105,22 @@ BOOL WINAPI StrRetToStrNW(LPWSTR,DWORD,LPSTRRET,const ITEMIDLIST*);
 #define SHCNRF_RecursiveInterrupt   0x1000  /* Must be combined with SHCNRF_InterruptLevel */
 #define SHCNRF_NewDelivery          0x8000  /* Messages use shared memory */
 
+/****************************************************************************
+ * SHChangeNotify
+ */
+
+typedef struct _SHCNF_PRINTJOB_INFO
+{
+    DWORD JobId;
+    // More info,,,
+} SHCNF_PRINTJOB_INFO, *PSHCNF_PRINTJOB_INFO;
+
+//
+// Add missing types for print job notifications.
+//
+#define SHCNF_PRINTJOBA 0x0004
+#define SHCNF_PRINTJOBW 0x0007
+
 
 /****************************************************************************
  * Shell Common Dialogs
index cea56de..61a0753 100644 (file)
@@ -4,14 +4,17 @@ spec2def(spoolss.dll spoolss.spec ADD_IMPORTLIB)
 list(APPEND SOURCE
     ../marshalling.c
     context.c
+    forms.c
     jobs.c
     main.c
     memory.c
     monitors.c
     ports.c
     printerdata.c
+    printerdrivers.c
     printers.c
     printprocessors.c
+    printproviders.c
     spoolfile.c
     tools.c)
 
diff --git a/win32ss/printing/base/spoolss/forms.c b/win32ss/printing/base/spoolss/forms.c
new file mode 100644 (file)
index 0000000..823cf89
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * PROJECT:     ReactOS Spooler Router
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Functions for managing print Forms
+ * COPYRIGHT:   Copyright 2020 ReactOS
+ */
+
+#include "precomp.h"
+
+BOOL WINAPI
+AddFormW(HANDLE hPrinter, DWORD Level, PBYTE pForm)
+{
+    PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    return pHandle->pPrintProvider->PrintProvider.fpAddForm(pHandle->hPrinter, Level, pForm);
+}
+
+BOOL WINAPI
+DeleteFormW(HANDLE hPrinter, PWSTR pFormName)
+{
+    PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    return pHandle->pPrintProvider->PrintProvider.fpDeleteForm(pHandle->hPrinter, pFormName);
+}
+
+BOOL WINAPI
+EnumFormsW(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
+{
+    PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if ( cbBuf && !pForm )
+    {
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+        return FALSE;
+    }
+
+    return pHandle->pPrintProvider->PrintProvider.fpEnumForms(pHandle->hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned);
+}
+
+BOOL WINAPI
+GetFormW(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded)
+{
+    PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if ( cbBuf && pForm )
+    {
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+        return FALSE;
+    }
+
+    return pHandle->pPrintProvider->PrintProvider.fpGetForm(pHandle->hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded);
+}
+
+BOOL WINAPI
+SetFormW(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm)
+{
+    PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    return pHandle->pPrintProvider->PrintProvider.fpSetForm(pHandle->hPrinter, pFormName, Level, pForm);
+}
index 0a6d8cb..949acfd 100644 (file)
@@ -7,6 +7,72 @@
 
 #include "precomp.h"
 
+BOOL WINAPI
+AddMonitorW(PWSTR pName, DWORD Level, PBYTE pMonitors)
+{
+    BOOL bReturnValue = TRUE;
+    DWORD dwErrorCode = MAXDWORD;
+    PSPOOLSS_PRINT_PROVIDER pPrintProvider;
+    PLIST_ENTRY pEntry;
+
+    // Loop through all Print Provider.
+    for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
+    {
+        pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
+
+        // Check if this Print Provider provides the function.
+        if (!pPrintProvider->PrintProvider.fpAddMonitor)
+            continue;
+
+        bReturnValue = pPrintProvider->PrintProvider.fpAddMonitor(pName, Level, pMonitors);
+
+        if ( !bReturnValue )
+        {
+            dwErrorCode = GetLastError();
+        }
+
+        // dwErrorCode shall not be overwritten if a previous call already succeeded.
+        if (dwErrorCode != ERROR_SUCCESS)
+            dwErrorCode = GetLastError();
+    }
+
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+DeleteMonitorW(PWSTR pName, PWSTR pEnvironment, PWSTR pMonitorName)
+{
+    BOOL bReturnValue = TRUE;
+    DWORD dwErrorCode = MAXDWORD;
+    PSPOOLSS_PRINT_PROVIDER pPrintProvider;
+    PLIST_ENTRY pEntry;
+
+    // Loop through all Print Provider.
+    for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
+    {
+        pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
+
+        // Check if this Print Provider provides the function.
+        if (!pPrintProvider->PrintProvider.fpDeleteMonitor)
+            continue;
+
+        bReturnValue = pPrintProvider->PrintProvider.fpDeleteMonitor(pName, pEnvironment, pMonitorName);
+
+        if ( !bReturnValue )
+        {
+            dwErrorCode = GetLastError();
+        }
+
+        // dwErrorCode shall not be overwritten if a previous call already succeeded.
+        if (dwErrorCode != ERROR_SUCCESS)
+            dwErrorCode = GetLastError();
+    }
+
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
 BOOL WINAPI
 EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
 {
@@ -14,6 +80,7 @@ EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcb
     DWORD cbCallBuffer;
     DWORD cbNeeded;
     DWORD dwReturned;
+    DWORD dwErrorCode = MAXDWORD;
     PBYTE pCallBuffer;
     PSPOOLSS_PRINT_PROVIDER pPrintProvider;
     PLIST_ENTRY pEntry;
@@ -47,6 +114,11 @@ EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcb
         dwReturned = 0;
         bReturnValue = pPrintProvider->PrintProvider.fpEnumMonitors(pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
 
+        if ( !bReturnValue )
+        {
+            dwErrorCode = GetLastError();
+        }
+
         // Add the returned counts to the total values.
         *pcbNeeded += cbNeeded;
         *pcReturned += dwReturned;
@@ -61,10 +133,11 @@ EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcb
         if (pCallBuffer)
             pCallBuffer += cbNeeded;
 
-        // Check if we shall not ask other Print Providers.
-        if (bReturnValue == ROUTER_STOP_ROUTING)
-            break;
+        // dwErrorCode shall not be overwritten if a previous EnumPrinters call already succeeded.
+        if (dwErrorCode != ERROR_SUCCESS)
+            dwErrorCode = GetLastError();
     }
 
-    return bReturnValue;
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
 }
index 918ec1a..b0a34ad 100644 (file)
@@ -7,6 +7,142 @@
 
 #include "precomp.h"
 
+BOOL WINAPI
+AddPortExW(PWSTR pName, DWORD Level, PBYTE lpBuffer, PWSTR lpMonitorName)
+{
+    BOOL bReturnValue = TRUE;
+    DWORD dwErrorCode = MAXDWORD;
+    PSPOOLSS_PRINT_PROVIDER pPrintProvider;
+    PLIST_ENTRY pEntry;
+
+    FIXME("AddPortEx(%S, %lu, %p, %s)\n", pName, Level, lpBuffer, debugstr_w(lpMonitorName));
+
+    // Loop through all Print Provider.
+    for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
+    {
+        pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
+
+        // Check if this Print Provider provides the function.
+        if (!pPrintProvider->PrintProvider.fpAddPortEx)
+            continue;
+
+        bReturnValue = pPrintProvider->PrintProvider.fpAddPortEx(pName, Level, lpBuffer, lpMonitorName);
+
+        if ( !bReturnValue )
+        {
+            dwErrorCode = GetLastError();
+        }
+
+        // dwErrorCode shall not be overwritten if a previous call already succeeded.
+        if (dwErrorCode != ERROR_SUCCESS)
+            dwErrorCode = GetLastError();
+    }
+
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+AddPortW(PWSTR pName, HWND hWnd, PWSTR pMonitorName)
+{
+    BOOL bReturnValue = TRUE;
+    DWORD dwErrorCode = MAXDWORD;
+    PSPOOLSS_PRINT_PROVIDER pPrintProvider;
+    PLIST_ENTRY pEntry;
+
+    FIXME("AddPort(%S, %p, %s)\n", pName, hWnd, debugstr_w(pMonitorName));
+
+    // Loop through all Print Provider.
+    for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
+    {
+        pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
+
+        // Check if this Print Provider provides the function.
+        if (!pPrintProvider->PrintProvider.fpAddPort)
+            continue;
+
+        bReturnValue = pPrintProvider->PrintProvider.fpAddPort(pName, hWnd, pMonitorName);
+
+        if ( !bReturnValue )
+        {
+            dwErrorCode = GetLastError();
+        }
+
+        // dwErrorCode shall not be overwritten if a previous call already succeeded.
+        if (dwErrorCode != ERROR_SUCCESS)
+            dwErrorCode = GetLastError();
+    }
+
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+ConfigurePortW(PWSTR pName, HWND hWnd, PWSTR pPortName)
+{
+    BOOL bReturnValue = TRUE;
+    DWORD dwErrorCode = MAXDWORD;
+    PSPOOLSS_PRINT_PROVIDER pPrintProvider;
+    PLIST_ENTRY pEntry;
+
+    // Loop through all Print Provider.
+    for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
+    {
+        pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
+
+        // Check if this Print Provider provides the function.
+        if (!pPrintProvider->PrintProvider.fpConfigurePort)
+            continue;
+
+        bReturnValue = pPrintProvider->PrintProvider.fpConfigurePort(pName, hWnd, pPortName);
+
+        if ( !bReturnValue )
+        {
+            dwErrorCode = GetLastError();
+        }
+
+        // dwErrorCode shall not be overwritten if a previous call already succeeded.
+        if (dwErrorCode != ERROR_SUCCESS)
+            dwErrorCode = GetLastError();
+    }
+
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+DeletePortW(PWSTR pName, HWND hWnd, PWSTR pPortName)
+{
+    BOOL bReturnValue = TRUE;
+    DWORD dwErrorCode = MAXDWORD;
+    PSPOOLSS_PRINT_PROVIDER pPrintProvider;
+    PLIST_ENTRY pEntry;
+
+    // Loop through all Print Provider.
+    for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
+    {
+        pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
+
+        // Check if this Print Provider provides the function.
+        if (!pPrintProvider->PrintProvider.fpDeletePort)
+            continue;
+
+        bReturnValue = pPrintProvider->PrintProvider.fpDeletePort(pName, hWnd, pPortName);
+
+        if ( !bReturnValue )
+        {
+            dwErrorCode = GetLastError();
+        }
+
+        // dwErrorCode shall not be overwritten if a previous call already succeeded.
+        if (dwErrorCode != ERROR_SUCCESS)
+            dwErrorCode = GetLastError();
+    }
+
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
 BOOL WINAPI
 EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
 {
@@ -14,6 +150,7 @@ EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded
     DWORD cbCallBuffer;
     DWORD cbNeeded;
     DWORD dwReturned;
+    DWORD dwErrorCode = MAXDWORD;
     PBYTE pCallBuffer;
     PSPOOLSS_PRINT_PROVIDER pPrintProvider;
     PLIST_ENTRY pEntry;
@@ -38,11 +175,20 @@ EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded
     {
         pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
 
+        // Check if this Print Provider provides an EnumPorts function.
+        if (!pPrintProvider->PrintProvider.fpEnumPorts)
+            continue;
+
         // Call the EnumPorts function of this Print Provider.
         cbNeeded = 0;
         dwReturned = 0;
         bReturnValue = pPrintProvider->PrintProvider.fpEnumPorts(pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
 
+        if ( !bReturnValue )
+        {
+            dwErrorCode = GetLastError();
+        }
+
         // Add the returned counts to the total values.
         *pcbNeeded += cbNeeded;
         *pcReturned += dwReturned;
@@ -57,10 +203,44 @@ EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded
         if (pCallBuffer)
             pCallBuffer += cbNeeded;
 
-        // Check if we shall not ask other Print Providers.
-        if (bReturnValue == ROUTER_STOP_ROUTING)
-            break;
+        // dwErrorCode shall not be overwritten if a previous EnumPrinters call already succeeded.
+        if (dwErrorCode != ERROR_SUCCESS)
+            dwErrorCode = GetLastError();
+    }
+
+    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);
 }
index fe44d42..a9a26fb 100644 (file)
@@ -7,6 +7,96 @@
 
 #include "precomp.h"
 
+DWORD WINAPI
+DeletePrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pValueName)
+{
+    PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    return pHandle->pPrintProvider->PrintProvider.fpDeletePrinterDataEx(pHandle->hPrinter, pKeyName, pValueName);
+}
+
+DWORD WINAPI
+DeletePrinterDataW(HANDLE hPrinter, PWSTR pValueName)
+{
+    PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    return pHandle->pPrintProvider->PrintProvider.fpDeletePrinterData(pHandle->hPrinter, pValueName);
+}
+
+DWORD WINAPI
+DeletePrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName)
+{
+    PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    return pHandle->pPrintProvider->PrintProvider.fpDeletePrinterKey(pHandle->hPrinter, pKeyName);
+}
+
+DWORD WINAPI
+EnumPrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PBYTE pEnumValues, DWORD cbEnumValues, PDWORD pcbEnumValues, PDWORD pnEnumValues)
+{
+    PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    return pHandle->pPrintProvider->PrintProvider.fpEnumPrinterDataEx(pHandle->hPrinter, pKeyName, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues);
+}
+
+DWORD WINAPI
+EnumPrinterDataW(HANDLE hPrinter, DWORD dwIndex, PWSTR pValueName, DWORD cbValueName, PDWORD pcbValueName, PDWORD pType, PBYTE pData, DWORD cbData, PDWORD pcbData)
+{
+    PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    return pHandle->pPrintProvider->PrintProvider.fpEnumPrinterData(pHandle->hPrinter, dwIndex, pValueName, cbValueName, pcbValueName, pType, pData, cbData, pcbData);
+}
+
+DWORD WINAPI
+EnumPrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName, PWSTR pSubkey, DWORD cbSubkey, PDWORD pcbSubkey)
+{
+    PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    return pHandle->pPrintProvider->PrintProvider.fpEnumPrinterKey(pHandle->hPrinter, pKeyName, pSubkey, cbSubkey, pcbSubkey);
+}
+
 DWORD WINAPI
 GetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
 {
diff --git a/win32ss/printing/base/spoolss/printerdrivers.c b/win32ss/printing/base/spoolss/printerdrivers.c
new file mode 100644 (file)
index 0000000..f5787bd
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * PROJECT:     ReactOS Spooler Router
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Functions related to Printer Configuration Data
+ * COPYRIGHT:   Copyright 2020 ReactOS
+ */
+
+#include "precomp.h"
+
+BOOL WINAPI
+AddPrinterDriverExW(PWSTR pName, DWORD Level, PBYTE pDriverInfo, DWORD dwFileCopyFlags)
+{
+    BOOL bReturnValue;
+    DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
+    PLIST_ENTRY pEntry;
+    PSPOOLSS_PRINT_PROVIDER pPrintProvider;
+
+    // Loop through all Print Providers.
+    for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
+    {
+        pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
+
+        bReturnValue = pPrintProvider->PrintProvider.fpAddPrinterDriverEx(pName, Level, pDriverInfo, dwFileCopyFlags);
+
+        if (bReturnValue == ROUTER_SUCCESS)
+        {
+            dwErrorCode = ERROR_SUCCESS;
+            goto Cleanup;
+        }
+        else if (bReturnValue == ROUTER_STOP_ROUTING)
+        {
+            ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pName);
+            dwErrorCode = GetLastError();
+            goto Cleanup;
+        }
+    }
+
+Cleanup:
+    // ERROR_INVALID_NAME by the Print Provider is translated to ERROR_INVALID_PRINTER_NAME here, but not in other APIs as far as I know.
+    if (dwErrorCode == ERROR_INVALID_NAME)
+        dwErrorCode = ERROR_INVALID_PRINTER_NAME;
+
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+AddPrinterDriverW(PWSTR pName, DWORD Level, PBYTE pDriverInfo)
+{
+    TRACE("AddPrinterDriverW(%S, %lu, %p)\n", pName, Level, pDriverInfo);
+    return AddPrinterDriverExW(pName, Level, pDriverInfo, APD_COPY_NEW_FILES);
+}
+
+BOOL WINAPI
+DeletePrinterDriverExW(PWSTR pName, PWSTR pEnvironment, PWSTR pDriverName, DWORD dwDeleteFlag, DWORD dwVersionFlag)
+{
+    BOOL bReturnValue;
+    DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
+    PLIST_ENTRY pEntry;
+    PSPOOLSS_PRINT_PROVIDER pPrintProvider;
+
+    // Loop through all Print Providers.
+    for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
+    {
+        pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
+
+        bReturnValue = pPrintProvider->PrintProvider.fpDeletePrinterDriverEx(pName, pEnvironment, pDriverName, dwDeleteFlag, dwVersionFlag);
+
+        if (bReturnValue == ROUTER_SUCCESS)
+        {
+            dwErrorCode = ERROR_SUCCESS;
+            goto Cleanup;
+        }
+        else if (bReturnValue == ROUTER_STOP_ROUTING)
+        {
+            ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pName);
+            dwErrorCode = GetLastError();
+            goto Cleanup;
+        }
+    }
+
+Cleanup:
+    // ERROR_INVALID_NAME by the Print Provider is translated to ERROR_INVALID_PRINTER_NAME here, but not in other APIs as far as I know.
+    if (dwErrorCode == ERROR_INVALID_NAME)
+        dwErrorCode = ERROR_INVALID_PRINTER_NAME;
+
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+DeletePrinterDriverW(PWSTR pName, PWSTR pEnvironment, PWSTR pDriverName)
+{
+    TRACE("DeletePrinterDriverW(%S, %S, %S)\n", pName, pEnvironment, pDriverName);
+    return DeletePrinterDriverExW(pName, pEnvironment, pDriverName, 0, 0);
+}
+
+BOOL WINAPI
+EnumPrinterDriversW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
+{
+    DWORD cbCallBuffer;
+    DWORD cbNeeded;
+    DWORD dwErrorCode = MAXDWORD;
+    DWORD dwReturned;
+    PBYTE pCallBuffer;
+    BOOL Ret = FALSE;
+    PSPOOLSS_PRINT_PROVIDER pPrintProvider;
+    PLIST_ENTRY pEntry;
+
+    // Begin counting.
+    *pcbNeeded = 0;
+    *pcReturned = 0;
+
+    if ( cbBuf && !pDriverInfo )
+    {
+        dwErrorCode = ERROR_INVALID_USER_BUFFER;
+        goto Cleanup;
+    }
+
+    // At the beginning, we have the full buffer available.
+    cbCallBuffer = cbBuf;
+    pCallBuffer = pDriverInfo;
+
+    // Loop through all Print Providers.
+    for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
+    {
+        pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
+
+        // Call the EnumPrinters function of this Print Provider.
+        cbNeeded = 0;
+        dwReturned = 0;
+
+        Ret = pPrintProvider->PrintProvider.fpEnumPrinterDrivers( pName, pEnvironment, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
+
+        if ( !Ret )
+        {
+            dwErrorCode = GetLastError();
+        }
+
+        // Add the returned counts to the total values.
+        *pcbNeeded += cbNeeded;
+        *pcReturned += dwReturned;
+
+        // Reduce the available buffer size for the next call without risking an underflow.
+        if (cbNeeded < cbCallBuffer)
+            cbCallBuffer -= cbNeeded;
+        else
+            cbCallBuffer = 0;
+
+        // Advance the buffer if the caller provided it.
+        if (pCallBuffer)
+            pCallBuffer += cbNeeded;
+
+        // dwErrorCode shall not be overwritten if a previous EnumPrinters call already succeeded.
+        if (dwErrorCode != ERROR_SUCCESS)
+            dwErrorCode = GetLastError();
+    }
+
+Cleanup:
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+GetPrinterDriverW(HANDLE hPrinter, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded)
+{
+    PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    return pHandle->pPrintProvider->PrintProvider.fpGetPrinterDriver(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
+}
+
+
+BOOL WINAPI
+GetPrinterDriverExW(
+    HANDLE hPrinter,
+    LPWSTR pEnvironment,
+    DWORD Level,
+    LPBYTE pDriverInfo,
+    DWORD cbBuf,
+    LPDWORD pcbNeeded,
+    DWORD dwClientMajorVersion,
+    DWORD dwClientMinorVersion,
+    PDWORD pdwServerMajorVersion,
+    PDWORD pdwServerMinorVersion )
+{
+    PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+
+    FIXME("GetPrinterDriverExW(%p, %lu, %lu, %p, %lu, %p, %lu, %lu, %p, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, dwClientMajorVersion, dwClientMinorVersion, pdwServerMajorVersion, pdwServerMinorVersion);
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if ( cbBuf && !pDriverInfo )
+    {
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+        return FALSE;
+    }
+
+    return pHandle->pPrintProvider->PrintProvider.fpGetPrinterDriverEx(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, dwClientMajorVersion, dwClientMinorVersion, pdwServerMajorVersion, pdwServerMinorVersion);
+}
+
+BOOL WINAPI
+GetPrinterDriverDirectoryW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverDirectory, DWORD cbBuf, PDWORD pcbNeeded)
+{
+    BOOL bReturnValue;
+    DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
+    PLIST_ENTRY pEntry;
+    PSPOOLSS_PRINT_PROVIDER pPrintProvider;
+
+    if ( cbBuf && !pDriverDirectory )
+    {
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+        return FALSE;
+    }
+
+    // Loop through all Print Providers.
+    for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
+    {
+        pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
+
+        bReturnValue = pPrintProvider->PrintProvider.fpGetPrinterDriverDirectory(pName, pEnvironment, Level, pDriverDirectory, cbBuf, pcbNeeded);
+
+        if (bReturnValue == ROUTER_SUCCESS)
+        {
+            dwErrorCode = ERROR_SUCCESS;
+            goto Cleanup;
+        }
+        else if (bReturnValue == ROUTER_STOP_ROUTING)
+        {
+            ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pName);
+            dwErrorCode = GetLastError();
+            goto Cleanup;
+        }
+    }
+
+Cleanup:
+    // ERROR_INVALID_NAME by the Print Provider is translated to ERROR_INVALID_PRINTER_NAME here, but not in other APIs as far as I know.
+    if (dwErrorCode == ERROR_INVALID_NAME)
+        dwErrorCode = ERROR_INVALID_PRINTER_NAME;
+
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
index 3414717..db35d47 100644 (file)
@@ -7,6 +7,170 @@
 
 #include "precomp.h"
 
+BOOL WINAPI
+AbortPrinter(HANDLE hPrinter)
+{
+    PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    return pHandle->pPrintProvider->PrintProvider.fpAbortPrinter(pHandle->hPrinter);
+}
+
+//
+// See [MS-RPRN] 2.2.1.11 SPLCLIENT_INFO, SPLCLIENT_INFO Level.
+//
+HANDLE WINAPI
+AddPrinterExW( PWSTR pName, DWORD Level, PBYTE pPrinter, PBYTE pClientInfo, DWORD ClientInfoLevel)
+{
+    BOOL bReturnValue;
+    DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
+    HANDLE hPrinter = NULL;
+    PWSTR pPrinterName = NULL;
+    PLIST_ENTRY pEntry;
+    PSPOOLSS_PRINTER_HANDLE pHandle;
+    PSPOOLSS_PRINT_PROVIDER pPrintProvider;
+
+    if ( Level != 2 )
+    {
+        FIXME( "Unsupported level %d\n", Level );
+        SetLastError( ERROR_INVALID_LEVEL );
+        return hPrinter;
+    }
+    else
+    {
+        PPRINTER_INFO_2W pi2w = (PPRINTER_INFO_2W)pPrinter;
+        pPrinterName = pi2w->pPrinterName;
+    }
+
+    // Loop through all Print Providers to find one able to open this Printer.
+    for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
+    {
+        pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
+
+        hPrinter = pPrintProvider->PrintProvider.fpAddPrinterEx(pName, Level, pPrinter, pClientInfo, ClientInfoLevel);
+
+        bReturnValue = GetLastError();
+
+        // Fallback.... ?
+
+        if ( hPrinter == NULL && bReturnValue == ERROR_NOT_SUPPORTED )
+        {
+            hPrinter = pPrintProvider->PrintProvider.fpAddPrinter(pName, Level, pPrinter);
+        }
+
+        bReturnValue = GetLastError();
+
+        if ( bReturnValue == ROUTER_SUCCESS && hPrinter )
+        {
+            // This Print Provider has opened this Printer.
+            // Store this information and return a handle.
+            pHandle = DllAllocSplMem(sizeof(SPOOLSS_PRINTER_HANDLE));
+            if (!pHandle)
+            {
+                dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+                ERR("DllAllocSplMem failed!\n");
+                goto Cleanup;
+            }
+
+            pHandle->pPrintProvider = pPrintProvider;
+            pHandle->hPrinter = hPrinter;
+
+            dwErrorCode = ERROR_SUCCESS;
+            goto Cleanup;
+        }
+        else if (bReturnValue == ROUTER_STOP_ROUTING)
+        {
+            ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pPrinterName);
+            dwErrorCode = GetLastError();
+            goto Cleanup;
+        }
+    }
+
+Cleanup:
+    // ERROR_INVALID_NAME by the Print Provider is translated to ERROR_INVALID_PRINTER_NAME here, but not in other APIs as far as I know.
+    if (dwErrorCode == ERROR_INVALID_NAME)
+        dwErrorCode = ERROR_INVALID_PRINTER_NAME;
+
+    SetLastError(dwErrorCode);
+    return hPrinter;
+}
+
+HANDLE WINAPI
+AddPrinterW(PWSTR pName, DWORD Level, PBYTE pPrinter)
+{
+    BOOL bReturnValue;
+    DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
+    HANDLE hPrinter = NULL;
+    PWSTR pPrinterName = NULL;
+    PLIST_ENTRY pEntry;
+    PSPOOLSS_PRINTER_HANDLE pHandle;
+    PSPOOLSS_PRINT_PROVIDER pPrintProvider;
+
+    FIXME("AddPrinterW(%S, %lu, %p)\n", pName, Level, pPrinter);
+
+    if ( Level != 2 )
+    {
+        FIXME( "Unsupported level %d\n", Level );
+        SetLastError( ERROR_INVALID_LEVEL );
+        return hPrinter;
+    }
+    else
+    {
+        PPRINTER_INFO_2W pi2w = (PPRINTER_INFO_2W)pPrinter;
+        pPrinterName = pi2w->pPrinterName;
+    }
+
+    // Xp return AddPrinterExW( pName, Level, pPrinter, NULL, 0); but,,,, W7u just Forward Direct.
+
+    // Loop through all Print Providers to find one able to open this Printer.
+    for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
+    {
+        pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
+
+        hPrinter = pPrintProvider->PrintProvider.fpAddPrinter(pName, Level, pPrinter);
+
+        bReturnValue = GetLastError();
+
+        if ( bReturnValue == ROUTER_SUCCESS && hPrinter )
+        {
+            // This Print Provider has opened this Printer.
+            // Store this information and return a handle.
+            pHandle = DllAllocSplMem(sizeof(SPOOLSS_PRINTER_HANDLE));
+            if (!pHandle)
+            {
+                dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+                ERR("DllAllocSplMem failed!\n");
+                goto Cleanup;
+            }
+
+            pHandle->pPrintProvider = pPrintProvider;
+            pHandle->hPrinter = hPrinter;
+
+            dwErrorCode = ERROR_SUCCESS;
+            goto Cleanup;
+        }
+        else if (bReturnValue == ROUTER_STOP_ROUTING)
+        {
+            ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pPrinterName);
+            dwErrorCode = GetLastError();
+            goto Cleanup;
+        }
+    }
+
+Cleanup:
+    // ERROR_INVALID_NAME by the Print Provider is translated to ERROR_INVALID_PRINTER_NAME here, but not in other APIs as far as I know.
+    if (dwErrorCode == ERROR_INVALID_NAME)
+        dwErrorCode = ERROR_INVALID_PRINTER_NAME;
+
+    SetLastError(dwErrorCode);
+    return hPrinter;
+}
 
 BOOL WINAPI
 ClosePrinter(HANDLE hPrinter)
@@ -14,6 +178,8 @@ ClosePrinter(HANDLE hPrinter)
     BOOL bReturnValue;
     PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
 
+    FIXME("ClosePrinter %p\n",hPrinter);
+
     // Sanity checks.
     if (!pHandle)
     {
@@ -25,13 +191,28 @@ ClosePrinter(HANDLE hPrinter)
 
     // Call CloseHandle of the Print Provider.
     bReturnValue = pHandle->pPrintProvider->PrintProvider.fpClosePrinter(pHandle->hPrinter);
-
+    FIXME("ClosePrinter 2\n");
     // Free our handle information.
     DllFreeSplMem(pHandle);
-
+    FIXME("ClosePrinter 3\n");
     return bReturnValue;
 }
 
+BOOL WINAPI
+DeletePrinter(HANDLE hPrinter)
+{
+    PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    return pHandle->pPrintProvider->PrintProvider.fpDeletePrinter(pHandle->hPrinter);
+}
+
 BOOL WINAPI
 EndDocPrinter(HANDLE hPrinter)
 {
@@ -70,6 +251,7 @@ EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cb
     DWORD dwErrorCode = MAXDWORD;
     DWORD dwReturned;
     PBYTE pCallBuffer;
+    BOOL Ret = FALSE;
     PSPOOLSS_PRINT_PROVIDER pPrintProvider;
     PLIST_ENTRY pEntry;
 
@@ -95,7 +277,12 @@ EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cb
         // Call the EnumPrinters function of this Print Provider.
         cbNeeded = 0;
         dwReturned = 0;
-        pPrintProvider->PrintProvider.fpEnumPrinters(Flags, Name, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
+        Ret = pPrintProvider->PrintProvider.fpEnumPrinters(Flags, Name, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
+
+        if ( !Ret )
+        {
+            dwErrorCode = GetLastError();
+        }
 
         // Add the returned counts to the total values.
         *pcbNeeded += cbNeeded;
@@ -122,7 +309,7 @@ Cleanup:
 }
 
 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;
 
@@ -133,11 +320,14 @@ GetPrinterDriverW(HANDLE hPrinter, PWSTR pEnvironment, DWORD Level, PBYTE pDrive
         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;
 
@@ -148,7 +338,7 @@ GetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD cbBuf, PDWORD pc
         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
@@ -218,6 +408,36 @@ ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
     return pHandle->pPrintProvider->PrintProvider.fpReadPrinter(pHandle->hPrinter, pBuf, cbBuf, pNoBytesRead);
 }
 
+BOOL WINAPI
+SeekPrinter( HANDLE hPrinter, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER pliNewPointer, DWORD dwMoveMethod, BOOL bWrite )
+{
+    PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    return pHandle->pPrintProvider->PrintProvider.fpSeekPrinter( pHandle->hPrinter, liDistanceToMove, pliNewPointer, dwMoveMethod, bWrite );
+}
+
+BOOL WINAPI
+SetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD Command)
+{
+    PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    return pHandle->pPrintProvider->PrintProvider.fpSetPrinter( pHandle->hPrinter, Level, pPrinter, Command );
+}
+
 DWORD WINAPI
 StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
 {
@@ -268,6 +488,8 @@ XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, P
 {
     PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hXcv;
 
+    FIXME("XcvDataW( %p, %S,,,)\n",hXcv, pszDataName);
+
     // Sanity checks.
     if (!pHandle)
     {
index 2a760bf..2401cc8 100644 (file)
@@ -6,6 +6,23 @@
  */
 
 #include "precomp.h"
+#include <prtprocenv.h>
+
+BOOL WINAPI
+AddPrintProcessorW(PWSTR pName, PWSTR pEnvironment, PWSTR pPathName, PWSTR pPrintProcessorName)
+{
+    if (!pEnvironment || !*pEnvironment)
+        pEnvironment = (PWSTR)wszCurrentEnvironment;
+    return FALSE;
+}
+
+BOOL WINAPI
+DeletePrintProcessorW(PWSTR pName, PWSTR pEnvironment, PWSTR pPrintProcessorName)
+{
+    if (!pEnvironment || !*pEnvironment)
+        pEnvironment = (PWSTR)wszCurrentEnvironment;
+    return FALSE;
+}
 
 BOOL WINAPI
 EnumPrintProcessorDatatypesW(PWSTR pName, PWSTR pPrintProcessorName, DWORD Level, PBYTE pDatatypes, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
@@ -19,6 +36,12 @@ EnumPrintProcessorDatatypesW(PWSTR pName, PWSTR pPrintProcessorName, DWORD Level
         return FALSE;
     }
 
+    if ( cbBuf && !pDatatypes )
+    {
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+        return FALSE;
+    }
+
     // Always call this function on the Local Spooler.
     pPrintProvider = CONTAINING_RECORD(PrintProviderList.Flink, SPOOLSS_PRINT_PROVIDER, Entry);
     return pPrintProvider->PrintProvider.fpEnumPrintProcessorDatatypes(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned);
@@ -29,6 +52,13 @@ EnumPrintProcessorsW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pPrintP
 {
     // Always call this function on the Local Spooler.
     PSPOOLSS_PRINT_PROVIDER pPrintProvider = CONTAINING_RECORD(PrintProviderList.Flink, SPOOLSS_PRINT_PROVIDER, Entry);
+
+    if ( cbBuf && !pPrintProcessorInfo )
+    {
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+        return FALSE;
+    }
+
     return pPrintProvider->PrintProvider.fpEnumPrintProcessors(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
 }
 
@@ -44,6 +74,12 @@ GetPrintProcessorDirectoryW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE
         return FALSE;
     }
 
+    if ( cbBuf && !pPrintProcessorInfo )
+    {
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+        return FALSE;
+    }
+
     // Always call this function on the Local Spooler.
     pPrintProvider = CONTAINING_RECORD(PrintProviderList.Flink, SPOOLSS_PRINT_PROVIDER, Entry);
     return pPrintProvider->PrintProvider.fpGetPrintProcessorDirectory(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded);
diff --git a/win32ss/printing/base/spoolss/printproviders.c b/win32ss/printing/base/spoolss/printproviders.c
new file mode 100644 (file)
index 0000000..9f29f6a
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * PROJECT:     ReactOS Spooler Router
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Functions for managing print Providers
+ * COPYRIGHT:   Copyright 2020 ReactOS
+ */
+
+#include "precomp.h"
+
+//
+// These do not forward!!!
+//
+
+BOOL WINAPI
+AddPrintProvidorW(PWSTR pName, DWORD Level, PBYTE pProviderInfo)
+{
+    FIXME("AddPrintProvidorW(%S, %lu, %p)\n", pName, Level, pProviderInfo);
+    return FALSE;
+}
+
+BOOL WINAPI
+DeletePrintProvidorW(PWSTR pName, PWSTR pEnvironment, PWSTR pPrintProviderName)
+{
+    FIXME("DeletePrintProvidorW(%s, %s, %s)\n", pName, pEnvironment, pPrintProviderName);
+    return FALSE;
+}
index 2ea70ea..fa7bdab 100644 (file)
@@ -1,18 +1,18 @@
-@ stub AbortPrinter
+@ stdcall AbortPrinter(ptr)
 @ stub AddDriverCatalog
-@ stub AddFormW
+@ stdcall AddFormW(ptr long ptr)
 @ stdcall AddJobW(long long ptr long ptr)
-@ stub AddMonitorW
+@ stdcall AddMonitorW(wstr long ptr)
 @ stub AddPerMachineConnectionW
-@ stub AddPortExW
-@ stub AddPortW
+@ stdcall AddPortExW(wstr long ptr wstr)
+@ stdcall AddPortW(wstr ptr wstr)
 @ stub AddPrinterConnectionW
-@ stub AddPrinterDriverExW
-@ stub AddPrinterDriverW
-@ stub AddPrinterExW
-@ stub AddPrinterW
-@ stub AddPrintProcessorW
-@ stub AddPrintProvidorW
+@ stdcall AddPrinterDriverExW(wstr long ptr long)
+@ stdcall AddPrinterDriverW(wstr long ptr)
+@ stdcall AddPrinterExW(wstr long ptr ptr long)
+@ stdcall AddPrinterW(wstr long ptr)
+@ stdcall AddPrintProcessorW(wstr wstr wstr wstr)
+@ stdcall AddPrintProvidorW(wstr long ptr)
 @ stub AdjustPointers
 @ stub AdjustPointersInStructuresArray
 @ stub AlignKMPtr
 @ 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
index 2fadb38..1506f4d 100644 (file)
@@ -2,6 +2,8 @@
 include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/idl)
 add_rpc_files(server ${REACTOS_SOURCE_DIR}/sdk/include/reactos/idl/winspool.idl)
 
+spec2def(spoolsv.exe spoolsv.spec ADD_IMPORTLIB)
+
 list(APPEND SOURCE
     forms.c
     init.c
index 533ad93..0dc2fd8 100644 (file)
  */
 
 #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;
 }
index 0b83cca..07642f1 100644 (file)
 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
index 8b510d7..7dbb06c 100644 (file)
 DWORD
 _RpcAddPort(WINSPOOL_HANDLE pName, ULONG_PTR hWnd, WCHAR* pMonitorName)
 {
-    UNIMPLEMENTED;
-    return ERROR_INVALID_FUNCTION;
+    DWORD dwErrorCode;
+
+    FIXME("AddPort(%S, %p, %s)\n", pName, hWnd, debugstr_w(pMonitorName));
+
+    dwErrorCode = RpcImpersonateClient(NULL);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
+        return dwErrorCode;
+    }
+
+    if (!AddPortW( pName, (HWND)hWnd, pMonitorName ))
+        dwErrorCode = GetLastError();
+
+    RpcRevertToSelf();
+    return dwErrorCode;
 }
 
 DWORD
 _RpcAddPortEx(WINSPOOL_HANDLE pName, WINSPOOL_PORT_CONTAINER* pPortContainer, WINSPOOL_PORT_VAR_CONTAINER* pPortVarContainer, WCHAR* pMonitorName)
 {
-    UNIMPLEMENTED;
-    return ERROR_INVALID_FUNCTION;
+    DWORD dwErrorCode, Level = pPortContainer->Level;
+    WINSPOOL_PORT_INFO_FF PortInfoFF;
+    PBYTE lpBuffer;
+
+    FIXME("AddPortEx(%S, %lu, %s)\n", pName, Level, debugstr_w(pMonitorName));
+
+    switch (Level)
+    {
+        case 1:
+           lpBuffer = (PBYTE)pPortContainer->PortInfo.pPortInfo1;
+           break;
+
+        case 0xFFFFFFFF:
+           PortInfoFF.pPortName = pPortContainer->PortInfo.pPortInfoFF->pPortName;
+           PortInfoFF.cbMonitorData = pPortVarContainer->cbMonitorData;
+           PortInfoFF.pMonitorData =  pPortVarContainer->pMonitorData;
+           lpBuffer = (PBYTE)&PortInfoFF;
+           break;
+
+        default:
+           ERR("Level = %d, unsupported!\n", Level);
+           return ERROR_INVALID_LEVEL;
+    }
+
+    dwErrorCode = RpcImpersonateClient(NULL);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
+        return dwErrorCode;
+    }
+
+    if (!AddPortExW(pName, Level, lpBuffer, pMonitorName ))
+        dwErrorCode = GetLastError();
+
+    RpcRevertToSelf();
+    return dwErrorCode;
 }
 
 DWORD
 _RpcConfigurePort(WINSPOOL_HANDLE pName, ULONG_PTR hWnd, WCHAR* pPortName)
 {
-    UNIMPLEMENTED;
-    return ERROR_INVALID_FUNCTION;
+    DWORD dwErrorCode;
+
+    dwErrorCode = RpcImpersonateClient(NULL);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
+        return dwErrorCode;
+    }
+
+    if (!ConfigurePortW( pName, (HWND)hWnd, pPortName ))
+        dwErrorCode = GetLastError();
+
+    RpcRevertToSelf();
+    return dwErrorCode;
 }
 
 DWORD
 _RpcDeletePort(WINSPOOL_HANDLE pName, ULONG_PTR hWnd, WCHAR* pPortName)
 {
-    UNIMPLEMENTED;
-    return ERROR_INVALID_FUNCTION;
+    DWORD dwErrorCode;
+
+    dwErrorCode = RpcImpersonateClient(NULL);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
+        return dwErrorCode;
+    }
+
+    if (!DeletePortW( pName, (HWND)hWnd, pPortName ))
+        dwErrorCode = GetLastError();
+
+    RpcRevertToSelf();
+    return dwErrorCode;
 }
 
 DWORD
@@ -71,6 +143,18 @@ _RpcEnumPorts(WINSPOOL_HANDLE pName, DWORD Level, BYTE* pPort, DWORD cbBuf, DWOR
 DWORD
 _RpcSetPort(WINSPOOL_HANDLE pName, WCHAR* pPortName, WINSPOOL_PORT_CONTAINER* pPortContainer)
 {
-    UNIMPLEMENTED;
-    return ERROR_INVALID_FUNCTION;
+    DWORD dwErrorCode;
+
+    dwErrorCode = RpcImpersonateClient(NULL);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
+        return dwErrorCode;
+    }
+
+    if (!SetPortW(pName, pPortName, pPortContainer->Level, (PBYTE)pPortContainer->PortInfo.pPortInfo3))
+        dwErrorCode = GetLastError();
+
+    RpcRevertToSelf();
+    return dwErrorCode;
 }
index ae85f84..4fbd544 100644 (file)
 DWORD
 _RpcAddPrinterDriver(WINSPOOL_HANDLE pName, WINSPOOL_DRIVER_CONTAINER* pDriverContainer)
 {
-    UNIMPLEMENTED;
-    return ERROR_INVALID_FUNCTION;
+    DWORD dwErrorCode;
+    PBYTE pDriverInfo = NULL;
+
+    switch ( pDriverContainer->Level )
+    {
+        case 8:
+        {
+            WINSPOOL_DRIVER_INFO_8 *pdi = pDriverContainer->DriverInfo.Level8;
+            PDRIVER_INFO_8W pdi8w = DllAllocSplMem(sizeof(DRIVER_INFO_8W));
+            pDriverInfo = (PBYTE)pdi8w;
+
+            pdi8w->pszPrintProcessor           = pdi->pPrintProcessor;
+            pdi8w->pszVendorSetup              = pdi->pVendorSetup;
+            pdi8w->pszzColorProfiles           = pdi->pszzColorProfiles;
+            pdi8w->pszInfPath                  = pdi->pInfPath;
+            pdi8w->pszzCoreDriverDependencies  = pdi->pszzCoreDriverDependencies;
+            pdi8w->ftMinInboxDriverVerDate     = pdi->ftMinInboxDriverVerDate;
+            pdi8w->dwlMinInboxDriverVerVersion = pdi->dwlMinInboxDriverVerVersion;
+        }
+        case 6:
+        {
+            WINSPOOL_DRIVER_INFO_6 *pdi = pDriverContainer->DriverInfo.Level6;
+            PDRIVER_INFO_6W pdi6w;
+
+            if ( pDriverInfo == NULL )
+            {
+                pdi6w = DllAllocSplMem(sizeof(DRIVER_INFO_6W));
+                pDriverInfo = (PBYTE)pdi6w;
+            }
+            else
+            {
+                pdi6w = (PDRIVER_INFO_6W)pDriverInfo;
+            }
+
+            pdi6w->pszMfgName       = pdi->pMfgName;
+            pdi6w->pszOEMUrl        = pdi->pOEMUrl;
+            pdi6w->pszHardwareID    = pdi->pHardwareID;
+            pdi6w->pszProvider      = pdi->pProvider;
+            pdi6w->ftDriverDate     = pdi->ftDriverDate;
+            pdi6w->dwlDriverVersion = pdi->dwlDriverVersion;
+        }
+        case 4:
+        {
+            WINSPOOL_DRIVER_INFO_4 *pdi = pDriverContainer->DriverInfo.Level4;
+            PDRIVER_INFO_4W pdi4w;
+
+            if ( pDriverInfo == NULL )
+            {
+                pdi4w = DllAllocSplMem(sizeof(DRIVER_INFO_4W));
+                pDriverInfo = (PBYTE)pdi4w;
+            }
+            else
+            {
+                pdi4w = (PDRIVER_INFO_4W)pDriverInfo;
+            }
+
+            pdi4w->pszzPreviousNames = pdi->pszzPreviousNames;
+        }
+        case 3:
+        {
+            WINSPOOL_DRIVER_INFO_3 *pdi = pDriverContainer->DriverInfo.Level3;
+            PDRIVER_INFO_3W pdi3w;
+
+            if ( pDriverInfo == NULL )
+            {
+                pdi3w = DllAllocSplMem(sizeof(DRIVER_INFO_3W));
+                pDriverInfo = (PBYTE)pdi3w;
+            }
+            else
+            {
+                pdi3w = (PDRIVER_INFO_3W)pDriverInfo;
+            }
+
+            pdi3w->pHelpFile        = pdi->pHelpFile;
+            pdi3w->pDependentFiles  = pdi->pDependentFiles;
+            pdi3w->pMonitorName     = pdi->pMonitorName;
+            pdi3w->pDefaultDataType = pdi->pDefaultDataType;
+            pdi3w->pDependentFiles  = pdi->pDependentFiles;
+        }
+        case 2:
+        {
+            WINSPOOL_DRIVER_INFO_2 *pdi = pDriverContainer->DriverInfo.Level2;
+            PDRIVER_INFO_2W pdi2w;
+
+            if ( pDriverInfo == NULL )
+            {
+                pdi2w = DllAllocSplMem(sizeof(DRIVER_INFO_2W));
+                pDriverInfo = (PBYTE)pdi2w;
+            }
+            else
+            {
+                pdi2w = (PDRIVER_INFO_2W)pDriverInfo;
+            }
+
+            pdi2w->pName        = pdi->pName;
+            pdi2w->pEnvironment = pdi->pEnvironment;
+            pdi2w->pDriverPath  = pdi->pDriverPath;
+            pdi2w->pDataFile    = pdi->pDataFile;
+            pdi2w->pConfigFile  = pdi->pConfigFile;
+        }
+            break;
+        //
+        // At this point pDriverInfo is null.
+        //
+        default:
+            return ERROR_INVALID_LEVEL;
+    }
+
+    dwErrorCode = RpcImpersonateClient(NULL);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
+        return dwErrorCode;
+    }
+
+    if (!AddPrinterDriverW( pName, pDriverContainer->Level, pDriverInfo ))
+        dwErrorCode = GetLastError();
+
+    if ( pDriverInfo ) DllFreeSplMem( pDriverInfo );
+
+    RpcRevertToSelf();
+    return dwErrorCode;
 }
 
 DWORD
 _RpcAddPrinterDriverEx(WINSPOOL_HANDLE pName, WINSPOOL_DRIVER_CONTAINER* pDriverContainer, DWORD dwFileCopyFlags)
 {
-    UNIMPLEMENTED;
-    return ERROR_INVALID_FUNCTION;
+    DWORD dwErrorCode;
+    PBYTE pDriverInfo = NULL;
+
+    switch ( pDriverContainer->Level )
+    {
+        case 8:
+        {
+            WINSPOOL_DRIVER_INFO_8 *pdi = pDriverContainer->DriverInfo.Level8;
+            PDRIVER_INFO_8W pdi8w = DllAllocSplMem(sizeof(DRIVER_INFO_8W));
+            pDriverInfo = (PBYTE)pdi8w;
+
+            pdi8w->pszPrintProcessor           = pdi->pPrintProcessor;
+            pdi8w->pszVendorSetup              = pdi->pVendorSetup;
+            pdi8w->pszzColorProfiles           = pdi->pszzColorProfiles;
+            pdi8w->pszInfPath                  = pdi->pInfPath;
+            pdi8w->pszzCoreDriverDependencies  = pdi->pszzCoreDriverDependencies;
+            pdi8w->ftMinInboxDriverVerDate     = pdi->ftMinInboxDriverVerDate;
+            pdi8w->dwlMinInboxDriverVerVersion = pdi->dwlMinInboxDriverVerVersion;
+        }
+        case 6:
+        {
+            WINSPOOL_DRIVER_INFO_6 *pdi = pDriverContainer->DriverInfo.Level6;
+            PDRIVER_INFO_6W pdi6w;
+
+            if ( pDriverInfo == NULL )
+            {
+                pdi6w = DllAllocSplMem(sizeof(DRIVER_INFO_6W));
+                pDriverInfo = (PBYTE)pdi6w;
+            }
+            else
+            {
+                pdi6w = (PDRIVER_INFO_6W)pDriverInfo;
+            }
+
+            pdi6w->pszMfgName       = pdi->pMfgName;
+            pdi6w->pszOEMUrl        = pdi->pOEMUrl;
+            pdi6w->pszHardwareID    = pdi->pHardwareID;
+            pdi6w->pszProvider      = pdi->pProvider;
+            pdi6w->ftDriverDate     = pdi->ftDriverDate;
+            pdi6w->dwlDriverVersion = pdi->dwlDriverVersion;
+        }
+        case 4:
+        {
+            WINSPOOL_DRIVER_INFO_4 *pdi = pDriverContainer->DriverInfo.Level4;
+            PDRIVER_INFO_4W pdi4w;
+
+            if ( pDriverInfo == NULL )
+            {
+                pdi4w = DllAllocSplMem(sizeof(DRIVER_INFO_4W));
+                pDriverInfo = (PBYTE)pdi4w;
+            }
+            else
+            {
+                pdi4w = (PDRIVER_INFO_4W)pDriverInfo;
+            }
+
+            pdi4w->pszzPreviousNames = pdi->pszzPreviousNames;
+        }
+        case 3:
+        {
+            WINSPOOL_DRIVER_INFO_3 *pdi = pDriverContainer->DriverInfo.Level3;
+            PDRIVER_INFO_3W pdi3w;
+
+            if ( pDriverInfo == NULL )
+            {
+                pdi3w = DllAllocSplMem(sizeof(DRIVER_INFO_3W));
+                pDriverInfo = (PBYTE)pdi3w;
+            }
+            else
+            {
+                pdi3w = (PDRIVER_INFO_3W)pDriverInfo;
+            }
+
+            pdi3w->pHelpFile        = pdi->pHelpFile;
+            pdi3w->pDependentFiles  = pdi->pDependentFiles;
+            pdi3w->pMonitorName     = pdi->pMonitorName;
+            pdi3w->pDefaultDataType = pdi->pDefaultDataType;
+            pdi3w->pDependentFiles  = pdi->pDependentFiles;
+        }
+        case 2:
+        {
+            WINSPOOL_DRIVER_INFO_2 *pdi = pDriverContainer->DriverInfo.Level2;
+            PDRIVER_INFO_2W pdi2w;
+
+            if ( pDriverInfo == NULL )
+            {
+                pdi2w = DllAllocSplMem(sizeof(DRIVER_INFO_2W));
+                pDriverInfo = (PBYTE)pdi2w;
+            }
+            else
+            {
+                pdi2w = (PDRIVER_INFO_2W)pDriverInfo;
+            }
+
+            pdi2w->pName        = pdi->pName;
+            pdi2w->pEnvironment = pdi->pEnvironment;
+            pdi2w->pDriverPath  = pdi->pDriverPath;
+            pdi2w->pDataFile    = pdi->pDataFile;
+            pdi2w->pConfigFile  = pdi->pConfigFile;
+        }
+            break;
+        //
+        // At this point pDriverInfo is null.
+        //
+        default:
+            return ERROR_INVALID_LEVEL;
+    }
+
+    dwErrorCode = RpcImpersonateClient(NULL);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
+        return dwErrorCode;
+    }
+
+    if (!AddPrinterDriverExW( pName, pDriverContainer->Level, pDriverInfo, dwFileCopyFlags ))
+        dwErrorCode = GetLastError();
+
+    if ( pDriverInfo ) DllFreeSplMem( pDriverInfo );
+
+    RpcRevertToSelf();
+    return dwErrorCode;
 }
 
 DWORD
 _RpcDeletePrinterDriver(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, WCHAR* pDriverName)
 {
-    UNIMPLEMENTED;
-    return ERROR_INVALID_FUNCTION;
+    DWORD dwErrorCode;
+
+    dwErrorCode = RpcImpersonateClient(NULL);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
+        return dwErrorCode;
+    }
+
+    if (!DeletePrinterDriverW(pName, pEnvironment, pDriverName))
+        dwErrorCode = GetLastError();
+
+    RpcRevertToSelf();
+    return dwErrorCode;
 }
 
 DWORD
 _RpcDeletePrinterDriverEx(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, WCHAR* pDriverName, DWORD dwDeleteFlag, DWORD dwVersionNum)
 {
-    UNIMPLEMENTED;
-    return ERROR_INVALID_FUNCTION;
+    DWORD dwErrorCode;
+
+    dwErrorCode = RpcImpersonateClient(NULL);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
+        return dwErrorCode;
+    }
+
+    if (!DeletePrinterDriverExW(pName, pEnvironment, pDriverName, dwDeleteFlag, dwVersionNum))
+        dwErrorCode = GetLastError();
+
+    RpcRevertToSelf();
+    return dwErrorCode;
 }
 
 DWORD
 _RpcEnumPrinterDrivers(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, DWORD Level, BYTE* pDrivers, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned)
 {
-    UNIMPLEMENTED;
-    return ERROR_INVALID_FUNCTION;
+    DWORD dwErrorCode;
+    PBYTE pPrinterDriversEnumAligned;
+
+    dwErrorCode = RpcImpersonateClient(NULL);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
+        return dwErrorCode;
+    }
+
+    pPrinterDriversEnumAligned = AlignRpcPtr(pDrivers, &cbBuf);
+
+    if (EnumPrinterDriversW(pName, pEnvironment, Level, pPrinterDriversEnumAligned, cbBuf, pcbNeeded, pcReturned))
+    {
+        // Replace absolute pointer addresses in the output by relative offsets.
+        ASSERT(Level <= 6 || Level == 8);
+        MarshallDownStructuresArray(pPrinterDriversEnumAligned, *pcReturned, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
+    }
+    else
+    {
+        dwErrorCode = GetLastError();
+    }
+
+    RpcRevertToSelf();
+    UndoAlignRpcPtr(pDrivers, pPrinterDriversEnumAligned, cbBuf, pcbNeeded);
+
+    return dwErrorCode;
 }
 
 DWORD
@@ -49,7 +338,7 @@ _RpcGetPrinterDriver(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pEnvironment, DWOR
     DWORD dwErrorCode;
     PBYTE pDriverAligned;
 
-    ERR("_RpcGetPrinterDriver(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriver, cbBuf, pcbNeeded);
+    TRACE("_RpcGetPrinterDriver(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriver, cbBuf, pcbNeeded);
 
     dwErrorCode = RpcImpersonateClient(NULL);
     if (dwErrorCode != ERROR_SUCCESS)
@@ -63,7 +352,7 @@ _RpcGetPrinterDriver(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pEnvironment, DWOR
     if (GetPrinterDriverW(hPrinter, pEnvironment, Level, pDriverAligned, cbBuf, pcbNeeded))
     {
         // Replace relative offset addresses in the output by absolute pointers.
-        ASSERT(Level >= 1 && Level <= 5);
+        ASSERT(Level <= 6 || Level == 8);
         MarshallDownStructure(pDriverAligned, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
     }
     else
@@ -77,16 +366,102 @@ _RpcGetPrinterDriver(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pEnvironment, DWOR
     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;
 }
index 08eec5f..b1eb907 100644 (file)
 DWORD
 _RpcAbortPrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
 {
-    UNIMPLEMENTED;
-    return ERROR_INVALID_FUNCTION;
+    DWORD dwErrorCode;
+
+    dwErrorCode = RpcImpersonateClient(NULL);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
+        return dwErrorCode;
+    }
+
+    if (!AbortPrinter(hPrinter))
+        dwErrorCode = GetLastError();
+
+    RpcRevertToSelf();
+    return dwErrorCode;
 }
 
 DWORD
@@ -53,8 +65,20 @@ _RpcClosePrinter(WINSPOOL_PRINTER_HANDLE* phPrinter)
 DWORD
 _RpcDeletePrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
 {
-    UNIMPLEMENTED;
-    return ERROR_INVALID_FUNCTION;
+    DWORD dwErrorCode;
+
+    dwErrorCode = RpcImpersonateClient(NULL);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
+        return dwErrorCode;
+    }
+
+    if (!DeletePrinter(hPrinter))
+        dwErrorCode = GetLastError();
+
+    RpcRevertToSelf();
+    return dwErrorCode;
 }
 
 DWORD
@@ -224,17 +248,64 @@ _RpcResetPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pDatatype, WINSPOOL_DE
 }
 
 DWORD
-_RpcResetPrinterEx(VOID)
+_RpcResetPrinterEx(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pDatatype, WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer, DWORD dwFlags)
 {
-    UNIMPLEMENTED;
-    return ERROR_INVALID_FUNCTION;
+    DWORD dwErrorCode;
+    PRINTER_DEFAULTSW pdw;
+
+    if (pDatatype)
+    {
+        pdw.pDatatype = pDatatype;
+    }
+    else
+    {
+        pdw.pDatatype = dwFlags & RESETPRINTERDEFAULTDATATYPE ? (PWSTR)-1 : NULL;
+    }
+
+    if (pDevModeContainer->pDevMode)
+    {
+        pdw.pDevMode = (PDEVMODEW)pDevModeContainer->pDevMode;
+        // Fixme : Need to check DevMode before forward call, by copy devmode.c from WinSpool.
+        //         Local SV!SplIsValidDevmode((PDW)pDevModeContainer->pDevMode, pDevModeContainer->cbBuf)
+    }
+    else
+    {
+        pdw.pDevMode = dwFlags & RESETPRINTERDEFAULTDEVMODE ? (PDEVMODEW)-1 : NULL;
+
+    }
+    pdw.DesiredAccess = 0;
+
+    dwErrorCode = RpcImpersonateClient(NULL);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
+        return dwErrorCode;
+    }
+
+    if (!ResetPrinterW(hPrinter, &pdw))
+        dwErrorCode = GetLastError();
+
+    RpcRevertToSelf();
+    return dwErrorCode;
 }
 
 DWORD
-_RpcSeekPrinter(VOID)
+_RpcSeekPrinter( WINSPOOL_PRINTER_HANDLE hPrinter, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER pliNewPointer, DWORD dwMoveMethod, BOOL bWrite )
 {
-    UNIMPLEMENTED;
-    return ERROR_INVALID_FUNCTION;
+    DWORD dwErrorCode;
+
+    dwErrorCode = RpcImpersonateClient(NULL);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
+        return dwErrorCode;
+    }
+
+    if (!SeekPrinter(hPrinter, liDistanceToMove, pliNewPointer, dwMoveMethod, bWrite))
+        dwErrorCode = GetLastError();
+
+    RpcRevertToSelf();
+    return dwErrorCode;
 }
 
 DWORD
index fcdb7d5..4dffb8c 100644 (file)
 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
index 3e04c32..b4d2b79 100644 (file)
 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;
 }
index f1a4cab..33c194e 100644 (file)
@@ -42,11 +42,26 @@ _RpcDeletePrinterConnection(WINSPOOL_HANDLE pName)
     return ERROR_INVALID_FUNCTION;
 }
 
+//
+// Forward Dead API....
+//
 DWORD
 _RpcPrinterMessageBox(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Error, ULONG_PTR hWnd, WCHAR* pText, WCHAR* pCaption, DWORD dwType)
 {
-    UNIMPLEMENTED;
-    return ERROR_INVALID_FUNCTION;
+    DWORD dwErrorCode;
+
+    dwErrorCode = RpcImpersonateClient(NULL);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
+        return dwErrorCode;
+    }
+
+    PrinterMessageBoxW(hPrinter, Error, (HWND)hWnd, pText, pCaption, dwType);
+    dwErrorCode = GetLastError();
+
+    RpcRevertToSelf();
+    return dwErrorCode;
 }
 
 DWORD
diff --git a/win32ss/printing/base/spoolsv/spoolsv.spec b/win32ss/printing/base/spoolsv/spoolsv.spec
new file mode 100644 (file)
index 0000000..ba9ddaa
--- /dev/null
@@ -0,0 +1,18 @@
+@ stdcall -stub YAbortPrinter(ptr long)
+@ stdcall -stub YAddJob(long long ptr long ptr long)
+@ stdcall -stub YDriverUnloadComplete(wstr long)
+@ stdcall -stub YEndDocPrinter(long long)
+@ stdcall -stub YEndPagePrinter(long long)
+@ stdcall -stub YFlushPrinter(ptr ptr long ptr long long)
+@ stdcall -stub YGetPrinter(ptr long ptr long ptr long)
+@ stdcall YGetPrinterDriver2(ptr wstr long ptr long ptr long long ptr ptr long)
+@ stdcall -stub YGetPrinterDriverDirectory(wstr wstr long ptr long ptr long)
+@ stdcall -stub YReadPrinter(ptr ptr long ptr long)
+@ stdcall -stub YSeekPrinter(ptr int64 ptr long long long)
+@ stdcall -stub YSetJob(ptr long long ptr long long)
+@ stdcall -stub YSetPort(wstr wstr long ptr long)
+@ stdcall -stub YSetPrinter(ptr long ptr long long)
+@ stdcall -stub YSplReadPrinter(ptr ptr long long)
+@ stdcall -stub YStartDocPrinter(ptr long ptr long)
+@ stdcall -stub YStartPagePrinter(ptr long)
+@ stdcall -stub YWritePrinter(ptr ptr long ptr long)
index 3013674..a9d4528 100644 (file)
 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;
 }
index 7d8a0e6..5fd3399 100644 (file)
@@ -177,6 +177,7 @@ BOOL WINAPI
 EnumFormsA(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
 {
     DWORD dwErrorCode, i;
+    PFORM_INFO_1W pfi1w = (PFORM_INFO_1W)pForm;
     PFORM_INFO_2W pfi2w = (PFORM_INFO_2W)pForm;
 
     TRACE("EnumFormsA(%p, %lu, %p, %lu, %p, %p)\n", hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned);
@@ -203,13 +204,18 @@ EnumFormsA(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNee
                     {
                         goto Cleanup;
                     }
-                    // Fall through...
-                case 1:
                     dwErrorCode = UnicodeToAnsiInPlace(pfi2w[i].pName);
                     if (dwErrorCode != ERROR_SUCCESS)
                     {
                         goto Cleanup;
                     }
+                    break;
+                case 1:
+                    dwErrorCode = UnicodeToAnsiInPlace(pfi1w[i].pName);
+                    if (dwErrorCode != ERROR_SUCCESS)
+                    {
+                        goto Cleanup;
+                    }
             }
         }
         return TRUE;
@@ -269,7 +275,8 @@ GetFormA(HANDLE hPrinter, PSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf,
 {
     DWORD dwErrorCode, len;
     LPWSTR FormNameW = NULL;
-    FORM_INFO_2W* pfi2w = (FORM_INFO_2W*)pForm;
+    PFORM_INFO_1W pfi1w = (PFORM_INFO_1W)pForm;
+    PFORM_INFO_2W pfi2w = (PFORM_INFO_2W)pForm;
 
     TRACE("GetFormA(%p, %s, %lu, %p, %lu, %p)\n", hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded);
 
@@ -300,20 +307,18 @@ GetFormA(HANDLE hPrinter, PSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf,
                 {
                     goto Cleanup;
                 }
-            // Fall through...
-            case 1:
                 dwErrorCode = UnicodeToAnsiInPlace(pfi2w->pName);
                 if (dwErrorCode != ERROR_SUCCESS)
                 {
                     goto Cleanup;
                 }
                 break;
-
-            default:
-                ERR("Level = %d, unsupported!\n", Level);
-                dwErrorCode = ERROR_INVALID_HANDLE;
-                SetLastError(dwErrorCode);
-                break;
+            case 1:
+                dwErrorCode = UnicodeToAnsiInPlace(pfi1w->pName);
+                if (dwErrorCode != ERROR_SUCCESS)
+                {
+                    goto Cleanup;
+                }
         }
     }
 Cleanup:
index 7cc17d4..6953143 100644 (file)
@@ -65,10 +65,12 @@ AddJobW(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNeeded
 
     if (dwErrorCode == ERROR_SUCCESS)
     {
+        JOB_INFO_1W* pji1w = (JOB_INFO_1W*)pData;
+
         // Replace relative offset addresses in the output by absolute pointers.
         MarshallUpStructure(cbBuf, pData, AddJobInfo1Marshalling.pInfo, AddJobInfo1Marshalling.cbStructureSize, TRUE);
         pHandle->bJob = TRUE;
-        FIXME("Notify Tray Icon\n");
+        UpdateTrayIcon( hPrinter, pji1w->JobId );
     }
 
 Cleanup:
@@ -489,23 +491,23 @@ SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command
     case 1:
       {
         JOB_INFO_1W *info1W = (JOB_INFO_1W*)JobW;
-        HeapFree(GetProcessHeap(), 0, info1W->pUserName);
-        HeapFree(GetProcessHeap(), 0, info1W->pDocument);
-        HeapFree(GetProcessHeap(), 0, info1W->pDatatype);
-        HeapFree(GetProcessHeap(), 0, info1W->pStatus);
+        if (info1W->pUserName) HeapFree(GetProcessHeap(), 0, info1W->pUserName);
+        if (info1W->pDocument) HeapFree(GetProcessHeap(), 0, info1W->pDocument);
+        if (info1W->pDatatype) HeapFree(GetProcessHeap(), 0, info1W->pDatatype);
+        if (info1W->pStatus) HeapFree(GetProcessHeap(), 0, info1W->pStatus);
         break;
       }
     case 2:
       {
         JOB_INFO_2W *info2W = (JOB_INFO_2W*)JobW;
-        HeapFree(GetProcessHeap(), 0, info2W->pUserName);
-        HeapFree(GetProcessHeap(), 0, info2W->pDocument);
-        HeapFree(GetProcessHeap(), 0, info2W->pNotifyName);
-        HeapFree(GetProcessHeap(), 0, info2W->pDatatype);
-        HeapFree(GetProcessHeap(), 0, info2W->pPrintProcessor);
-        HeapFree(GetProcessHeap(), 0, info2W->pParameters);
-        HeapFree(GetProcessHeap(), 0, info2W->pDevMode);
-        HeapFree(GetProcessHeap(), 0, info2W->pStatus);
+        if (info2W->pUserName) HeapFree(GetProcessHeap(), 0, info2W->pUserName);
+        if (info2W->pDocument) HeapFree(GetProcessHeap(), 0, info2W->pDocument);
+        if (info2W->pNotifyName) HeapFree(GetProcessHeap(), 0, info2W->pNotifyName);
+        if (info2W->pDatatype) HeapFree(GetProcessHeap(), 0, info2W->pDatatype);
+        if (info2W->pPrintProcessor) HeapFree(GetProcessHeap(), 0, info2W->pPrintProcessor);
+        if (info2W->pParameters) HeapFree(GetProcessHeap(), 0, info2W->pParameters);
+        if (info2W->pDevMode) HeapFree(GetProcessHeap(), 0, info2W->pDevMode);
+        if (info2W->pStatus) HeapFree(GetProcessHeap(), 0, info2W->pStatus);
         break;
       }
     }
index 720d353..7365755 100644 (file)
@@ -18,7 +18,7 @@ AddMonitorA(PSTR pName, DWORD Level, PBYTE pMonitors)
     MONITOR_INFO_2W mi2w;
 
     mi2a = (LPMONITOR_INFO_2A) pMonitors;
-    TRACE("AddMonitorA(%s, %d, %p) :  %s %s %s\n", debugstr_a(pName), Level, pMonitors,
+    FIXME("AddMonitorA(%s, %d, %p) :  %s %s %s\n", debugstr_a(pName), Level, pMonitors,
           debugstr_a(mi2a ? mi2a->pName : NULL),
           debugstr_a(mi2a ? mi2a->pEnvironment : NULL),
           debugstr_a(mi2a ? mi2a->pDLLName : NULL));
@@ -65,10 +65,10 @@ AddMonitorA(PSTR pName, DWORD Level, PBYTE pMonitors)
 
     res = AddMonitorW(nameW, Level, (LPBYTE) &mi2w);
 
-    HeapFree(GetProcessHeap(), 0, mi2w.pName);
-    HeapFree(GetProcessHeap(), 0, mi2w.pEnvironment);
-    HeapFree(GetProcessHeap(), 0, mi2w.pDLLName);
-    HeapFree(GetProcessHeap(), 0, nameW);
+    if (mi2w.pName) HeapFree(GetProcessHeap(), 0, mi2w.pName);
+    if (mi2w.pEnvironment) HeapFree(GetProcessHeap(), 0, mi2w.pEnvironment);
+    if (mi2w.pDLLName) HeapFree(GetProcessHeap(), 0, mi2w.pDLLName);
+    if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
 
     return (res);
 }
@@ -78,7 +78,8 @@ AddMonitorW(PWSTR pName, DWORD Level, PBYTE pMonitors)
 {
     DWORD dwErrorCode;
     WINSPOOL_MONITOR_CONTAINER MonitorInfoContainer;
-    TRACE("AddMonitorW(%S, %lu, %p)\n", pName, Level, pMonitors);
+
+    FIXME("AddMonitorW(%S, %lu, %p)\n", pName, Level, pMonitors);
 
     if (Level != 2)
     {
@@ -101,7 +102,7 @@ AddMonitorW(PWSTR pName, DWORD Level, PBYTE pMonitors)
         ERR("_RpcAddMonitor failed with exception code %lu!\n", dwErrorCode);
     }
     RpcEndExcept;
-
+FIXME("AddMonitorW Error Code %lu\n", dwErrorCode);
     SetLastError(dwErrorCode);
     return (dwErrorCode == ERROR_SUCCESS);
 }
@@ -136,9 +137,9 @@ DeleteMonitorA(PSTR pName, PSTR pEnvironment, PSTR pMonitorName)
 
     res = DeleteMonitorW(nameW, EnvironmentW, MonitorNameW);
 
-    HeapFree(GetProcessHeap(), 0, MonitorNameW);
-    HeapFree(GetProcessHeap(), 0, EnvironmentW);
-    HeapFree(GetProcessHeap(), 0, nameW);
+    if (MonitorNameW) HeapFree(GetProcessHeap(), 0, MonitorNameW);
+    if (EnvironmentW) HeapFree(GetProcessHeap(), 0, EnvironmentW);
+    if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
 
     return (res);
 }
@@ -148,7 +149,7 @@ DeleteMonitorW(PWSTR pName, PWSTR pEnvironment, PWSTR pMonitorName)
 {
     DWORD dwErrorCode;
 
-    TRACE("DeleteMonitorW(%S, %S, %S)\n", pName, pEnvironment, pMonitorName);
+    FIXME("DeleteMonitorW(%S, %S, %S)\n", pName, pEnvironment, pMonitorName);
 
     // Do the RPC call
     RpcTryExcept
@@ -296,8 +297,8 @@ emA_cleanup:
     if (pcbNeeded)  *pcbNeeded = needed;
     if (pcReturned) *pcReturned = (res) ? numentries : 0;
 
-    HeapFree(GetProcessHeap(), 0, nameW);
-    HeapFree(GetProcessHeap(), 0, bufferW);
+    if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
+    if (bufferW) HeapFree(GetProcessHeap(), 0, bufferW);
 
     FIXME("returning %d with %d (%d byte for %d entries)\n", (res), GetLastError(), needed, numentries);
 
index 6444bf0..2dd2755 100644 (file)
@@ -8,27 +8,40 @@
 #include "precomp.h"
 #include <marshalling/ports.h>
 
+typedef struct _MONITORUIDATA
+{
+    HMODULE hLibrary;
+    HANDLE hActCtx;
+    ULONG_PTR ulpCookie;
+    PWSTR pModuleName;
+    BOOL Activeated;
+} MONITORUIDATA, *PMONITORUIDATA;
+
+typedef DWORD (*PPfpFunction)(LPWSTR, ULONG_PTR, LPWSTR);
+
 typedef struct _PORTTHREADINFO
 {
-  LPWSTR pName;
-  HWND hWnd;
-  LPWSTR pPortName;
-  FARPROC fpFunction;
-  DWORD dwErrorCode;
-  HANDLE hEvent;
+    LPWSTR pName;
+    ULONG_PTR hWnd;
+    LPWSTR pPortName;
+    PPfpFunction fpFunction;
+    DWORD dwErrorCode;
+    HANDLE hEvent;
 } PORTTHREADINFO, *PPORTTHREADINFO;
 
 VOID WINAPI
 IntPortThread( PPORTTHREADINFO pPortThreadInfo )
 {
+    FIXME("IPT : %s\n",debugstr_w( pPortThreadInfo->pPortName ));
     // Do the RPC call
     RpcTryExcept
     {
-        pPortThreadInfo->dwErrorCode = (*pPortThreadInfo->fpFunction)( pPortThreadInfo->pName, pPortThreadInfo->hWnd, pPortThreadInfo->pPortName);
+        pPortThreadInfo->dwErrorCode = pPortThreadInfo->fpFunction( pPortThreadInfo->pName, pPortThreadInfo->hWnd, pPortThreadInfo->pPortName );
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
     {
         pPortThreadInfo->dwErrorCode = RpcExceptionCode();
+        ERR("IPT : _RpcXyzPort failed with exception code %lu!\n", pPortThreadInfo->dwErrorCode);
     }
     RpcEndExcept;
 
@@ -39,7 +52,7 @@ IntPortThread( PPORTTHREADINFO pPortThreadInfo )
 // Start a thread to wait on a printer port.
 //
 BOOL WINAPI
-StartPortThread( LPWSTR pName, HWND hWnd, LPWSTR pPortName, FARPROC fpFunction )
+StartPortThread( LPWSTR pName, HWND hWnd, LPWSTR pPortName, PPfpFunction fpFunction )
 {
     PORTTHREADINFO PortThreadInfo;
     HANDLE htHandle;
@@ -49,7 +62,7 @@ StartPortThread( LPWSTR pName, HWND hWnd, LPWSTR pPortName, FARPROC fpFunction )
     if ( hWnd ) EnableWindow( hWnd, FALSE );
 
     PortThreadInfo.pName = pName;
-    PortThreadInfo.hWnd = hWnd;
+    PortThreadInfo.hWnd = (ULONG_PTR)hWnd;
     PortThreadInfo.pPortName = pPortName;
     PortThreadInfo.fpFunction = fpFunction;
     PortThreadInfo.dwErrorCode = ERROR_SUCCESS;
@@ -86,6 +99,322 @@ StartPortThread( LPWSTR pName, HWND hWnd, LPWSTR pPortName, FARPROC fpFunction )
     return (PortThreadInfo.dwErrorCode == ERROR_SUCCESS);
 }
 
+BOOL WINAPI
+GetMonitorUIFullName( PWSTR pDeviceName, PWSTR *pModuleName )
+{
+    STRSAFE_LPWSTR SysDir;
+    UINT length;
+    HRESULT hr;
+
+   *pModuleName = NULL;
+
+    SysDir = HeapAlloc(hProcessHeap, 0, MAX_PATH*sizeof(WCHAR));
+
+    if ( SysDir )
+    {
+        memset( SysDir, 0, MAX_PATH*sizeof(WCHAR) );
+
+        length = GetSystemDirectoryW( SysDir, MAX_PATH*sizeof(WCHAR) );
+
+        if ( length > 0 )
+        {
+            StringCbCatW(SysDir, MAX_PATH*sizeof(WCHAR), L"\\");
+
+            hr = StringCchCatW( SysDir, MAX_PATH*sizeof(WCHAR), pDeviceName );
+            if ( !FAILED(hr) )
+            {
+                *pModuleName = SysDir;
+                return TRUE;
+            }
+            SetLastError(HRESULT_CODE(hr));
+        }
+
+        HeapFree(hProcessHeap, 0, SysDir);
+    }
+    return FALSE;
+}
+
+BOOL WINAPI
+GetMonitorUIActivationContext( PWSTR pDeviceName, PMONITORUIDATA pmuid )
+{
+   // ACTCTXW actctx;
+   // HANDLE handle;
+    BOOL Ret = FALSE;
+
+    FIXME("GMUIAC : Module pDeviceName %S\n",pDeviceName);
+
+    if ( !GetMonitorUIFullName( pDeviceName, &pmuid->pModuleName ) )
+    {
+        ERR("GetMonitorUIFullName Failed\n");
+        return Ret;
+    }
+/*    OMG! SxS again?
+    memset(&actctx, 0, sizeof(ACTCTXW));
+    actctx.cbSize = sizeof(ACTCTXW);
+    actctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;
+    actctx.lpResourceName = MAKEINTRESOURCEW(123); This might be the reason....
+    actctx.lpSource = pmuid->pModuleName;
+
+    handle = CreateActCtxW(&actctx);
+
+    if ( handle != INVALID_HANDLE_VALUE )
+    {
+        pmuid->hActCtx = handle;
+        if ( ActivateActCtx( handle, &pmuid->ulpCookie ) )
+        {
+            pmuid->Activeated = TRUE;
+            Ret = TRUE;
+        }
+        else
+        {
+            pmuid->Activeated = FALSE;
+        }
+    }
+    else
+    {
+        ERR("GetMonitorUIActivationContext Failed %S\n",pmuid->pModuleName);
+    }*/
+    pmuid->hActCtx = INVALID_HANDLE_VALUE;
+    Ret = TRUE;
+    return Ret;
+}
+
+VOID FASTCALL
+FreeMonitorUI( PMONITORUIDATA pmuid )
+{
+    if ( pmuid )
+    {
+        if ( pmuid->hLibrary )
+        {
+            FreeLibrary( pmuid->hLibrary );
+        }
+        if ( pmuid->Activeated )
+        {
+            DeactivateActCtx( 0, pmuid->ulpCookie );
+        }
+        if ( pmuid->hActCtx != INVALID_HANDLE_VALUE )
+        {
+            ReleaseActCtx( pmuid->hActCtx );
+        }
+        if ( pmuid->pModuleName )
+        {
+            DllFreeSplMem( pmuid->pModuleName );
+        }
+        DllFreeSplMem( pmuid );
+    }
+}
+
+BOOL FASTCALL
+StrNCatBuff( PWSTR ptr, size_t Size, PWSTR args, ...)
+{
+    va_list Args;
+    PWSTR pwstr;
+    HRESULT hr;
+    BOOL Ret = TRUE;
+
+    va_start(Args, args );
+
+   for ( pwstr = args ; pwstr ; pwstr = va_arg( Args, PWSTR ) )
+   {
+       hr = StringCchCatNW( ptr, Size, pwstr, wcslen(pwstr) );
+       if ( FAILED(hr) )
+       {
+           SetLastError(HRESULT_CODE(hr));
+           Ret = FALSE;
+           break;
+        }
+    }
+
+    va_end(Args);
+
+    return Ret;
+}
+
+PWSTR WINAPI
+ConstructXcvName( PWSTR pName, PWSTR pMonitorPortName, PWSTR pXcvName )
+{
+    BOOL Ret = FALSE;
+    PWSTR pwstr = NULL;
+    size_t sXcv, smpn = 0, Size = 0;
+
+    if ( pName )
+    {
+        Size = wcslen( pName ) + 1;
+    }
+
+    sXcv = wcslen( pXcvName ) + Size;
+
+    if ( pMonitorPortName )
+    {
+        smpn = wcslen( pMonitorPortName );
+    }
+
+    Size = sXcv + smpn + 3;
+
+    pwstr = DllAllocSplMem( Size * sizeof(WCHAR) );
+
+    memset( pwstr, 0, Size );
+
+    if ( pwstr )
+    {
+        // The caller wants an Xcv handle and provided a string like:
+        //    ", XcvMonitor Local Port"
+        //    "\\COMPUTERNAME\, XcvMonitor Local Port"
+        //    ", XcvPort LPT1:"
+        //    "\\COMPUTERNAME\, XcvPort LPT1:"
+        //
+        //    This produces; !pName ",XcvMonitor " or pName "\\COMPUTERNAME\XcvMonitor "
+        //
+        Ret = StrNCatBuff( pwstr,
+                           Size,
+                           pName ? pName : L"",
+                           pName ? L"\\" : L",",
+                           pXcvName,
+                           L" ",
+                           pMonitorPortName ? pMonitorPortName : L"",
+                           NULL );
+    }
+
+    if ( !Ret )
+    {
+        DllFreeSplMem( pwstr );
+        pwstr = NULL;
+    }
+
+    return pwstr;
+}
+
+DWORD WINAPI
+GetMonitorUI( PWSTR pName, PWSTR pMonitorPortName, PWSTR pXcvName, PMONITORUI *pmui, PMONITORUIDATA *ppmuid )
+{
+    DWORD dwErrorCode = ERROR_SUCCESS, cbOutputNeeded, dwStatus;
+    HANDLE hPrinter = NULL;
+    HMODULE hModule;
+    PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
+    PWSTR pDevice = NULL, pOutputString = NULL;
+    PMONITORUIDATA pmuid = NULL;
+    PRINTER_DEFAULTSW wDefault = { 0, 0, PRINTER_ATTRIBUTE_QUEUED };
+    BYTE OutputData[1024], InputData[4];
+
+    *pmui = NULL;
+    *ppmuid = NULL;
+
+    pDevice = ConstructXcvName( pName, pMonitorPortName, pXcvName );
+
+    if ( !pDevice )
+    {
+        return GetLastError();
+    }
+
+    FIXME("GMUI : XcvName : %S\n",pDevice);
+
+    if ( OpenPrinterW( (LPWSTR)pDevice, &hPrinter, &wDefault ) )
+    {
+        pHandle = (PSPOOLER_HANDLE)hPrinter;
+
+        // Do the RPC call
+        RpcTryExcept
+        {
+            dwErrorCode = _RpcXcvData( pHandle->hPrinter,
+                                       L"MonitorUI",
+                                       (PBYTE)&InputData,
+                                       0,
+                                       (PBYTE)&OutputData,
+                                       1024,
+                                       &cbOutputNeeded,
+                                       &dwStatus );
+        }
+        RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+        {
+            dwErrorCode = RpcExceptionCode();
+            ERR("GMUI : _RpcXcvData failed with exception code %lu!\n", dwErrorCode);
+        }
+        RpcEndExcept;
+
+        if ( dwErrorCode == ERROR_INSUFFICIENT_BUFFER )
+        {
+            pOutputString = DllAllocSplMem( cbOutputNeeded );
+
+            // Do the RPC call
+            RpcTryExcept
+            {
+                dwErrorCode = _RpcXcvData( pHandle->hPrinter,
+                                           L"MonitorUI",
+                                           (PBYTE)&InputData,
+                                           0,
+                                           (PBYTE)pOutputString,
+                                           cbOutputNeeded,
+                                           &cbOutputNeeded,
+                                           &dwStatus );
+            }
+            RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+            {
+                dwErrorCode = RpcExceptionCode();
+                ERR("GMUI : _RpcXcvData failed with exception code %lu!\n", dwErrorCode);
+            }
+            RpcEndExcept;
+        }
+
+        if ( dwErrorCode != ERROR_SUCCESS || dwStatus != ERROR_SUCCESS )
+        {
+            goto Cleanup;
+        }
+
+        pmuid = DllAllocSplMem( sizeof(MONITORUIDATA) );
+        if ( pmuid )
+        {
+            memset( pmuid, 0, sizeof(MONITORUIDATA) );
+            pmuid->hActCtx = INVALID_HANDLE_VALUE;
+        }
+        else
+        {
+            ERR("GMUI : Memory error\n");
+            dwErrorCode = GetLastError();
+            goto Cleanup;
+        }
+
+        if ( GetMonitorUIActivationContext( pOutputString ? pOutputString : (PWSTR)&OutputData, pmuid ) )
+        {
+            FIXME("GMUI : MonitorUI Path : %S\n",pmuid->pModuleName);
+
+            hModule = LoadLibraryW( pmuid->pModuleName );
+            if ( hModule )
+            {
+                FARPROC fpInitializePrintMonitorUI = (PVOID) GetProcAddress( hModule, "InitializePrintMonitorUI" );
+                if ( fpInitializePrintMonitorUI )
+                {
+                    pmuid->hLibrary = hModule;
+                    *pmui = (PMONITORUI)(*fpInitializePrintMonitorUI)();
+                    *ppmuid = pmuid;
+                }
+                else
+                {
+                   ERR("GMUI : Failed to get MUI %S\n",pmuid->pModuleName);
+                   FreeMonitorUI( pmuid );
+                }
+            }
+            else
+            {
+                ERR("GMUI : Failed to load library %S\n",pmuid->pModuleName);
+            }
+        }
+    }
+    else
+    {
+        ERR("GMUI : Failed to open printer handle\n");
+    }
+
+    dwErrorCode = GetLastError();
+
+Cleanup:
+    if ( hPrinter ) ClosePrinter( hPrinter );
+    if ( pOutputString ) DllFreeSplMem( pOutputString );
+    if ( pDevice ) DllFreeSplMem( pDevice );
+
+    FIXME("GMUI : Error Code Exit %d\n",dwErrorCode);
+
+    return dwErrorCode;
+}
 
 BOOL WINAPI
 AddPortA(PSTR pName, HWND hWnd, PSTR pMonitorName)
@@ -113,8 +442,8 @@ AddPortA(PSTR pName, HWND hWnd, PSTR pMonitorName)
 
     res = AddPortW(nameW, hWnd, monitorW);
 
-    HeapFree(GetProcessHeap(), 0, nameW);
-    HeapFree(GetProcessHeap(), 0, monitorW);
+    if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
+    if (monitorW) HeapFree(GetProcessHeap(), 0, monitorW);
 
     return res;
 }
@@ -127,12 +456,12 @@ AddPortExW(PWSTR pName, DWORD Level, PBYTE lpBuffer, PWSTR lpMonitorName)
     WINSPOOL_PORT_VAR_CONTAINER PortVarContainer;
     WINSPOOL_PORT_INFO_FF *pPortInfoFF;
 
-    TRACE("AddPortExW(%S, %lu, %p, %S)\n", pName, Level, lpBuffer, lpMonitorName);
+    FIXME("AddPortExW(%S, %lu, %p, %S)\n", pName, Level, lpBuffer, lpMonitorName);
 
     switch (Level)
     {
         case 1:
-           // FIXME!!!! Only Level 1 is supported? See note in wine winspool test info.c : line 575.
+           // FIXME!!!! Only Level 1 is supported? See note in wine winspool test info.c : line 575. It's just not supported here.
            PortInfoContainer.PortInfo.pPortInfo1 = (WINSPOOL_PORT_INFO_1*)lpBuffer;
            PortInfoContainer.Level = Level;
            PortVarContainer.cbMonitorData = 0;
@@ -182,7 +511,7 @@ AddPortExA(PSTR pName, DWORD Level, PBYTE lpBuffer, PSTR lpMonitorName)
     pi1A = (PORT_INFO_1A *)lpBuffer;
     pPortInfoFF = (WINSPOOL_PORT_INFO_FF*)lpBuffer;
 
-    TRACE("AddPortExA(%s, %d, %p, %s): %s\n", debugstr_a(pName), Level, lpBuffer, debugstr_a(lpMonitorName), debugstr_a(pi1A ? pi1A->pName : NULL));
+    FIXME("AddPortExA(%s, %d, %p, %s): %s\n", debugstr_a(pName), Level, lpBuffer, debugstr_a(lpMonitorName), debugstr_a(pi1A ? pi1A->pName : NULL));
 
     if ( !lpBuffer || !lpMonitorName )
     {
@@ -256,8 +585,44 @@ Cleanup:
 BOOL WINAPI
 AddPortW(PWSTR pName, HWND hWnd, PWSTR pMonitorName)
 {
-    TRACE("AddPortW(%S, %p, %S)\n", pName, hWnd, pMonitorName);
-    return StartPortThread(pName, hWnd, pMonitorName, (FARPROC)_RpcAddPort);
+    DWORD SessionId, dwErrorCode = 0;
+    PMONITORUIDATA pmuid;
+    PMONITORUI pmui = NULL;
+    BOOL Ret = FALSE;
+
+    FIXME("AddPortW(%S, %p, %S)\n", pName, hWnd, pMonitorName);
+
+    dwErrorCode = GetMonitorUI( pName, pMonitorName, L"XcvMonitor", &pmui, &pmuid );
+    FIXME("AddPortW Error %d\n",dwErrorCode);
+    if (dwErrorCode != ERROR_SUCCESS )
+    {
+        if ( dwErrorCode == ERROR_NOT_SUPPORTED          ||
+             dwErrorCode == ERROR_MOD_NOT_FOUND          ||
+             dwErrorCode == ERROR_INVALID_PRINT_MONITOR  ||
+             dwErrorCode == ERROR_UNKNOWN_PORT           ||
+             dwErrorCode == ERROR_INVALID_PRINTER_NAME )
+        {
+            if ( ProcessIdToSessionId( GetCurrentProcessId(), &SessionId ) && SessionId ) // Looking if this is remote.
+            {
+                dwErrorCode = ERROR_NOT_SUPPORTED;
+            }
+            else
+            {
+                Ret = StartPortThread( pName, hWnd, pMonitorName, (PPfpFunction)_RpcAddPort );
+                FIXME("AddPortW return StartPortThread\n");
+                dwErrorCode = GetLastError();
+            }
+        }
+    }
+    else
+    {
+        Ret = (*pmui->pfnAddPortUI)( pName, hWnd, pMonitorName, NULL );
+    }
+
+    SetLastError(dwErrorCode);
+    FreeMonitorUI( pmuid );
+
+    return Ret;
 }
 
 BOOL WINAPI
@@ -288,8 +653,8 @@ ConfigurePortA(PSTR pName, HWND hWnd, PSTR pPortName)
 
     res = ConfigurePortW(nameW, hWnd, portW);
 
-    HeapFree(GetProcessHeap(), 0, nameW);
-    HeapFree(GetProcessHeap(), 0, portW);
+    if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
+    if (portW) HeapFree(GetProcessHeap(), 0, portW);
 
     return res;
 }
@@ -297,8 +662,43 @@ ConfigurePortA(PSTR pName, HWND hWnd, PSTR pPortName)
 BOOL WINAPI
 ConfigurePortW(PWSTR pName, HWND hWnd, PWSTR pPortName)
 {
-    TRACE("ConfigurePortW(%S, %p, %S)\n", pName, hWnd, pPortName);
-    return StartPortThread(pName, hWnd, pPortName, (FARPROC)_RpcConfigurePort);
+    DWORD SessionId, dwErrorCode = 0;
+    PMONITORUIDATA pmuid;
+    PMONITORUI pmui = NULL;
+    BOOL Ret = FALSE;
+
+    FIXME("ConfigurePortW(%S, %p, %S)\n", pName, hWnd, pPortName);
+
+    dwErrorCode = GetMonitorUI( pName, pPortName, L"XcvPort", &pmui, &pmuid );
+
+    if (dwErrorCode != ERROR_SUCCESS )
+    {
+        if ( dwErrorCode == ERROR_NOT_SUPPORTED          ||
+             dwErrorCode == ERROR_MOD_NOT_FOUND          ||
+             dwErrorCode == ERROR_INVALID_PRINT_MONITOR  ||
+             dwErrorCode == ERROR_UNKNOWN_PORT           ||
+             dwErrorCode == ERROR_INVALID_PRINTER_NAME )
+        {
+            if ( ProcessIdToSessionId( GetCurrentProcessId(), &SessionId ) && SessionId ) // Looking if this is remote.
+            {
+                dwErrorCode = ERROR_NOT_SUPPORTED;
+            }
+            else
+            {
+                Ret = StartPortThread(pName, hWnd, pPortName, (PPfpFunction)_RpcConfigurePort );
+                dwErrorCode = GetLastError();
+            }
+        }
+    }
+    else
+    {
+        Ret = (*pmui->pfnConfigurePortUI)( pName, hWnd, pPortName );
+    }
+
+    SetLastError(dwErrorCode);
+    FreeMonitorUI( pmuid );
+
+    return Ret;
 }
 
 BOOL WINAPI
@@ -309,7 +709,7 @@ DeletePortA(PSTR pName, HWND hWnd, PSTR pPortName)
     INT     len;
     DWORD   res;
 
-    TRACE("DeletePortA(%s, %p, %s)\n", debugstr_a(pName), hWnd, debugstr_a(pPortName));
+    FIXME("DeletePortA(%s, %p, %s)\n", debugstr_a(pName), hWnd, debugstr_a(pPortName));
 
     /* convert servername to unicode */
     if (pName)
@@ -329,8 +729,8 @@ DeletePortA(PSTR pName, HWND hWnd, PSTR pPortName)
 
     res = DeletePortW(nameW, hWnd, portW);
 
-    HeapFree(GetProcessHeap(), 0, nameW);
-    HeapFree(GetProcessHeap(), 0, portW);
+    if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
+    if (portW) HeapFree(GetProcessHeap(), 0, portW);
 
     return res;
 }
@@ -338,8 +738,36 @@ DeletePortA(PSTR pName, HWND hWnd, PSTR pPortName)
 BOOL WINAPI
 DeletePortW(PWSTR pName, HWND hWnd, PWSTR pPortName)
 {
-    TRACE("DeletePortW(%S, %p, %S)\n", pName, hWnd, pPortName);
-    return StartPortThread(pName, hWnd, pPortName, (FARPROC)_RpcDeletePort);
+    DWORD dwErrorCode = 0;
+    PMONITORUIDATA pmuid;
+    PMONITORUI pmui = NULL;
+    BOOL Ret = FALSE;
+
+    FIXME("DeletePortW(%S, %p, %S)\n", pName, hWnd, pPortName);
+
+    dwErrorCode = GetMonitorUI( pName, pPortName, L"XcvPort", &pmui, &pmuid );
+    FIXME("DeletePortW Error %d\n",dwErrorCode);
+    if (dwErrorCode != ERROR_SUCCESS )
+    {
+        if ( dwErrorCode == ERROR_NOT_SUPPORTED          ||
+             dwErrorCode == ERROR_MOD_NOT_FOUND          ||
+             dwErrorCode == ERROR_INVALID_PRINT_MONITOR  ||
+             dwErrorCode == ERROR_UNKNOWN_PORT           ||
+             dwErrorCode == ERROR_INVALID_PRINTER_NAME )
+        {
+            Ret = StartPortThread(pName, hWnd, pPortName, (PPfpFunction)_RpcDeletePort );
+            dwErrorCode = GetLastError();
+        }
+    }
+    else
+    {
+        Ret = (*pmui->pfnDeletePortUI)( pName, hWnd, pPortName );
+    }
+
+    SetLastError(dwErrorCode);
+    FreeMonitorUI( pmuid );
+
+    return Ret;
 }
 
 BOOL WINAPI
@@ -354,6 +782,13 @@ EnumPortsA(PSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded,
 
     TRACE("EnumPortsA(%s, %d, %p, %d, %p, %p)\n", debugstr_a(pName), Level, pPorts, cbBuf, pcbNeeded, pcReturned);
 
+    if ((Level < 1) || (Level > 2))
+    {
+        ERR("Level = %d, unsupported!\n", Level);
+        SetLastError(ERROR_INVALID_LEVEL);
+        return FALSE;
+    }
+
     /* convert servername to unicode */
     if (pName)
     {
@@ -470,8 +905,8 @@ cleanup:
     if (pcbNeeded)  *pcbNeeded = needed;
     if (pcReturned) *pcReturned = (res) ? numentries : 0;
 
-    HeapFree(GetProcessHeap(), 0, nameW);
-    HeapFree(GetProcessHeap(), 0, bufferW);
+    if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
+    if (bufferW) HeapFree(GetProcessHeap(), 0, bufferW);
 
     TRACE("returning %d with %d (%d byte for %d of %d entries)\n",
             (res), GetLastError(), needed, (res)? numentries : 0, numentries);
@@ -486,6 +921,13 @@ EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded
 
     TRACE("EnumPortsW(%S, %lu, %p, %lu, %p, %p)\n", pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
 
+    if ((Level < 1) || (Level > 2))
+    {
+        ERR("Level = %d, unsupported!\n", Level);
+        SetLastError(ERROR_INVALID_LEVEL);
+        return FALSE;
+    }
+
     // Do the RPC call
     RpcTryExcept
     {
index 267f073..ec67b79 100644 (file)
@@ -62,9 +62,10 @@ extern CRITICAL_SECTION rtlCritSec;
 // utils.c
 DWORD UnicodeToAnsiInPlace(PWSTR pwszField);
 DWORD UnicodeToAnsiZZInPlace(PWSTR pwszzField);
-SECURITY_DESCRIPTOR * get_sd( SECURITY_DESCRIPTOR *sd, DWORD *size );
+SECURITY_DESCRIPTOR * get_sd(SECURITY_DESCRIPTOR *sd, DWORD *size);
 LONG WINAPI IntProtectHandle(HANDLE,BOOL);
 BOOL WINAPI IntUnprotectHandle(HANDLE);
+VOID UpdateTrayIcon(HANDLE hPrinter, DWORD JobId);
 
 // devmode.c
 extern void RosConvertAnsiDevModeToUnicodeDevmode(PDEVMODEA pDevModeInput, PDEVMODEW *pDevModeOutput);
index 7e574e9..d49733d 100644 (file)
@@ -57,7 +57,7 @@ DeletePrinterDataA(HANDLE hPrinter, PSTR pValueName)
 
     res = DeletePrinterDataW( hPrinter, valuenameW );
 
-    HeapFree(GetProcessHeap(), 0, valuenameW);
+    if (valuenameW) HeapFree(GetProcessHeap(), 0, valuenameW);
 
     return res;
 
@@ -89,8 +89,8 @@ DeletePrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PCSTR pValueName)
 
     res = DeletePrinterDataExW( hPrinter, keynameW, valuenameW );
 
-    HeapFree(GetProcessHeap(), 0, keynameW);
-    HeapFree(GetProcessHeap(), 0, valuenameW);
+    if (keynameW) HeapFree(GetProcessHeap(), 0, keynameW);
+    if (valuenameW) HeapFree(GetProcessHeap(), 0, valuenameW);
 
     return res;
 }
@@ -129,7 +129,7 @@ DeletePrinterKeyA(HANDLE hPrinter, PCSTR pKeyName)
 
     res = DeletePrinterKeyW( hPrinter, keynameW );
 
-    HeapFree(GetProcessHeap(), 0, keynameW);
+    if (keynameW) HeapFree(GetProcessHeap(), 0, keynameW);
 
     return res;
 }
@@ -219,18 +219,17 @@ EnumPrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PBYTE pEnumValues, DWORD cbE
     dwBufSize = 0;
     for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex)
     {
-       PPRINTER_ENUM_VALUESW ppev =
-               &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
+       PPRINTER_ENUM_VALUESW ppev = &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
 
        if (dwBufSize < ppev->cbValueName)
            dwBufSize = ppev->cbValueName;
 
-       if (dwBufSize < ppev->cbData && (ppev->dwType == REG_SZ ||
-               ppev->dwType == REG_EXPAND_SZ || ppev->dwType == REG_MULTI_SZ))
+       if ( dwBufSize < ppev->cbData &&
+           (ppev->dwType == REG_SZ || ppev->dwType == REG_EXPAND_SZ || ppev->dwType == REG_MULTI_SZ))
            dwBufSize = ppev->cbData;
     }
 
-    TRACE ("Largest Unicode name or value is %i bytes\n", dwBufSize);
+    FIXME ("Largest Unicode name or value is %i bytes\n", dwBufSize);
 
     pBuffer = HeapAlloc (hHeap, 0, dwBufSize);
     if (pBuffer == NULL)
index a30b611..7503117 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "precomp.h"
 #include <marshalling/printerdrivers.h>
+
 extern const WCHAR wszCurrentEnvironment[];
 
 static int multi_sz_lenA(const char *str)
@@ -231,26 +232,26 @@ AddPrinterDriverExA(PSTR pName, DWORD Level, PBYTE pDriverInfo, DWORD dwFileCopy
     res = AddPrinterDriverExW(nameW, Level, (LPBYTE) &diW, dwFileCopyFlags);
 
     TRACE("got %u with %u\n", res, GetLastError());
-    HeapFree(GetProcessHeap(), 0, nameW);
-    HeapFree(GetProcessHeap(), 0, diW.pName);
-    HeapFree(GetProcessHeap(), 0, diW.pEnvironment);
-    HeapFree(GetProcessHeap(), 0, diW.pDriverPath);
-    HeapFree(GetProcessHeap(), 0, diW.pDataFile);
-    HeapFree(GetProcessHeap(), 0, diW.pConfigFile);
-    HeapFree(GetProcessHeap(), 0, diW.pHelpFile);
-    HeapFree(GetProcessHeap(), 0, diW.pDependentFiles);
-    HeapFree(GetProcessHeap(), 0, diW.pMonitorName);
-    HeapFree(GetProcessHeap(), 0, diW.pDefaultDataType);
-    HeapFree(GetProcessHeap(), 0, diW.pszzPreviousNames);
-    HeapFree(GetProcessHeap(), 0, diW.pszMfgName);
-    HeapFree(GetProcessHeap(), 0, diW.pszOEMUrl);
-    HeapFree(GetProcessHeap(), 0, diW.pszHardwareID);
-    HeapFree(GetProcessHeap(), 0, diW.pszProvider);
-    HeapFree(GetProcessHeap(), 0, diW.pszPrintProcessor);
-    HeapFree(GetProcessHeap(), 0, diW.pszVendorSetup);
-    HeapFree(GetProcessHeap(), 0, diW.pszzColorProfiles);
-    HeapFree(GetProcessHeap(), 0, diW.pszInfPath);
-    HeapFree(GetProcessHeap(), 0, diW.pszzCoreDriverDependencies);
+    if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
+    if (diW.pName) HeapFree(GetProcessHeap(), 0, diW.pName);
+    if (diW.pEnvironment) HeapFree(GetProcessHeap(), 0, diW.pEnvironment);
+    if (diW.pDriverPath) HeapFree(GetProcessHeap(), 0, diW.pDriverPath);
+    if (diW.pDataFile) HeapFree(GetProcessHeap(), 0, diW.pDataFile);
+    if (diW.pConfigFile) HeapFree(GetProcessHeap(), 0, diW.pConfigFile);
+    if (diW.pHelpFile) HeapFree(GetProcessHeap(), 0, diW.pHelpFile);
+    if (diW.pDependentFiles) HeapFree(GetProcessHeap(), 0, diW.pDependentFiles);
+    if (diW.pMonitorName) HeapFree(GetProcessHeap(), 0, diW.pMonitorName);
+    if (diW.pDefaultDataType) HeapFree(GetProcessHeap(), 0, diW.pDefaultDataType);
+    if (diW.pszzPreviousNames) HeapFree(GetProcessHeap(), 0, diW.pszzPreviousNames);
+    if (diW.pszMfgName) HeapFree(GetProcessHeap(), 0, diW.pszMfgName);
+    if (diW.pszOEMUrl) HeapFree(GetProcessHeap(), 0, diW.pszOEMUrl);
+    if (diW.pszHardwareID) HeapFree(GetProcessHeap(), 0, diW.pszHardwareID);
+    if (diW.pszProvider) HeapFree(GetProcessHeap(), 0, diW.pszProvider);
+    if (diW.pszPrintProcessor) HeapFree(GetProcessHeap(), 0, diW.pszPrintProcessor);
+    if (diW.pszVendorSetup) HeapFree(GetProcessHeap(), 0, diW.pszVendorSetup);
+    if (diW.pszzColorProfiles) HeapFree(GetProcessHeap(), 0, diW.pszzColorProfiles);
+    if (diW.pszInfPath) HeapFree(GetProcessHeap(), 0, diW.pszInfPath);
+    if (diW.pszzCoreDriverDependencies) HeapFree(GetProcessHeap(), 0, diW.pszzCoreDriverDependencies);
 
     TRACE("=> %u with %u\n", res, GetLastError());
     return res;
@@ -259,7 +260,7 @@ AddPrinterDriverExA(PSTR pName, DWORD Level, PBYTE pDriverInfo, DWORD dwFileCopy
 BOOL WINAPI
 AddPrinterDriverExW(PWSTR pName, DWORD Level, PBYTE pDriverInfo, DWORD dwFileCopyFlags)
 {
-    DWORD dwErrorCode;
+    DWORD dwErrorCode = ERROR_SUCCESS;
     WINSPOOL_DRIVER_INFO_8 * pdi = NULL;
     WINSPOOL_DRIVER_CONTAINER pDriverContainer;
 
@@ -310,7 +311,6 @@ AddPrinterDriverExW(PWSTR pName, DWORD Level, PBYTE pDriverInfo, DWORD dwFileCop
         }
         case 4:
         {
-
             PDRIVER_INFO_4W pdi4w = (PDRIVER_INFO_4W)pDriverInfo;
             if ( pdi == NULL )  pdi = HeapAlloc(hProcessHeap, 0, sizeof(WINSPOOL_DRIVER_INFO_4));
 
@@ -398,6 +398,7 @@ DeletePrinterDriverA(PSTR pName, PSTR pEnvironment, PSTR pDriverName)
 BOOL WINAPI
 DeletePrinterDriverExA(PSTR pName, PSTR pEnvironment, PSTR pDriverName, DWORD dwDeleteFlag, DWORD dwVersionFlag)
 {
+    DWORD dwErrorCode;
     UNICODE_STRING NameW, EnvW, DriverW;
     BOOL ret;
 
@@ -409,10 +410,13 @@ DeletePrinterDriverExA(PSTR pName, PSTR pEnvironment, PSTR pDriverName, DWORD dw
 
     ret = DeletePrinterDriverExW(NameW.Buffer, EnvW.Buffer, DriverW.Buffer, dwDeleteFlag, dwVersionFlag);
 
+    dwErrorCode = GetLastError();
+
     RtlFreeUnicodeString(&DriverW);
     RtlFreeUnicodeString(&EnvW);
     RtlFreeUnicodeString(&NameW);
 
+    SetLastError(dwErrorCode);
     return ret;
 }
 
@@ -461,20 +465,22 @@ DeletePrinterDriverW(PWSTR pName, PWSTR pEnvironment, PWSTR pDriverName)
 BOOL WINAPI
 EnumPrinterDriversA(PSTR pName, PSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
 {
-    BOOL ret;
+    BOOL ret = FALSE;
     DWORD dwErrorCode, i;
     UNICODE_STRING pNameW, pEnvironmentW;
     PWSTR pwstrNameW, pwstrEnvironmentW;
     PDRIVER_INFO_1W pdi1w = (PDRIVER_INFO_1W)pDriverInfo;
     PDRIVER_INFO_8W pdi8w = (PDRIVER_INFO_8W)pDriverInfo;
 
-    TRACE("EnumPrinterDriversA(%s, %s, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned);
+    FIXME("EnumPrinterDriversA(%s, %s, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned);
 
     pwstrNameW = AsciiToUnicode(&pNameW, pName);
     pwstrEnvironmentW = AsciiToUnicode(&pEnvironmentW, pEnvironment);
 
     ret = EnumPrinterDriversW( pwstrNameW, pwstrEnvironmentW, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned );
 
+    dwErrorCode = GetLastError();
+
     if (ret)
     {
         for ( i = 0; i < *pcReturned; i++ )
@@ -613,11 +619,13 @@ EnumPrinterDriversA(PSTR pName, PSTR pEnvironment, DWORD Level, PBYTE pDriverInf
                 }
             }
         }
+        dwErrorCode = ERROR_SUCCESS;
     }
 Cleanup:
     RtlFreeUnicodeString(&pNameW);
     RtlFreeUnicodeString(&pEnvironmentW);
-
+    SetLastError(dwErrorCode);
+    FIXME("EnumPrinterDriversA Exit %d Err %d\n",ret,GetLastError());
     return ret;
 }
 
@@ -626,10 +634,10 @@ EnumPrinterDriversW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverI
 {
     DWORD dwErrorCode;
 
-    TRACE("EnumPrinterDriversW(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned);
+    FIXME("EnumPrinterDriversW(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned);
 
     // Dismiss invalid levels already at this point.
-    if (Level > 8 || Level == 7 || Level < 1)
+    if (Level < 1 || Level == 7 || Level > 8)
     {
         dwErrorCode = ERROR_INVALID_LEVEL;
         goto Cleanup;
@@ -663,7 +671,7 @@ EnumPrinterDriversW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverI
     }
 
 Cleanup:
-    SetLastError(dwErrorCode);
+    SetLastError(dwErrorCode); FIXME("EnumPrinterDriversW Exit Err %d\n",dwErrorCode);
     return (dwErrorCode == ERROR_SUCCESS);
 
 }
@@ -688,7 +696,7 @@ GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriv
     if (Level <  1 || Level == 7 || Level > 8)
     {
         dwErrorCode = ERROR_INVALID_LEVEL;
-        ERR("Invalid Level!\n");
+        ERR("Invalid Level! %d\n",Level);
         goto Cleanup;
     }
 
@@ -817,13 +825,13 @@ GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriv
         case 2:
         case 5:
         {
-            dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pName);
+            dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pConfigFile);
             if (dwErrorCode != ERROR_SUCCESS)
             {
                 goto Cleanup;
             }
+            dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pDataFile);
 
-            dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pEnvironment);
             if (dwErrorCode != ERROR_SUCCESS)
             {
                 goto Cleanup;
@@ -835,13 +843,13 @@ GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriv
                 goto Cleanup;
             }
 
-            dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pDataFile);
+            dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pEnvironment);
             if (dwErrorCode != ERROR_SUCCESS)
             {
                 goto Cleanup;
             }
 
-            dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pConfigFile);
+            dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pName);
             if (dwErrorCode != ERROR_SUCCESS)
             {
                 goto Cleanup;
@@ -977,6 +985,12 @@ GetPrinterDriverDirectoryW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE p
 
     TRACE("GetPrinterDriverDirectoryW(%S, %S, %lu, %p, %lu, %p)\n", pName, pEnvironment, Level, pDriverDirectory, cbBuf, pcbNeeded);
 
+    if (Level != 1)
+    {
+        dwErrorCode = ERROR_INVALID_LEVEL;
+        goto Cleanup;
+    }
+
     if ( !pEnvironment || !*pEnvironment )
     {
         pEnvironment = (PWSTR)wszCurrentEnvironment;
@@ -994,6 +1008,7 @@ GetPrinterDriverDirectoryW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE p
     }
     RpcEndExcept;
 
+Cleanup:
     SetLastError(dwErrorCode);
     return (dwErrorCode == ERROR_SUCCESS);
 }
index f88948f..1c39d7a 100644 (file)
@@ -509,7 +509,7 @@ LoadPrinterDriver( HANDLE hspool )
 
             hLibrary = LoadLibrary(pdi->pConfigFile);
 
-            FIXME("IGPD : Get Printer Driver %S\n",pdi->pConfigFile);
+            FIXME("IGPD : Get Printer Driver Config File : %S\n",pdi->pConfigFile);
 
             RtlFreeHeap( GetProcessHeap(), 0, pdi);
             return hLibrary;
@@ -657,7 +657,7 @@ DevQueryPrintEx( PDEVQUERYPRINT_INFO pDQPInfo )
 INT WINAPI
 DocumentEvent( HANDLE hPrinter, HDC hdc, int iEsc, ULONG cbIn, PVOID pvIn, ULONG cbOut, PVOID pvOut)
 {
-    TRACE("DocumentEvent(%p, %p, %lu, %lu, %p, %lu, %p)\n", hPrinter, hdc, iEsc, cbIn, pvIn, cbOut, pvOut);
+    FIXME("DocumentEvent(%p, %p, %lu, %lu, %p, %lu, %p)\n", hPrinter, hdc, iEsc, cbIn, pvIn, cbOut, pvOut);
     UNIMPLEMENTED;
     return DOCUMENTEVENT_UNSUPPORTED;
 }
@@ -2938,6 +2938,38 @@ ResetPrinterW(HANDLE hPrinter, PPRINTER_DEFAULTSW pDefault)
     return FALSE;
 }
 
+BOOL WINAPI
+SeekPrinter( HANDLE hPrinter, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER pliNewPointer, DWORD dwMoveMethod, BOOL bWrite )
+{
+    DWORD dwErrorCode;
+    PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
+
+    FIXME("SeekPrinter(%p, %I64u, %p, %lu, %d)\n", hPrinter, liDistanceToMove.QuadPart, pliNewPointer, dwMoveMethod, bWrite);
+
+    // Sanity checks.
+    if (!pHandle)
+    {
+        dwErrorCode = ERROR_INVALID_HANDLE;
+        goto Cleanup;
+    }
+
+    // Do the RPC call
+    RpcTryExcept
+    {
+        dwErrorCode = _RpcSeekPrinter(pHandle->hPrinter, liDistanceToMove, pliNewPointer, dwMoveMethod, bWrite);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        dwErrorCode = RpcExceptionCode();
+        ERR("_RpcSeekPrinter failed with exception code %lu!\n", dwErrorCode);
+    }
+    RpcEndExcept;
+
+Cleanup:
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
 BOOL WINAPI
 SetDefaultPrinterA(LPCSTR pszPrinter)
 {
@@ -3802,7 +3834,7 @@ StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
         dwReturnValue = pHandle->dwJobID;
         if ( !pHandle->bTrayIcon )
         {
-            FIXME("Notify Tray Icon\n");
+            UpdateTrayIcon( hPrinter, pHandle->dwJobID );
         }
     }
 
@@ -3905,6 +3937,65 @@ Cleanup:
 BOOL WINAPI
 XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus)
 {
+    DWORD dwErrorCode, Bogus = 0;
+    PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hXcv;
+
     TRACE("XcvDataW(%p, %S, %p, %lu, %p, %lu, %p, %p)\n", hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded, pdwStatus);
-    return FALSE;
+
+    if ( pcbOutputNeeded == NULL )
+    {
+        dwErrorCode = ERROR_INVALID_PARAMETER;
+        goto Cleanup;
+    }
+
+    // Sanity checks.
+    if (!pHandle) // ( IntProtectHandle( hXcv, FALSE ) )
+    {
+        dwErrorCode = ERROR_INVALID_HANDLE;
+        goto Cleanup;
+    }
+
+    //
+    // Do fixups.
+    //
+    if ( pInputData == NULL )
+    {
+        if ( !cbInputData )
+        {
+             pInputData = (PBYTE)&Bogus;
+        }
+    }
+
+    if ( pOutputData == NULL )
+    {
+        if ( !cbOutputData )
+        {
+            pOutputData = (PBYTE)&Bogus;
+        }
+    }
+
+    // Do the RPC call
+    RpcTryExcept
+    {
+        dwErrorCode = _RpcXcvData( pHandle->hPrinter,
+                                   pszDataName,
+                                   pInputData,
+                                   cbInputData,
+                                   pOutputData,
+                                   cbOutputData,
+                                   pcbOutputNeeded,
+                                   pdwStatus );
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        dwErrorCode = RpcExceptionCode();
+        ERR("_RpcXcvData failed with exception code %lu!\n", dwErrorCode);
+    }
+    RpcEndExcept;
+
+    //IntUnprotectHandle( hXcv );
+
+Cleanup:
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
 }
index d40d81e..f0f79f2 100644 (file)
@@ -246,9 +246,9 @@ epp_cleanup:
     if (pcbNeeded)  *pcbNeeded = needed;
     if (pcReturned) *pcReturned = (res) ? numentries : 0;
 
-    HeapFree(GetProcessHeap(), 0, nameW);
-    HeapFree(GetProcessHeap(), 0, envW);
-    HeapFree(GetProcessHeap(), 0, bufferW);
+    if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
+    if (envW) HeapFree(GetProcessHeap(), 0, envW);
+    if (bufferW) HeapFree(GetProcessHeap(), 0, bufferW);
 
     TRACE("returning %d with %d (%d byte for %d entries)\n", (res), GetLastError(), needed, numentries);
 
index 8dae057..3fa4a37 100644 (file)
@@ -6,6 +6,14 @@
 */
 
 #include "precomp.h"
+#include <shlobj.h>
+#include <undocshell.h>
+
+#define MAX_GETPRINTER_SIZE 4096 - MAX_PATH
+typedef void (WINAPI *PPfpSHChangeNotify)(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2);
+
+static HMODULE hShell32 = (HMODULE)-1;
+
 
 /*
  * Converts an incoming Unicode string to an ANSI string.
@@ -330,3 +338,41 @@ SECURITY_DESCRIPTOR * get_sd( SECURITY_DESCRIPTOR *sd, DWORD *size )
     return retsd;
 }
 
+VOID
+UpdateTrayIcon( HANDLE hPrinter, DWORD JobId )
+{
+    PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
+    SHCNF_PRINTJOB_INFO spji;
+    PRINTER_INFO_1W pi1w[MAX_GETPRINTER_SIZE] = {0};
+    DWORD cbNeeded;
+    PPfpSHChangeNotify fpFunction;
+
+    pHandle->bTrayIcon = TRUE;
+
+    spji.JobId = JobId;
+
+    if (!GetPrinterW( hPrinter, 1, (PBYTE)&pi1w, MAX_GETPRINTER_SIZE, &cbNeeded) )
+    {
+        ERR("UpdateTrayIcon : GetPrinterW cbNeeded %d\n");
+        return;
+    }
+
+    if ( hShell32 == (HMODULE)-1 )
+    {
+        hShell32 = LoadLibraryW(L"shell32.dll");
+    }
+
+    if ( hShell32 )
+    {
+        fpFunction = (PPfpSHChangeNotify)GetProcAddress( hShell32, "SHChangeNotify" );
+
+        if ( fpFunction )
+        {
+            fpFunction( SHCNE_CREATE, (SHCNF_FLUSHNOWAIT|SHCNF_FLUSH|SHCNF_PRINTJOBW), pi1w->pName , &spji );
+        }
+    }
+    else
+    {
+        ERR("UpdateTrayIcon : No Shell32!\n");
+    }
+}
index e459f5a..dbd454c 100644 (file)
 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)
index 90af259..14540a2 100644 (file)
@@ -8,7 +8,10 @@
 static const MARSHALLING FormInfo1Marshalling = {
     sizeof(FORM_INFO_1W),
     {
+        { FIELD_OFFSET(FORM_INFO_1W, Flags), RTL_FIELD_SIZE(FORM_INFO_1W, Flags), RTL_FIELD_SIZE(FORM_INFO_1W, Flags), FALSE },
         { FIELD_OFFSET(FORM_INFO_1W, pName), RTL_FIELD_SIZE(FORM_INFO_1W, pName), RTL_FIELD_SIZE(FORM_INFO_1W, pName), TRUE },
+        { FIELD_OFFSET(FORM_INFO_1W, Size), RTL_FIELD_SIZE(FORM_INFO_1W, Size), RTL_FIELD_SIZE(FORM_INFO_1W, Size), FALSE },
+        { FIELD_OFFSET(FORM_INFO_1W, ImageableArea), RTL_FIELD_SIZE(FORM_INFO_1W, ImageableArea), RTL_FIELD_SIZE(FORM_INFO_1W, ImageableArea), FALSE },
         { MAXDWORD, 0, 0, FALSE }
     }
 };
@@ -16,10 +19,16 @@ static const MARSHALLING FormInfo1Marshalling = {
 static const MARSHALLING FormInfo2Marshalling = {
     sizeof(FORM_INFO_2W),
     {
+        { FIELD_OFFSET(FORM_INFO_2W, Flags), RTL_FIELD_SIZE(FORM_INFO_2W, Flags), RTL_FIELD_SIZE(FORM_INFO_2W, Flags), FALSE },
         { FIELD_OFFSET(FORM_INFO_2W, pName), RTL_FIELD_SIZE(FORM_INFO_2W, pName), RTL_FIELD_SIZE(FORM_INFO_2W, pName), TRUE },
+        { FIELD_OFFSET(FORM_INFO_2W, Size), RTL_FIELD_SIZE(FORM_INFO_2W, Size), RTL_FIELD_SIZE(FORM_INFO_2W, Size), FALSE },
+        { FIELD_OFFSET(FORM_INFO_2W, ImageableArea), RTL_FIELD_SIZE(FORM_INFO_2W, ImageableArea), RTL_FIELD_SIZE(FORM_INFO_2W, ImageableArea), FALSE },
         { FIELD_OFFSET(FORM_INFO_2W, pKeyword), RTL_FIELD_SIZE(FORM_INFO_2W, pKeyword), RTL_FIELD_SIZE(FORM_INFO_2W, pKeyword), TRUE },
+        { FIELD_OFFSET(FORM_INFO_2W, StringType), RTL_FIELD_SIZE(FORM_INFO_2W, StringType), RTL_FIELD_SIZE(FORM_INFO_2W, StringType), FALSE },
         { FIELD_OFFSET(FORM_INFO_2W, pMuiDll), RTL_FIELD_SIZE(FORM_INFO_2W, pMuiDll), RTL_FIELD_SIZE(FORM_INFO_2W, pMuiDll), TRUE },
-        { FIELD_OFFSET(FORM_INFO_2W, pDisplayName), RTL_FIELD_SIZE(FORM_INFO_2W, pDisplayName), RTL_FIELD_SIZE(FORM_INFO_2W, pDisplayName), FALSE },
+        { FIELD_OFFSET(FORM_INFO_2W, dwResourceId), RTL_FIELD_SIZE(FORM_INFO_2W, dwResourceId), RTL_FIELD_SIZE(FORM_INFO_2W, dwResourceId), FALSE },
+        { FIELD_OFFSET(FORM_INFO_2W, pDisplayName), RTL_FIELD_SIZE(FORM_INFO_2W, pDisplayName), RTL_FIELD_SIZE(FORM_INFO_2W, pDisplayName), TRUE },
+        { FIELD_OFFSET(FORM_INFO_2W, wLangId), RTL_FIELD_SIZE(FORM_INFO_2W, wLangId), RTL_FIELD_SIZE(FORM_INFO_2W, wLangId), FALSE },
         { MAXDWORD, 0, 0, FALSE }
     }
 };
index d46c774..7a8fcd5 100644 (file)
@@ -125,5 +125,6 @@ static const MARSHALLING* pPrinterDriverMarshalling[] = {
     &PrinterDriver4Marshalling,
     &PrinterDriver5Marshalling,
     &PrinterDriver6Marshalling,
+    NULL,
     &PrinterDriver8Marshalling,
 };
index 51de840..30a5490 100644 (file)
@@ -8,6 +8,21 @@
 #ifndef _REACTOS_SPOOLSS_H
 #define _REACTOS_SPOOLSS_H
 
+#define RESETPRINTERDEFAULTDATATYPE 0x0001
+#define RESETPRINTERDEFAULTDEVMODE  0x0002
+
+#define PORT_IS_UNKNOWN  0
+#define PORT_IS_LPT      1
+#define PORT_IS_COM      2
+#define PORT_IS_FILE     3
+#define PORT_IS_FILENAME 4
+#define PORT_IS_WINE     5
+#define PORT_IS_UNIXNAME 5
+#define PORT_IS_PIPE     6
+#define PORT_IS_VNET     7
+#define PORT_IS_XPS      8
+
+
 // Constants
 #define MAX_PRINTER_NAME        220
 
@@ -64,6 +79,7 @@ typedef struct _FILE_INFO_1
     DWORD  dwOptions;
 } FILE_INFO_1, *PFILE_INFO_1;
 
+BOOL WINAPI AddPortExW(LPWSTR, DWORD, LPBYTE, LPWSTR);
 PVOID WINAPI AlignRpcPtr(PVOID pBuffer, PDWORD pcbBuffer);
 PWSTR WINAPI AllocSplStr(PCWSTR pwszInput);
 PVOID WINAPI DllAllocSplMem(DWORD dwBytes);
@@ -73,11 +89,13 @@ BOOL WINAPI InitializeRouter(HANDLE SpoolerStatusHandle);
 PBYTE WINAPI PackStrings(PCWSTR* pSource, PBYTE pDest, const DWORD* DestOffsets, PBYTE pEnd);
 PVOID WINAPI ReallocSplMem(PVOID pOldMem, DWORD cbOld, DWORD cbNew);
 BOOL WINAPI ReallocSplStr(PWSTR* ppwszString, PCWSTR pwszInput);
+BOOL WINAPI SeekPrinter(HANDLE hPrinter,LARGE_INTEGER liDistanceToMove,PLARGE_INTEGER pliNewPointer,DWORD dwMoveMethod,BOOL bWrite);
 BOOL WINAPI SplInitializeWinSpoolDrv(PVOID* pTable);
 BOOL WINAPI SpoolerInit(VOID);
 PDWORD WINAPI UndoAlignRpcPtr(PVOID pDestinationBuffer, PVOID pSourceBuffer, DWORD cbBuffer, PDWORD pcbNeeded);
 BOOL WINAPI SplGetSpoolFileInfo(HANDLE hPrinter,HANDLE hProcessHandle,DWORD Level,FILE_INFO_1 *pFileInfo,DWORD dwSize,DWORD* dwNeeded );
 BOOL WINAPI SplCommitSpoolData(HANDLE hPrinter,HANDLE hProcessHandle,DWORD cbCommit,DWORD Level,FILE_INFO_1 *pFileInfo,DWORD dwSize,DWORD* dwNeeded);
 BOOL WINAPI SplCloseSpoolFileHandle( HANDLE hPrinter );
+BOOL WINAPI GetPrinterDriverExW(HANDLE hPrinter,LPWSTR pEnvironment,DWORD Level,LPBYTE pDriverInfo,DWORD cbBuf,LPDWORD pcbNeeded,DWORD dwClientMajorVersion,DWORD dwClientMinorVersion,PDWORD pdwServerMajorVersion,PDWORD pdwServerMinorVersion );
 
 #endif
index 8350e8e..c8984e4 100644 (file)
@@ -24,10 +24,10 @@ static MONITOR2 _MonitorFunctions = {
     LocalmonReadPort,               // pfnReadPort
     LocalmonEndDocPort,             // pfnEndDocPort
     LocalmonClosePort,              // pfnClosePort
-    NULL,                           // pfnAddPort
-    NULL,                           // pfnAddPortEx
-    NULL,                           // pfnConfigurePort
-    NULL,                           // pfnDeletePort
+    LocalmonAddPort,                // pfnAddPort moved to localui.dll since w2k, but~
+    LocalmonAddPortEx,              // pfnAddPortEx
+    LocalmonConfigurePort,          // pfnConfigurePort moved to localui.dll since w2k, but~
+    LocalmonDeletePort,             // pfnDeletePort moved to localui.dll since w2k, but~
     LocalmonGetPrinterDataFromPort, // pfnGetPrinterDataFromPort
     LocalmonSetPortTimeOuts,        // pfnSetPortTimeOuts
     LocalmonXcvOpenPort,            // pfnXcvOpenPort
@@ -114,32 +114,48 @@ LocalmonShutdown(HANDLE hMonitor)
     PLOCALMON_HANDLE pLocalmon;
     PLOCALMON_PORT pPort;
     PLOCALMON_XCV pXcv;
+    PLIST_ENTRY pEntry;
 
     TRACE("LocalmonShutdown(%p)\n", hMonitor);
 
     pLocalmon = (PLOCALMON_HANDLE)hMonitor;
 
+    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.
@@ -164,6 +180,7 @@ InitializePrintMonitor2(PMONITORINIT pMonitorInit, PHANDLE phMonitor)
 
     // Create a new LOCALMON_HANDLE structure.
     pLocalmon = DllAllocSplMem(sizeof(LOCALMON_HANDLE));
+    pLocalmon->Sig = SIGLCMMON;
     InitializeCriticalSection(&pLocalmon->Section);
     InitializeListHead(&pLocalmon->FilePorts);
     InitializeListHead(&pLocalmon->RegistryPorts);
@@ -198,9 +215,10 @@ InitializePrintMonitor2(PMONITORINIT pMonitorInit, PHANDLE phMonitor)
             goto Cleanup;
         }
 
+        pPort->Sig = SIGLCMPORT;
         pPort->pLocalmon = pLocalmon;
         pPort->hFile = INVALID_HANDLE_VALUE;
-        pPort->pwszPortName = (PWSTR)((PBYTE)pPort + sizeof(LOCALMON_PORT));
+        pPort->pwszPortName = (PWSTR)(pPort+1);
 
         // Get the port name.
         cchPortName = cchMaxPortName + 1;
@@ -229,6 +247,7 @@ InitializePrintMonitor2(PMONITORINIT pMonitorInit, PHANDLE phMonitor)
 
         // Add it to the list.
         InsertTailList(&pLocalmon->RegistryPorts, &pPort->Entry);
+        TRACE("InitializePrintMonitor2 Port : %s \n",debugstr_w(pPort->pwszPortName));
 
         // Don't let the cleanup routine free this.
         pPort = NULL;
index bee1a22..a1f527a 100644 (file)
@@ -139,7 +139,6 @@ _ClosePortHandles(PLOCALMON_PORT pPort)
             DefineDosDeviceW(DDD_REMOVE_DEFINITION, pwszNonspooledPortName, NULL);
             DllFreeSplMem(pwszNonspooledPortName);
         }
-
         DllFreeSplMem(pwszPortNameWithoutColon);
     }
 }
@@ -1050,3 +1049,180 @@ Cleanup:
     SetLastError(dwErrorCode);
     return (dwErrorCode == ERROR_SUCCESS);
 }
+
+BOOL WINAPI
+LocalmonAddPortEx( HANDLE hMonitor, LPWSTR pName, DWORD Level, LPBYTE lpBuffer, LPWSTR lpMonitorName )
+{
+    PLOCALMON_HANDLE pLocalmon = (PLOCALMON_HANDLE)hMonitor;
+    PLOCALMON_PORT pPort;
+    HKEY hKey;
+    DWORD dwErrorCode, cbPortName;
+    PORT_INFO_1W * pi = (PORT_INFO_1W *) lpBuffer;
+
+    FIXME("LocalmonAddPortEx(%p, %lu, %p, %s) => %s\n", hMonitor, Level, lpBuffer, debugstr_w(lpMonitorName), debugstr_w(pi ? pi->pName : NULL));
+
+    // Sanity checks
+    if ( !pLocalmon )
+    {
+        dwErrorCode = ERROR_INVALID_PARAMETER;
+        goto Cleanup;
+    }
+
+    if ( ( lpMonitorName == NULL )                          ||
+         ( lstrcmpiW( lpMonitorName, L"Local Port" ) != 0 ) ||
+         ( pi == NULL )                                     ||
+         ( pi->pName == NULL )                              ||
+         ( pi->pName[0] == '\0' ) )
+    {
+        ERR("Fail Monitor Port Name\n");
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if ( Level != 1 )
+    {
+        SetLastError(ERROR_INVALID_LEVEL);
+        return FALSE;
+    }
+
+    dwErrorCode = RegOpenKeyW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Ports", &hKey );
+    if ( dwErrorCode == ERROR_SUCCESS )
+    {
+        if ( DoesPortExist( pi->pName ) )
+        {
+            RegCloseKey( hKey) ;
+            FIXME("Port Exist => FALSE with %u\n", ERROR_INVALID_PARAMETER);
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return FALSE;
+        }
+
+        cbPortName = (wcslen( pi->pName ) + 1) * sizeof(WCHAR);
+
+        // Create a new LOCALMON_PORT structure for it.
+        pPort = DllAllocSplMem(sizeof(LOCALMON_PORT) + cbPortName);
+        if (!pPort)
+        {
+            dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+            RegCloseKey( hKey );
+            goto Cleanup;
+        }
+
+        pPort->Sig = SIGLCMPORT;
+        pPort->hFile = INVALID_HANDLE_VALUE;
+        pPort->pLocalmon = pLocalmon;
+        pPort->pwszPortName = wcscpy( (PWSTR)(pPort+1), pi->pName );
+
+        // Insert it into the Registry list.
+        InsertTailList(&pLocalmon->RegistryPorts, &pPort->Entry);
+
+        dwErrorCode = RegSetValueExW( hKey, pi->pName, 0, REG_SZ, (const BYTE *) L"", sizeof(L"") );
+        RegCloseKey( hKey );
+    }
+
+Cleanup:
+    if (dwErrorCode != ERROR_SUCCESS) SetLastError(ERROR_INVALID_PARAMETER);
+
+    FIXME("LocalmonAddPortEx => %u with %u\n", (dwErrorCode == ERROR_SUCCESS), GetLastError());
+
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
+// Fallback Throw Back code....
+//
+// This is pre-w2k support, seems to be moved into LocalUI.
+//
+//
+
+BOOL WINAPI
+LocalmonAddPort( HANDLE hMonitor, LPWSTR pName, HWND hWnd, LPWSTR pMonitorName )
+{
+    DWORD res, cbPortName;
+    HKEY hroot;
+    PLOCALMON_HANDLE pLocalmon = (PLOCALMON_HANDLE)hMonitor;
+    PLOCALMON_PORT pPort;
+    WCHAR PortName[MAX_PATH] = {0}; // Need to use a Dialog to get name.
+
+    FIXME("LocalmonAddPort : %s\n", debugstr_w( (LPWSTR) pMonitorName ) );
+
+    res = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Ports", &hroot);
+    if (res == ERROR_SUCCESS)
+    {
+        if ( DoesPortExist( PortName ) )
+        {
+            RegCloseKey(hroot);
+            FIXME("=> %u\n", ERROR_ALREADY_EXISTS);
+            res = ERROR_ALREADY_EXISTS;
+            goto Cleanup;
+        }
+
+        cbPortName = (wcslen( PortName ) + 1) * sizeof(WCHAR);
+
+        // Create a new LOCALMON_PORT structure for it.
+        pPort = DllAllocSplMem(sizeof(LOCALMON_PORT) + cbPortName);
+        if (!pPort)
+        {
+            res = ERROR_NOT_ENOUGH_MEMORY;
+            RegCloseKey( hroot );
+            goto Cleanup;
+        }
+
+        pPort->Sig = SIGLCMPORT;
+        pPort->hFile = INVALID_HANDLE_VALUE;
+        pPort->pLocalmon = pLocalmon;
+        pPort->pwszPortName = wcscpy( (PWSTR)(pPort+1), PortName );
+
+        // Insert it into the Registry list.
+        InsertTailList(&pLocalmon->RegistryPorts, &pPort->Entry);
+
+        res = RegSetValueExW(hroot, PortName, 0, REG_SZ, (const BYTE *) L"", sizeof(L""));
+        RegCloseKey(hroot);
+    }
+
+    FIXME("=> %u\n", res);
+
+Cleanup:
+    SetLastError(res);
+    return (res == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+LocalmonConfigurePort( HANDLE hMonitor, LPWSTR pName, HWND hWnd, LPWSTR pPortName )
+{
+    //// See ConfigurePortUI
+    FIXME("LocalmonConfigurePort : %s\n", debugstr_w( pPortName ) );
+    return FALSE;
+}
+
+BOOL WINAPI
+LocalmonDeletePort( HANDLE hMonitor, LPWSTR pName, HWND hWnd, LPWSTR pPortName )
+{
+    DWORD res;
+    HKEY hroot;
+    PLOCALMON_HANDLE pLocalmon = (PLOCALMON_HANDLE)hMonitor;
+    PLOCALMON_PORT pPort;
+
+    FIXME("LocalmonDeletePort : %s\n", debugstr_w( pPortName ) );
+
+    res = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Ports", &hroot);
+    if ( res == ERROR_SUCCESS )
+    {
+        res = RegDeleteValueW(hroot, pPortName );
+
+        RegCloseKey(hroot);
+
+        pPort = _FindPort( pLocalmon, pPortName );
+        if ( pPort )
+        {
+            EnterCriticalSection(&pPort->pLocalmon->Section);
+            RemoveEntryList(&pPort->Entry);
+            LeaveCriticalSection(&pPort->pLocalmon->Section);
+
+            DllFreeSplMem(pPort);
+        }
+
+        FIXME("=> %u with %u\n", res, GetLastError() );
+    }
+
+    SetLastError(res);
+    return (res == ERROR_SUCCESS);
+}
index 8b222e2..98a63ea 100644 (file)
@@ -27,6 +27,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(localmon);
 
 #include "resource.h"
 
+#define SIGLCMMON  'FrCN'
+#define SIGLCMPORT 'FrHK'
+
 // Structures
 /**
  * Describes the monitor handle returned by InitializePrintMonitor2.
@@ -35,6 +38,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(localmon);
 typedef struct _LOCALMON_HANDLE
 {
     CRITICAL_SECTION Section;       /** Critical Section for modifying or reading the ports. */
+    DWORD Sig;
     LIST_ENTRY FilePorts;           /** Ports created when a document is printed on FILE: and the user entered a file name. */
     LIST_ENTRY RegistryPorts;       /** Valid ports loaded from the local registry. */
     LIST_ENTRY XcvHandles;          /** Xcv handles created with LocalmonXcvOpenPort. */
@@ -48,6 +52,9 @@ LOCALMON_HANDLE, *PLOCALMON_HANDLE;
 typedef struct _LOCALMON_PORT
 {
     LIST_ENTRY Entry;
+    PWSTR pwszPortName;             /** The name of this port including the trailing colon. Empty for virtual file ports. */
+    PLOCALMON_HANDLE pLocalmon;     /** Pointer to the parent LOCALMON_HANDLE structure. */
+    DWORD Sig;
     enum {
         PortType_Other = 0,         /** Any port that doesn't belong into the other categories (default). */
         PortType_FILE,              /** A port created when a document is printed on FILE: and the user entered a file name. */
@@ -59,9 +66,7 @@ typedef struct _LOCALMON_PORT
     DWORD dwJobID;                  /** ID of the printing job we are processing (for later reporting progress using SetJobW). */
     HANDLE hFile;                   /** Handle to the opened port or INVALID_HANDLE_VALUE if it isn't currently opened. */
     HANDLE hPrinter;                /** Handle to the printer for the job on this port (for using SetJobW). */
-    PLOCALMON_HANDLE pLocalmon;     /** Pointer to the parent LOCALMON_HANDLE structure. */
     PWSTR pwszMapping;              /** The current mapping of the DOS Device corresponding to this port at the time _CreateNonspooledPort has been called. */
-    PWSTR pwszPortName;             /** The name of this port including the trailing colon. Empty for virtual file ports. */
 }
 LOCALMON_PORT, *PLOCALMON_PORT;
 
@@ -95,11 +100,16 @@ BOOL WINAPI LocalmonReadPort(HANDLE hPort, PBYTE pBuffer, DWORD cbBuffer, PDWORD
 BOOL WINAPI LocalmonSetPortTimeOuts(HANDLE hPort, LPCOMMTIMEOUTS lpCTO, DWORD Reserved);
 BOOL WINAPI LocalmonStartDocPort(HANDLE hPort, PWSTR pPrinterName, DWORD JobId, DWORD Level, PBYTE pDocInfo);
 BOOL WINAPI LocalmonWritePort(HANDLE hPort, PBYTE pBuffer, DWORD cbBuf, PDWORD pcbWritten);
+BOOL WINAPI LocalmonAddPort( HANDLE hMonitor, LPWSTR pName, HWND hWnd, LPWSTR pMonitorName );
+BOOL WINAPI LocalmonAddPortEx( HANDLE hMonitor, LPWSTR pName, DWORD Level, LPBYTE lpBuffer, LPWSTR lpMonitorName );
+BOOL WINAPI LocalmonConfigurePort( HANDLE hMonitor, LPWSTR pName, HWND hWnd, LPWSTR pPortName );
+BOOL WINAPI LocalmonDeletePort( HANDLE hMonitor, LPWSTR pName, HWND hWnd, LPWSTR pPortName );
 
 // tools.c
 BOOL DoesPortExist(PCWSTR pwszPortName);
 DWORD GetLPTTransmissionRetryTimeout(VOID);
 DWORD GetPortNameWithoutColon(PCWSTR pwszPortName, PWSTR* ppwszPortNameWithoutColon);
+DWORD GetTypeFromName(LPCWSTR name);
 
 // xcv.c
 BOOL WINAPI LocalmonXcvClosePort(HANDLE hXcv);
index 0a5a797..9342225 100644 (file)
@@ -164,3 +164,97 @@ GetPortNameWithoutColon(PCWSTR pwszPortName, PWSTR* ppwszPortNameWithoutColon)
 
     return ERROR_SUCCESS;
 }
+
+/**
+ * @name _IsNEPort
+ *
+ * Checks if the given port name is a virtual Ne port.
+ * A virtual Ne port may appear in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ports and can have the formats
+ * Ne00:, Ne01:, Ne-02:, Ne456:
+ * This check is extra picky to not cause false positives (like file name ports starting with "Ne").
+ *
+ * @param pwszPortName
+ * The port name to check.
+ *
+ * @return
+ * TRUE if this is definitely a virtual Ne port, FALSE if not.
+ */
+static __inline BOOL
+_IsNEPort(PCWSTR pwszPortName)
+{
+    PCWSTR p = pwszPortName;
+
+    // First character needs to be 'N' (uppercase or lowercase)
+    if (*p != L'N' && *p != L'n')
+        return FALSE;
+
+    // Next character needs to be 'E' (uppercase or lowercase)
+    p++;
+    if (*p != L'E' && *p != L'e')
+        return FALSE;
+
+    // An optional hyphen may follow now.
+    p++;
+    if (*p == L'-')
+        p++;
+
+    // Now an arbitrary number of digits may follow.
+    while (*p >= L'0' && *p <= L'9')
+        p++;
+
+    // Finally, the virtual Ne port must be terminated by a colon.
+    if (*p != ':')
+        return FALSE;
+
+    // If this is the end of the string, we have a virtual Ne port.
+    p++;
+    return (*p == L'\0');
+}
+
+DWORD
+GetTypeFromName(LPCWSTR name)
+{
+    HANDLE  hfile;
+
+    if (!wcsncmp(name, L"LPT", ARRAYSIZE(L"LPT") - 1) )
+        return PORT_IS_LPT;
+
+    if (!wcsncmp(name, L"COM", ARRAYSIZE(L"COM") - 1) )
+        return PORT_IS_COM;
+
+    if (!lstrcmpW(name, L"FILE:") )
+        return PORT_IS_FILE;
+
+//    if (name[0] == '/')
+//        return PORT_IS_UNIXNAME;
+
+//    if (name[0] == '|')
+//        return PORT_IS_PIPE;
+
+    if ( _IsNEPort( name ) )
+        return PORT_IS_VNET;
+
+    if (!wcsncmp(name, L"XPS", ARRAYSIZE(L"XPS") - 1))
+        return PORT_IS_XPS;
+
+    /* Must be a file or a directory. Does the file exist ? */
+    hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+
+    FIXME("%p for OPEN_EXISTING on %s\n", hfile, debugstr_w(name));
+
+    if (hfile == INVALID_HANDLE_VALUE)
+    {
+        /* Can we create the file? */
+        hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
+        FIXME("%p for OPEN_ALWAYS\n", hfile);
+    }
+
+    if (hfile != INVALID_HANDLE_VALUE)
+    {
+        CloseHandle(hfile); FIXME("PORT_IS_FILENAME %d\n",PORT_IS_FILENAME);
+        return PORT_IS_FILENAME;
+    }
+    FIXME("PORT_IS_UNKNOWN %d\n",PORT_IS_UNKNOWN);
+    /* We can't use the name. use GetLastError() for the reason */
+    return PORT_IS_UNKNOWN;
+}
index a726f3b..25635c3 100644 (file)
 static DWORD
 _HandleAddPort(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded)
 {
-    return ERROR_CALL_NOT_IMPLEMENTED;
+    DWORD res, cbPortName;
+    HKEY hroot;
+    HKEY hToken = NULL;
+    PLOCALMON_PORT pPort;
+    PLOCALMON_HANDLE pLocalmon = pXcv->pLocalmon;
+    PWSTR PortName = (PWSTR)pInputData;
+
+    FIXME("LcmXcvAddPort : %s\n", debugstr_w( (LPWSTR) PortName ) );
+
+    if (!pLocalmon )
+    {
+        res = ERROR_INVALID_PARAMETER;
+        goto Cleanup;
+    }
+
+    // This action can only happen at SERVER_ACCESS_ADMINISTER access level.
+    if (!(pXcv->GrantedAccess & SERVER_ACCESS_ADMINISTER))
+    {
+        res = ERROR_ACCESS_DENIED;
+        goto Cleanup;
+    }
+
+    // Switch to the SYSTEM context for modifying the registry.
+    hToken = RevertToPrinterSelf();
+    if (!hToken)
+    {
+        res = GetLastError();
+        ERR("RevertToPrinterSelf failed with error %lu!\n", res);
+        goto Cleanup;
+    }
+
+    res = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Ports", &hroot);
+    if (res == ERROR_SUCCESS)
+    {
+        if ( DoesPortExist( PortName ) )
+        {
+            RegCloseKey(hroot);
+            FIXME("=> %u\n", ERROR_ALREADY_EXISTS);
+            res = ERROR_ALREADY_EXISTS;
+            goto Cleanup;
+        }
+
+        cbPortName = (wcslen( PortName ) + 1) * sizeof(WCHAR);
+
+        // Create a new LOCALMON_PORT structure for it.
+        pPort = DllAllocSplMem(sizeof(LOCALMON_PORT) + cbPortName);
+        if (!pPort)
+        {
+            res = ERROR_NOT_ENOUGH_MEMORY;
+            RegCloseKey( hroot );
+            goto Cleanup;
+        }
+        memset( pPort, 0, sizeof(LOCALMON_PORT) + cbPortName );
+
+        pPort->hFile = INVALID_HANDLE_VALUE;
+        pPort->pLocalmon = pLocalmon;
+        pPort->pwszPortName = wcscpy( (PWSTR)(pPort+1), PortName );
+
+        // Insert it into the Registry list.
+        InsertTailList(&pLocalmon->RegistryPorts, &pPort->Entry);
+
+        res = RegSetValueExW(hroot, PortName, 0, REG_SZ, (const BYTE *) L"", sizeof(L""));
+        RegCloseKey(hroot);
+    }
+
+    FIXME("=> %u\n", res);
+
+Cleanup:
+    if (hToken) ImpersonatePrinterClient(hToken);
+    SetLastError(res);
+    return res;
 }
 
 /**
@@ -96,7 +166,79 @@ Cleanup:
 static DWORD
 _HandleDeletePort(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded)
 {
-    return ERROR_CALL_NOT_IMPLEMENTED;
+    DWORD res;
+    HKEY hroot;
+    HKEY hToken = NULL;
+    PLOCALMON_HANDLE pLocalmon = pXcv->pLocalmon;
+    PLOCALMON_PORT pPort = NULL;
+    PLIST_ENTRY pEntry;
+    PWSTR pPortName = (PWSTR)pInputData;
+
+    FIXME("LcmXcvDeletePort : %s\n", debugstr_w( pPortName ) );
+
+    if (!pLocalmon )
+    {
+        res = ERROR_INVALID_PARAMETER;
+        goto Cleanup;
+    }
+
+    // This action can only happen at SERVER_ACCESS_ADMINISTER access level.
+    if (!(pXcv->GrantedAccess & SERVER_ACCESS_ADMINISTER))
+    {
+        res = ERROR_ACCESS_DENIED;
+        goto Cleanup;
+    }
+
+    // Switch to the SYSTEM context for modifying the registry.
+    hToken = RevertToPrinterSelf();
+    if (!hToken)
+    {
+        res = GetLastError();
+        ERR("RevertToPrinterSelf failed with error %lu!\n", res);
+        goto Cleanup;
+    }
+
+    res = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Ports", &hroot);
+    if ( res == ERROR_SUCCESS )
+    {
+        res = RegDeleteValueW(hroot, pPortName );
+
+        RegCloseKey(hroot);
+
+        if ( res == ERROR_SUCCESS )
+        {
+            EnterCriticalSection(&pLocalmon->Section);
+
+            if (!IsListEmpty(&pLocalmon->RegistryPorts) )
+            {
+                for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink)
+                {
+                    pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry);
+
+                    if (wcscmp(pPort->pwszPortName, pPortName) == 0)
+                        break;
+                }
+            }
+
+            LeaveCriticalSection(&pLocalmon->Section);
+
+            if ( pPort )
+            {
+                FIXME("LcmXcvDeletePort removed Port Entry\n");
+                EnterCriticalSection(&pPort->pLocalmon->Section);
+                RemoveEntryList(&pPort->Entry);
+                LeaveCriticalSection(&pPort->pLocalmon->Section);
+
+                DllFreeSplMem(pPort);
+            }
+        }
+        FIXME("LcmXcvDeletePort => %u with %u\n", res, GetLastError() );
+    }
+
+Cleanup:
+    if (hToken) ImpersonatePrinterClient(hToken);
+    SetLastError(res);
+    return res;
 }
 
 /**
@@ -202,7 +344,7 @@ _HandleMonitorUI(PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
     const WCHAR wszMonitorUI[] = L"LocalUI.dll";
 
     // Sanity checks
-    if (!pOutputData || !pcbOutputNeeded)
+    if (!pcbOutputNeeded)
         return ERROR_INVALID_PARAMETER;
 
     *pcbOutputNeeded = sizeof(wszMonitorUI);
@@ -211,6 +353,9 @@ _HandleMonitorUI(PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
     if (cbOutputData < *pcbOutputNeeded)
         return ERROR_INSUFFICIENT_BUFFER;
 
+    if (!pOutputData)
+        return ERROR_INVALID_PARAMETER;
+
     // Copy the string.
     CopyMemory(pOutputData, wszMonitorUI, sizeof(wszMonitorUI));
     return ERROR_SUCCESS;
@@ -257,7 +402,21 @@ _HandlePortExists(PBYTE pInputData, PBYTE pOutputData, DWORD cbOutputData, PDWOR
 static DWORD
 _HandlePortIsValid(PBYTE pInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
 {
-    return ERROR_CALL_NOT_IMPLEMENTED;
+    DWORD res;
+
+    TRACE("HandlePortIsValid : pInputData %s\n", debugstr_w( (LPWSTR) pInputData));
+
+    res = GetTypeFromName((LPCWSTR) pInputData);
+
+    TRACE("HandlePortIsValid : detected as %u\n",  res);
+
+    /* names, that we have recognized, are valid */
+    if (res) return ERROR_SUCCESS;
+
+    TRACE("=> %u\n", GetLastError());
+
+    /* ERROR_ACCESS_DENIED, ERROR_PATH_NOT_FOUND or something else */
+    return GetLastError();
 }
 
 /**
@@ -354,7 +513,9 @@ LocalmonXcvClosePort(HANDLE hXcv)
     }
 
     // Remove it from the list and free the memory.
+    LeaveCriticalSection(&pXcv->pLocalmon->Section);
     RemoveEntryList(&pXcv->Entry);
+    LeaveCriticalSection(&pXcv->pLocalmon->Section);
     DllFreeSplMem(pXcv);
 
     SetLastError(ERROR_SUCCESS);
@@ -364,7 +525,7 @@ LocalmonXcvClosePort(HANDLE hXcv)
 DWORD WINAPI
 LocalmonXcvDataPort(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
 {
-    TRACE("LocalmonXcvDataPort(%p, %S, %p, %lu, %p, %lu, %p)\n", hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded);
+    FIXME("LocalmonXcvDataPort(%p, %S, %p, %lu, %p, %lu, %p)\n", hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded);
 
     // Sanity checks
     if (!pszDataName)
index b8cd309..d9cdf37 100644 (file)
@@ -1,9 +1,12 @@
+remove_definitions(-D_WIN32_WINNT=0x502)
+add_definitions(-D_WIN32_WINNT=0x600)
 
 spec2def(localspl.dll localspl.spec ADD_IMPORTLIB)
 
 include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/skiplist)
 
 list(APPEND SOURCE
+    forms.c
     jobs.c
     main.c
     monitors.c
@@ -15,7 +18,8 @@ list(APPEND SOURCE
     printingthread.c
     printprocessors.c
     spoolfile.c
-    tools.c)
+    tools.c
+    xcv.c)
 
 add_library(localspl MODULE
     ${SOURCE}
@@ -25,6 +29,6 @@ add_library(localspl MODULE
 
 set_module_type(localspl win32dll UNICODE)
 target_link_libraries(localspl skiplist16 wine)
-add_importlibs(localspl advapi32 netapi32 rpcrt4 secur32 spoolss msvcrt kernel32 ntdll)
+add_importlibs(localspl user32 advapi32 advapi32_vista netapi32 rpcrt4 secur32 spoolss msvcrt kernel32 ntdll)
 add_pch(localspl precomp.h SOURCE)
 add_cd_file(TARGET localspl DESTINATION reactos/system32 FOR all)
diff --git a/win32ss/printing/providers/localspl/forms.c b/win32ss/printing/providers/localspl/forms.c
new file mode 100644 (file)
index 0000000..03c0162
--- /dev/null
@@ -0,0 +1,746 @@
+/*
+ * PROJECT:     ReactOS Spooler Router
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Functions for managing print Forms
+ * COPYRIGHT:   Copyright 2020 ReactOS
+ */
+
+#include "precomp.h"
+
+#define FORMINFOSIG '.2'
+#define FORMMAXNAMESIZE CCHDEVICENAME-1
+
+typedef struct _FORM_INFO_LIST
+{
+    LIST_ENTRY List;
+    DWORD Sig;
+    DWORD Index;
+    FORM_INFO_2W;
+} FORM_INFO_LIST, *PFORM_INFO_LIST;
+
+LIST_ENTRY FormList;
+static DWORD _dwLastForm;
+
+// Local Constants
+static DWORD dwFormInfo1Offsets[] = {
+    FIELD_OFFSET(FORM_INFO_1W, pName),
+    MAXDWORD
+};
+
+static DWORD dwFormInfo2Offsets[] = {
+    FIELD_OFFSET(FORM_INFO_2W, pName),
+    FIELD_OFFSET(FORM_INFO_2W, pKeyword),
+    FIELD_OFFSET(FORM_INFO_2W, pMuiDll),
+    FIELD_OFFSET(FORM_INFO_2W, pDisplayName),
+    MAXDWORD
+};
+
+
+// Built in Form names
+WCHAR wszLetter[] = L"Letter";
+WCHAR wszLetterSmall[] = L"Letter Small";
+WCHAR wszTabloid[] = L"Tabloid";
+WCHAR wszLedger[] = L"Ledger";
+WCHAR wszLegal[] = L"Legal";
+WCHAR wszStatement[] = L"Statement";
+WCHAR wszExecutive[] = L"Executive";
+WCHAR wszA3[] = L"A3";
+WCHAR wszA4[] = L"A4";
+WCHAR wszA4Small[] = L"A4 Small";
+WCHAR wszA5[] = L"A5";
+WCHAR wszB4JIS[] = L"B4 (JIS)";
+WCHAR wszB5JIS[] = L"B5 (JIS)";
+WCHAR wszFolio[] = L"Folio";
+WCHAR wszQuarto[] = L"Quarto";
+WCHAR wsz10x14[] = L"10 x 14";
+WCHAR wsz11x17[] = L"11 x 17";
+WCHAR wszNote[] = L"Note";
+WCHAR wszEnvelope9[] = L"Envelope #9";
+WCHAR wszEnvelope10[] = L"Envelope #10";
+WCHAR wszEnvelope11[] = L"Envelope #11";
+WCHAR wszEnvelope12[] = L"Envelope #12";
+WCHAR wszEnvelope14[] = L"Envelope #14";
+WCHAR wszCsizesheet[] = L"C size sheet";
+WCHAR wszDsizesheet[] = L"D size sheet";
+WCHAR wszEsizesheet[] = L"E size sheet";
+WCHAR wszEnvelopeDL[] = L"Envelope DL";
+WCHAR wszEnvelopeC5[] = L"Envelope C5";
+WCHAR wszEnvelopeC3[] = L"Envelope C3";
+WCHAR wszEnvelopeC4[] = L"Envelope C4";
+WCHAR wszEnvelopeC6[] = L"Envelope C6";
+WCHAR wszEnvelope65[] = L"Envelope 65";
+WCHAR wszEnvelopeB4[] = L"Envelope B4";
+WCHAR wszEnvelopeB5[] = L"Envelope B5";
+WCHAR wszEnvelopeB6[] = L"Envelope B6";
+WCHAR wszEnvelope[] = L"Envelope";
+WCHAR wszEnvelopeMonarch[] = L"Envelope Monarch";
+WCHAR wsz634Envelope[] = L"6 3/4 Envelope";
+WCHAR wszUSStdFanfold[] = L"US Std Fanfold";
+WCHAR wszGermanStdFanfold[] = L"German Std Fanfold";
+WCHAR wszGermanLegalFanfold[] = L"German Legal Fanfold";
+WCHAR wszB4ISO[] = L"B4 (ISO)";
+WCHAR wszJapanesePostcard[] = L"Japanese Postcard";
+WCHAR wsz9x11[] = L"9 x 11";
+WCHAR wsz10x11[] = L"10 x 11";
+WCHAR wsz15x11[] = L"15 x 11";
+WCHAR wszEnvelopeInvite[] = L"Envelope Invite";
+WCHAR wszReserved48[] = L"Reserved48";
+WCHAR wszReserved49[] = L"Reserved49";
+WCHAR wszLetterExtra[] = L"Letter Extra";
+WCHAR wszLegalExtra[] = L"Legal Extra";
+WCHAR wszTabloidExtra[] = L"Tabloid Extra";
+WCHAR wszA4Extra[] = L"A4 Extra";
+WCHAR wszLetterTransverse[] = L"Letter Transverse";
+WCHAR wszA4Transverse[] = L"A4 Transverse";
+WCHAR wszLetterExtraTransverse[] = L"Letter Extra Transverse";
+WCHAR wszSuperA[] = L"Super A";
+WCHAR wszSuperB[] = L"Super B";
+WCHAR wszLetterPlus[] = L"Letter Plus";
+WCHAR wszA4Plus[] = L"A4 Plus";
+WCHAR wszA5Transverse[] = L"A5 Transverse";
+WCHAR wszB5JISTransverse[] = L"B5 (JIS) Transverse";
+WCHAR wszA3Extra[] = L"A3 Extra";
+WCHAR wszA5Extra[] = L"A5 Extra";
+WCHAR wszB5ISOExtra[] = L"B5 (ISO) Extra";
+WCHAR wszA0[] = L"A0";
+WCHAR wszA3Transverse[] = L"A3 Transverse";
+WCHAR wszA3ExtraTransverse[] = L"A3 Extra Transverse";
+WCHAR wszJapaneseDoublePostcard[] = L"Japanese Double Postcard";
+WCHAR wszA1[] = L"A1";
+WCHAR wszJapaneseEnvelopeKaku2[] = L"Japanese Envelope Kaku #2";
+WCHAR wszJapaneseEnvelopeKaku3[] = L"Japanese Envelope Kaku #3";
+WCHAR wszJapaneseEnvelopeChou3[] = L"Japanese Envelope Chou #3";
+WCHAR wszJapaneseEnvelopeChou4[] = L"Japanese Envelope Chou #4";
+WCHAR wszLetterRotated[] = L"Letter Rotated";
+WCHAR wszA3Rotated[] = L"A3 Rotated";
+WCHAR wszA4Rotated[] = L"A4 Rotated";
+WCHAR wszA5Rotated[] = L"A5 Rotated";
+WCHAR wszB4JISRotated[] = L"B4 (JIS) Rotated";
+WCHAR wszB5JISRotated[] = L"B5 (JIS) Rotated";
+WCHAR wszJapanesePostcardRotated[] = L"Japanese Postcard Rotated";
+WCHAR wszDoubleJapanPostcardRotated[] = L"Double Japan Postcard Rotated";
+WCHAR wsA6Rotatedz[] = L"A6 Rotated";
+WCHAR wszJapanEnvelopeKaku2Rotated[] = L"Japan Envelope Kaku #2 Rotated";
+WCHAR wszJapanEnvelopeKaku3Rotated[] = L"Japan Envelope Kaku #3 Rotated";
+WCHAR wszJapanEnvelopeChou3Rotated[] = L"Japan Envelope Chou #3 Rotated";
+WCHAR wszJapanEnvelopeChou4Rotated[] = L"Japan Envelope Chou #4 Rotated";
+WCHAR wszB6JIS[] = L"B6 (JIS)";
+WCHAR wszB6JISRotated[] = L"B6 (JIS) Rotated";
+WCHAR wsz12x11[] = L"12 x 11";
+WCHAR wszJapanEnvelopeYou4[] = L"Japan Envelope You #4";
+WCHAR wszJapanEnvelopeYou4Rotated[] = L"Japan Envelope You #4 Rotated";
+WCHAR wszPRC16K[] = L"PRC 16K";
+WCHAR wszPRC32K[] = L"PRC 32K";
+WCHAR wszPRC32KBig[] = L"PRC 32K(Big)";
+WCHAR wszPRCEnvelope1[] = L"PRC Envelope #1";
+WCHAR wszPRCEnvelope2[] = L"PRC Envelope #2";
+WCHAR wszPRCEnvelope3[] = L"PRC Envelope #3";
+WCHAR wszPRCEnvelope4[] = L"PRC Envelope #4";
+WCHAR wszPRCEnvelope5[] = L"PRC Envelope #5";
+WCHAR wszPRCEnvelope6[] = L"PRC Envelope #6";
+WCHAR wszPRCEnvelope7[] = L"PRC Envelope #7";
+WCHAR wszPRCEnvelope8[] = L"PRC Envelope #8";
+WCHAR wszPRCEnvelope9[] = L"PRC Envelope #9";
+WCHAR wszPRCEnvelope10[] = L"PRC Envelope #10";
+WCHAR wszPRC16KRotated[] = L"PRC 16K Rotated";
+WCHAR wszPRC32KRotated[] = L"PRC 32K Rotated";
+WCHAR wszPRC32KBigRotated[] = L"PRC 32K(Big) Rotated";
+WCHAR wszPRCEnvelope1Rotated[] = L"PRC Envelope #1 Rotated";
+WCHAR wszPRCEnvelope2Rotated[] = L"PRC Envelope #2 Rotated";
+WCHAR wszPRCEnvelope3Rotated[] = L"PRC Envelope #3 Rotated";
+WCHAR wszPRCEnvelope4Rotated[] = L"PRC Envelope #4 Rotated";
+WCHAR wszPRCEnvelope5Rotated[] = L"PRC Envelope #5 Rotated";
+WCHAR wszPRCEnvelope6Rotated[] = L"PRC Envelope #6 Rotated";
+WCHAR wszPRCEnvelope7Rotated[] = L"PRC Envelope #7 Rotated";
+WCHAR wszPRCEnvelope8Rotated[] = L"PRC Envelope #8 Rotated";
+WCHAR wszPRCEnvelope9Rotated[] = L"PRC Envelope #9 Rotated";
+WCHAR wszPRCEnvelope10Rotated[] = L"PRC Envelope #10 Rotated";
+
+// Built in Forms
+FORM_INFO_1W BuiltInForms[] =
+{
+    { FORM_USER, wszLetter,                    {215900, 279400},{ 0, 0, 215900, 279400}},
+    { FORM_USER, wszLetterSmall,               {215900, 279400},{ 0, 0, 215900, 279400}},
+    { FORM_USER, wszTabloid,                   {279400, 431800},{ 0, 0, 279400, 431800}},
+    { FORM_USER, wszLedger,                    {431800, 279400},{ 0, 0, 431800, 279400}},
+    { FORM_USER, wszLegal,                     {215900, 355600},{ 0, 0, 215900, 355600}},
+    { FORM_USER, wszStatement,                 {139700, 215900},{ 0, 0, 139700, 215900}},
+    { FORM_USER, wszExecutive,                 {184150, 266700},{ 0, 0, 184150, 266700}},
+    { FORM_USER, wszA3,                        {297000, 420000},{ 0, 0, 297000, 420000}},
+    { FORM_USER, wszA4,                        {210000, 297000},{ 0, 0, 210000, 297000}},
+    { FORM_USER, wszA4Small,                   {210000, 297000},{ 0, 0, 210000, 297000}},
+    { FORM_USER, wszA5,                        {148000, 210000},{ 0, 0, 148000, 210000}},
+    { FORM_USER, wszB4JIS,                     {257000, 364000},{ 0, 0, 257000, 364000}},
+    { FORM_USER, wszB5JIS,                     {182000, 257000},{ 0, 0, 182000, 257000}},
+    { FORM_USER, wszFolio,                     {215900, 330200},{ 0, 0, 215900, 330200}},
+    { FORM_USER, wszQuarto,                    {215000, 275000},{ 0, 0, 215000, 275000}},
+    { FORM_USER, wsz10x14,                     {254000, 355600},{ 0, 0, 254000, 355600}},
+    { FORM_USER, wsz11x17,                     {279400, 431800},{ 0, 0, 279400, 431800}},
+    { FORM_USER, wszNote,                      {215900, 279400},{ 0, 0, 215900, 279400}},
+    { FORM_USER, wszEnvelope9,                 { 98425, 225425},{ 0, 0,  98425, 225425}},
+    { FORM_USER, wszEnvelope10,                {104775, 241300},{ 0, 0, 104775, 241300}},
+    { FORM_USER, wszEnvelope11,                {114300, 263525},{ 0, 0, 114300, 263525}},
+    { FORM_USER, wszEnvelope12,                {120650, 279400},{ 0, 0, 120650, 279400}},
+    { FORM_USER, wszEnvelope14,                {127000, 292100},{ 0, 0, 127000, 292100}},
+    { FORM_USER, wszCsizesheet,                {431800, 558800},{ 0, 0, 431800, 558800}},
+    { FORM_USER, wszDsizesheet,                {558800, 863600},{ 0, 0, 558800, 863600}},
+    { FORM_USER, wszEsizesheet,                {863600,1117600},{ 0, 0, 863600,1117600}},
+    { FORM_USER, wszEnvelopeDL,                {110000, 220000},{ 0, 0, 110000, 220000}},
+    { FORM_USER, wszEnvelopeC5,                {162000, 229000},{ 0, 0, 162000, 229000}},
+    { FORM_USER, wszEnvelopeC3,                {324000, 458000},{ 0, 0, 324000, 458000}},
+    { FORM_USER, wszEnvelopeC4,                {229000, 324000},{ 0, 0, 229000, 324000}},
+    { FORM_USER, wszEnvelopeC6,                {114000, 162000},{ 0, 0, 114000, 162000}},
+    { FORM_USER, wszEnvelope65,                {114000, 229000},{ 0, 0, 114000, 229000}},
+    { FORM_USER, wszEnvelopeB4,                {250000, 353000},{ 0, 0, 250000, 353000}},
+    { FORM_USER, wszEnvelopeB5,                {176000, 250000},{ 0, 0, 176000, 250000}},
+    { FORM_USER, wszEnvelopeB6,                {176000, 125000},{ 0, 0, 176000, 125000}},
+    { FORM_USER, wszEnvelope,                  {110000, 230000},{ 0, 0, 110000, 230000}},
+    { FORM_USER, wszEnvelopeMonarch,           { 98425, 190500},{ 0, 0,  98425, 190500}},
+    { FORM_USER, wsz634Envelope,               { 92075, 165100},{ 0, 0,  92075, 165100}},
+    { FORM_USER, wszUSStdFanfold,              {377825, 279400},{ 0, 0, 377825, 279400}},
+    { FORM_USER, wszGermanStdFanfold,          {215900, 304800},{ 0, 0, 215900, 304800}},
+    { FORM_USER, wszGermanLegalFanfold,        {215900, 330200},{ 0, 0, 215900, 330200}},
+// add more, I'm lazy
+    { FORM_USER, wszDoubleJapanPostcardRotated,{148000, 200000},{ 0, 0, 148000, 200000}},
+//
+    { FORM_USER, wszPRCEnvelope10Rotated,      {458000, 324009},{ 0, 0, 458000, 324009}},
+    { FORM_USER, 0,                            {     0,      0},{ 0, 0,      0,      0}}
+};
+
+//
+// Form information Registry entry stucture, in correct format.
+//
+// Example : 11 x 17  REG_BINARY  68 43 04 00 b8 96 06 00 00 00 00 00 00 00 00 00 68 43 04 00 b8 96 06 00 01 00 00 00 02 00 00 00
+//                               [        Size           |               ImageableArea                   | Index 1 + |   Flags   ] , is FORM_PRINTER.
+//
+typedef struct _REGISTRYFORMINFO
+{
+    SIZEL Size;
+    RECTL ImageableArea;
+    DWORD Index;
+    DWORD Flags;
+} REGISTRYFORMINFO, *PREGISTRYFORMINFO;
+
+HKEY hFormCKey = NULL;
+HKEY hFormsKey = NULL;
+
+BOOL
+InitializeFormList(VOID)
+{
+    DWORD dwErrorCode;
+    PFORM_INFO_LIST pfil;
+    REGISTRYFORMINFO rfi;
+
+    FIXME("InitializeFormList\n");
+
+    dwErrorCode = (DWORD)RegCreateKeyExW( HKEY_LOCAL_MACHINE,
+                                         L"SYSTEM\\CurrentControlSet\\Control\\Print\\Forms",
+                                          0,
+                                          NULL,
+                                          REG_OPTION_VOLATILE,
+                                          KEY_ALL_ACCESS,
+                                          NULL,
+                                         &hFormCKey,
+                                          NULL ); // KEY_OPENED_EXISTING_KEY );
+
+    if ( dwErrorCode != ERROR_SUCCESS && dwErrorCode != ERROR_ALREADY_EXISTS )
+    {
+        ERR("RegCreateKeyExW failed for the Forms with error %lu!\n", dwErrorCode);
+        goto Cleanup;
+    }
+
+    // Open some registry keys and leave them open. We need them multiple times throughout the Local Spooler.
+    dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Print\\Forms", 0, KEY_ALL_ACCESS, &hFormsKey);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RegOpenKeyExW failed for \"Forms\" with error %lu!\n", dwErrorCode);
+        goto Cleanup;
+    }
+
+    _dwLastForm = 1;
+
+    InitializeListHead(&FormList);
+
+    {
+        int i = 0, Size;
+        while ( BuiltInForms[ i ].pName != NULL )
+        {
+            TRACE("InitializeFormList L s %S\n",BuiltInForms[ i ].pName );
+
+            Size = sizeof(FORM_INFO_LIST) + ((wcslen(BuiltInForms[ i ].pName) + 1) * sizeof(WCHAR));
+
+            pfil = DllAllocSplMem( Size );
+
+            pfil->pName         = wcscpy( (PWSTR)(pfil+1), BuiltInForms[ i ].pName );
+            pfil->Flags         = BuiltInForms[ i ].Flags;
+            pfil->Size          = BuiltInForms[ i ].Size;
+            pfil->ImageableArea = BuiltInForms[ i ].ImageableArea;
+            pfil->Sig           = FORMINFOSIG;
+            pfil->Index         = _dwLastForm++;
+            pfil->pKeyword      = NULL;
+            pfil->StringType    = STRING_NONE;
+            pfil->pMuiDll       = NULL;
+            pfil->dwResourceId  = 0;
+            pfil->pDisplayName  = NULL;
+            pfil->wLangId       = 0;
+
+            InsertTailList( &FormList, &pfil->List );
+
+            rfi.Size          = pfil->Size;
+            rfi.ImageableArea = pfil->ImageableArea;
+            rfi.Index         = pfil->Index;
+            rfi.Flags         = pfil->Flags;
+
+            dwErrorCode = RegSetValueExW( hFormsKey, pfil->pName, 0, REG_BINARY, (PBYTE)&rfi, sizeof( rfi ) );
+            if ( dwErrorCode == ERROR_SUCCESS )
+            {
+                TRACE("Init : RQVEW : %S added\n",pfil->pName);
+            }
+
+            i++;
+        }
+    }
+
+Cleanup:
+    return TRUE;
+}
+
+PFORM_INFO_LIST
+FASTCALL
+FindForm( WCHAR * pFormName, WCHAR * pKeyword )
+{
+    PLIST_ENTRY ListEntry;
+    PFORM_INFO_LIST pfil;
+
+    ListEntry = FormList.Flink;
+
+    while (ListEntry != &FormList)
+    {
+        pfil = CONTAINING_RECORD(ListEntry, FORM_INFO_LIST, List);
+
+        ListEntry = ListEntry->Flink;
+
+        if ( pFormName && !_wcsicmp( pfil->pName, pFormName ) )
+            return pfil;
+
+        if ( pKeyword && !_wcsicmp( (WCHAR*)pfil->pKeyword, pKeyword ) )
+            return pfil;
+    }
+    return NULL;
+}
+
+static void
+_LocalGetFormLevel1(PFORM_INFO_LIST pfil, PFORM_INFO_1W* ppFormInfo, PBYTE* ppFormInfoEnd, PDWORD pcbNeeded)
+{
+    DWORD n;
+    PCWSTR pwszStrings[1];
+
+    pwszStrings[0] = pfil->pName;
+
+    // Calculate the string lengths.
+    if (!ppFormInfo)
+    {
+        for (n = 0; n < _countof(pwszStrings); ++n)
+        {
+            *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
+        }
+
+        *pcbNeeded += sizeof(FORM_INFO_1W);
+        return;
+    }
+
+    (*ppFormInfo)->Flags         = pfil->Flags;
+    (*ppFormInfo)->Size          = pfil->Size;
+    (*ppFormInfo)->ImageableArea = pfil->ImageableArea;
+
+    // Finally copy the structure and advance to the next one in the output buffer.
+    *ppFormInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppFormInfo), dwFormInfo1Offsets, *ppFormInfoEnd);
+    (*ppFormInfo)++;
+}
+
+static void
+_LocalGetFormLevel2(PFORM_INFO_LIST pfil, PFORM_INFO_2W* ppFormInfo, PBYTE* ppFormInfoEnd, PDWORD pcbNeeded)
+{
+    DWORD n;
+    PCWSTR pwszStrings[4];
+
+    pwszStrings[0] = pfil->pName;
+    pwszStrings[1] = (PCWSTR)pfil->pKeyword;
+    pwszStrings[2] = pfil->pMuiDll;
+    pwszStrings[3] = pfil->pDisplayName;
+
+    // Calculate the string lengths.
+    if (!ppFormInfo)
+    {
+        for (n = 0; n < _countof(pwszStrings); ++n)
+        {
+            if (pwszStrings[n])
+            {
+                *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
+            }
+        }
+        *pcbNeeded += sizeof(FORM_INFO_2W);
+        return;
+    }
+
+    (*ppFormInfo)->Flags         = pfil->Flags;
+    (*ppFormInfo)->Size          = pfil->Size;
+    (*ppFormInfo)->ImageableArea = pfil->ImageableArea;
+    (*ppFormInfo)->StringType    = pfil->StringType; //// If caller is remote, set STRING_LANGPAIR always;
+    (*ppFormInfo)->dwResourceId  = pfil->dwResourceId;
+
+    // Finally copy the structure and advance to the next one in the output buffer.
+    *ppFormInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppFormInfo), dwFormInfo2Offsets, *ppFormInfoEnd);
+    (*ppFormInfo)++;
+}
+
+typedef void (*PLocalGetFormLevelFunc)(PFORM_INFO_LIST, PVOID, PBYTE*, PDWORD);
+
+static const PLocalGetFormLevelFunc pfnGetFormLevels[] = {
+    NULL,
+    (PLocalGetFormLevelFunc)&_LocalGetFormLevel1,
+    (PLocalGetFormLevelFunc)&_LocalGetFormLevel2
+};
+
+//
+// API Functions
+//
+BOOL WINAPI
+LocalAddForm(HANDLE hPrinter, DWORD Level, PBYTE pForm)
+{
+    DWORD dwErrorCode, Size, cbNeeded;
+    PFORM_INFO_LIST pfil;
+    PLOCAL_HANDLE pHandle;
+    REGISTRYFORMINFO rfi;
+    PFORM_INFO_1W pfi1w = (PFORM_INFO_1W)pForm;
+    PFORM_INFO_2W pfi2w = (PFORM_INFO_2W)pForm;
+
+    FIXME("AddForm(%p, %lu, %p)\n", hPrinter, Level, pForm);
+
+    // Check if this is a printer handle.
+    pHandle = (PLOCAL_HANDLE)hPrinter;
+    if (pHandle->HandleType != HandleType_Printer)
+    {
+        dwErrorCode = ERROR_INVALID_HANDLE;
+        goto Cleanup;
+    }
+
+    // Only support 1 & 2
+    if (Level < 1 || Level > 2)
+    {
+        // The caller supplied an invalid level.
+        dwErrorCode = ERROR_INVALID_LEVEL;
+        goto Cleanup;
+    }
+
+    pfil = FindForm( pfi1w->pName, NULL );
+    if ( pfil )
+    {
+        dwErrorCode = ERROR_FILE_EXISTS;
+        goto Cleanup;
+    }
+
+    dwErrorCode = RegQueryValueExW( hFormsKey, pfi1w->pName, NULL, NULL, NULL, &cbNeeded );
+    if ( dwErrorCode == ERROR_SUCCESS )
+    {
+        dwErrorCode = ERROR_FILE_EXISTS;
+        goto Cleanup;
+    }
+
+    if ( wcslen(pfi1w->pName) > FORMMAXNAMESIZE ) // Limit REG Name size.
+    {
+        dwErrorCode = ERROR_INVALID_PARAMETER;
+        goto Cleanup;
+    }
+
+    Size = sizeof(FORM_INFO_LIST) + ((MAX_PATH + 1) * sizeof(WCHAR));
+
+    pfil = DllAllocSplMem( Size );
+    if ( !pfil )
+    {
+        dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+        goto Cleanup;
+    }
+
+    pfil->Sig           = FORMINFOSIG;
+    pfil->Index         = _dwLastForm++;
+    pfil->pName         = wcscpy( (PWSTR)(pfil+1), pfi1w->pName );
+    pfil->Flags         = pfi1w->Flags;
+    pfil->Size          = pfi1w->Size;
+    pfil->ImageableArea = pfi1w->ImageableArea;
+    pfil->StringType    = STRING_NONE;
+
+    if ( Level > 1 )
+    {
+        pfil->pKeyword     = pfi2w->pKeyword;
+        pfil->pMuiDll      = pfi2w->pMuiDll;
+        pfil->pDisplayName = pfi2w->pDisplayName;
+        pfil->StringType   = pfi2w->StringType;
+        pfil->dwResourceId = pfi2w->dwResourceId;
+    }
+
+    rfi.Size          = pfil->Size;
+    rfi.ImageableArea = pfil->ImageableArea;
+    rfi.Index         = pfil->Index;
+    rfi.Flags         = pfil->Flags;
+
+    dwErrorCode = RegSetValueExW( hFormsKey, pfil->pName, 0, REG_BINARY, (PBYTE)&rfi, sizeof( rfi ) );
+
+    BroadcastChange(pHandle);
+
+    InsertTailList( &FormList, &pfil->List );
+
+Cleanup:
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+LocalDeleteForm(HANDLE hPrinter, PWSTR pFormName)
+{
+    DWORD dwErrorCode, cbNeeded;
+    PFORM_INFO_LIST pfil;
+    REGISTRYFORMINFO rfi;
+    PLOCAL_HANDLE pHandle;
+
+    FIXME("DeleteForm(%p, %S)\n", hPrinter, pFormName);
+
+    // Check if this is a printer handle.
+    pHandle = (PLOCAL_HANDLE)hPrinter;
+    if (pHandle->HandleType != HandleType_Printer)
+    {
+        dwErrorCode = ERROR_INVALID_HANDLE;
+        goto Cleanup;
+    }
+
+    pfil = FindForm( pFormName, NULL );
+    if ( !pfil )
+    {
+        dwErrorCode = ERROR_INVALID_PARAMETER;
+        goto Cleanup;
+    }
+
+    dwErrorCode = RegQueryValueExW( hFormsKey, pFormName, NULL, NULL, (PBYTE)&rfi, &cbNeeded );
+    if ( dwErrorCode != ERROR_SUCCESS )
+    {
+        goto Cleanup;
+    }
+
+    dwErrorCode = RegDeleteValueW(hFormsKey, pFormName);
+    if ( dwErrorCode != ERROR_SUCCESS )
+    {
+        goto Cleanup;
+    }
+
+    RemoveEntryList(&pfil->List);
+
+    DllFreeSplMem(pfil);
+
+    BroadcastChange(pHandle);
+
+    dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+LocalEnumForms(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
+{
+    DWORD dwErrorCode;
+    PFORM_INFO_LIST pfil = NULL;
+    PBYTE pEnd = &pForm[cbBuf];
+    PLOCAL_HANDLE pHandle;
+    PLIST_ENTRY ListEntry;
+
+    FIXME("EnumForms(%p, %lu, %p, %lu, %p, %p)\n", hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned);
+
+    // Check if this is a printer handle.
+    pHandle = (PLOCAL_HANDLE)hPrinter;
+    if (pHandle->HandleType != HandleType_Printer)
+    {
+        dwErrorCode = ERROR_INVALID_HANDLE;
+        goto Cleanup;
+    }
+
+    // Only support 1 & 2
+    if (Level < 1 || Level > 2)
+    {
+        // The caller supplied an invalid level.
+        dwErrorCode = ERROR_INVALID_LEVEL;
+        goto Cleanup;
+    }
+
+    // Count the required buffer size.
+    *pcbNeeded = 0;
+
+    ListEntry = FormList.Flink;
+
+    if (IsListEmpty(ListEntry))
+    {
+        dwErrorCode = ERROR_INVALID_PARAMETER;
+        goto Cleanup;
+    }
+
+    while ( ListEntry != &FormList )
+    {
+        pfil = CONTAINING_RECORD(ListEntry, FORM_INFO_LIST, List);
+        ListEntry = ListEntry->Flink;
+
+        pfnGetFormLevels[Level](pfil, NULL, NULL, pcbNeeded);
+    }
+
+    // Check if the supplied buffer is large enough.
+    if (cbBuf < *pcbNeeded)
+    {
+        ERR("Insuffisient Buffer size\n");
+        dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
+        goto Cleanup;
+    }
+
+    // Copy over the information.
+    pEnd = &pForm[*pcbNeeded];
+
+    ListEntry = FormList.Flink;
+
+    while ( ListEntry != &FormList )
+    {
+        pfil = CONTAINING_RECORD(ListEntry, FORM_INFO_LIST, List);
+        ListEntry = ListEntry->Flink;
+
+        pfnGetFormLevels[Level](pfil, &pForm, &pEnd, NULL);
+        (*pcReturned)++;
+    }
+
+    dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+LocalGetForm(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded)
+{
+    DWORD dwErrorCode;
+    PFORM_INFO_LIST pfil;
+    PBYTE pEnd = &pForm[cbBuf];
+    PLOCAL_HANDLE pHandle;
+
+    FIXME("GetForm(%p, %S, %lu, %p, %lu, %p)\n", hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded);
+
+    // Check if this is a printer handle.
+    pHandle = (PLOCAL_HANDLE)hPrinter;
+    if (pHandle->HandleType != HandleType_Printer)
+    {
+        dwErrorCode = ERROR_INVALID_HANDLE;
+        goto Cleanup;
+    }
+
+    // Only support 1 & 2
+    if (Level < 1 || Level > 2)
+    {
+        // The caller supplied an invalid level.
+        dwErrorCode = ERROR_INVALID_LEVEL;
+        goto Cleanup;
+    }
+
+    pfil = FindForm( pFormName, NULL );
+    if ( !pfil )
+    {
+        dwErrorCode = ERROR_INVALID_PARAMETER;
+        goto Cleanup;
+    }
+
+    // Count the required buffer size.
+    *pcbNeeded = 0;
+
+    pfnGetFormLevels[Level](pfil, NULL, NULL, pcbNeeded);
+
+    // Check if the supplied buffer is large enough.
+    if (cbBuf < *pcbNeeded)
+    {
+        ERR("Insuffisient Buffer size\n");
+        dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
+        goto Cleanup;
+    }
+
+    // Copy over the information.
+    pEnd = &pForm[*pcbNeeded];
+
+    pfnGetFormLevels[Level](pfil, &pForm, &pEnd, NULL);
+
+    dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+localSetForm(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm)
+{
+    DWORD dwErrorCode, cbNeeded;
+    PFORM_INFO_LIST pfil;
+    REGISTRYFORMINFO rfi;
+    PLOCAL_HANDLE pHandle;
+    PFORM_INFO_1W pfi1w = (PFORM_INFO_1W)pForm;
+    PFORM_INFO_2W pfi2w = (PFORM_INFO_2W)pForm;
+
+    FIXME("SetFormW(%p, %S, %lu, %p)\n", hPrinter, pFormName, Level, pForm);
+
+    // Check if this is a printer handle.
+    pHandle = (PLOCAL_HANDLE)hPrinter;
+    if (pHandle->HandleType != HandleType_Printer)
+    {
+        dwErrorCode = ERROR_INVALID_HANDLE;
+        goto Cleanup;
+    }
+
+    // Only support 1 & 2
+    if (Level < 1 || Level > 2)
+    {
+        // The caller supplied an invalid level.
+        dwErrorCode = ERROR_INVALID_LEVEL;
+        goto Cleanup;
+    }
+
+    pfil = FindForm( pFormName, NULL );
+    if ( !pfil )
+    {
+        dwErrorCode = ERROR_INVALID_PARAMETER;
+        goto Cleanup;
+    }
+
+    dwErrorCode = RegQueryValueExW( hFormsKey, pFormName, NULL, NULL, (PBYTE)&rfi, &cbNeeded) ;
+    if ( dwErrorCode != ERROR_SUCCESS )
+    {
+        goto Cleanup;
+    }
+
+    pfil->Flags         = pfi1w->Flags;
+    pfil->Size          = pfi1w->Size;
+    pfil->ImageableArea = pfi1w->ImageableArea;
+
+    if ( Level > 1 )
+    {
+        pfil->pKeyword     = pfi2w->pKeyword;
+        pfil->pMuiDll      = pfi2w->pMuiDll;
+        pfil->pDisplayName = pfi2w->pDisplayName;
+        pfil->StringType   = pfi2w->StringType;
+        pfil->dwResourceId = pfi2w->dwResourceId;
+    }
+
+    rfi.Size          = pfil->Size;
+    rfi.ImageableArea = pfil->ImageableArea;
+    rfi.Flags         = pfil->Flags;
+
+    dwErrorCode = RegSetValueExW( hFormsKey, pfil->pName, 0, REG_BINARY, (PBYTE)&rfi, sizeof( rfi ) );
+
+    BroadcastChange(pHandle);
+
+Cleanup:
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
index 0a47398..c54e663 100644 (file)
@@ -25,9 +25,9 @@ const DWORD dwSpoolerMinorVersion = 0;
 const WCHAR wszDefaultDocumentName[] = L"Local Downlevel Document";
 
 PCWSTR wszPrintProviderInfo[3] = {
+    L"Windows NT Local Printers",           // Description
     L"Windows NT Local Print Providor",     // Name
-    L"Locally connected Printers",          // Comment
-    L"Windows NT Local Printers"            // Description
+    L"Locally connected Printers"           // Comment
 };
 
 // Local Constants
@@ -41,10 +41,10 @@ static const PRINTPROVIDOR _PrintProviderFunctions = {
     NULL,                                       // fpSetPrinter
     LocalGetPrinter,                            // fpGetPrinter
     LocalEnumPrinters,                          // fpEnumPrinters
-    NULL,                                       // fpAddPrinterDriver
-    NULL,                                       // fpEnumPrinterDrivers
+    LocalAddPrinterDriver,                      // fpAddPrinterDriver
+    LocalEnumPrinterDrivers,                    // fpEnumPrinterDrivers
     LocalGetPrinterDriver,                      // fpGetPrinterDriver
-    NULL,                                       // fpGetPrinterDriverDirectory
+    LocalGetPrinterDriverDirectory,             // fpGetPrinterDriverDirectory
     NULL,                                       // fpDeletePrinterDriver
     NULL,                                       // fpAddPrintProcessor
     LocalEnumPrintProcessors,                   // fpEnumPrintProcessors
@@ -64,34 +64,34 @@ static const PRINTPROVIDOR _PrintProviderFunctions = {
     LocalSetPrinterData,                        // fpSetPrinterData
     NULL,                                       // fpWaitForPrinterChange
     LocalClosePrinter,                          // fpClosePrinter
-    NULL,                                       // fpAddForm
-    NULL,                                       // fpDeleteForm
-    NULL,                                       // fpGetForm
-    NULL,                                       // fpSetForm
-    NULL,                                       // fpEnumForms
+    LocalAddForm,                               // fpAddForm
+    LocalDeleteForm,                            // fpDeleteForm
+    LocalGetForm,                               // fpGetForm
+    localSetForm,                               // fpSetForm
+    LocalEnumForms,                             // fpEnumForms
     LocalEnumMonitors,                          // fpEnumMonitors
     LocalEnumPorts,                             // fpEnumPorts
-    NULL,                                       // fpAddPort
-    NULL,                                       // fpConfigurePort
-    NULL,                                       // fpDeletePort
+    LocalAddPort,                               // fpAddPort
+    LocalConfigurePort,                         // fpConfigurePort
+    LocalDeletePort,                            // fpDeletePort
     NULL,                                       // fpCreatePrinterIC
     NULL,                                       // fpPlayGdiScriptOnPrinterIC
     NULL,                                       // fpDeletePrinterIC
     NULL,                                       // fpAddPrinterConnection
     NULL,                                       // fpDeletePrinterConnection
-    NULL,                                       // fpPrinterMessageBox
-    NULL,                                       // fpAddMonitor
-    NULL,                                       // fpDeleteMonitor
+    LocalPrinterMessageBox,                     // fpPrinterMessageBox
+    LocalAddMonitor,                            // fpAddMonitor
+    LocalDeleteMonitor,                         // fpDeleteMonitor
     NULL,                                       // fpResetPrinter
-    NULL,                                       // fpGetPrinterDriverEx
+    LocalGetPrinterDriverEx,                    // fpGetPrinterDriverEx
     NULL,                                       // fpFindFirstPrinterChangeNotification
     NULL,                                       // fpFindClosePrinterChangeNotification
-    NULL,                                       // fpAddPortEx
+    LocalAddPortEx,                             // fpAddPortEx
     NULL,                                       // fpShutDown
     NULL,                                       // fpRefreshPrinterChangeNotification
     NULL,                                       // fpOpenPrinterEx
     NULL,                                       // fpAddPrinterEx
-    NULL,                                       // fpSetPort
+    LocalSetPort,                               // fpSetPort
     NULL,                                       // fpEnumPrinterData
     NULL,                                       // fpDeletePrinterData
     NULL,                                       // fpClusterSplOpen
@@ -108,8 +108,8 @@ static const PRINTPROVIDOR _PrintProviderFunctions = {
     NULL,                                       // fpAddPerMachineConnection
     NULL,                                       // fpDeletePerMachineConnection
     NULL,                                       // fpEnumPerMachineConnections
-    NULL,                                       // fpXcvData
-    NULL,                                       // fpAddPrinterDriverEx
+    LocalXcvData,                               // fpXcvData
+    LocalAddPrinterDriverEx,                    // fpAddPrinterDriverEx
     NULL,                                       // fpSplReadPrinter
     NULL,                                       // fpDriverUnloadComplete
     LocalGetSpoolFileInfo,                      // fpGetSpoolFileInfo
@@ -218,6 +218,12 @@ _InitializeLocalSpooler(void)
     if (!InitializeGlobalJobList())
         goto Cleanup;
 
+    if (!InitializeFormList())
+        goto Cleanup;
+
+    if (!InitializePrinterDrivers())
+        goto Cleanup;
+
     // Local Spooler Initialization finished successfully!
     bReturnValue = TRUE;
 
index 9a04ca7..80c52f5 100644 (file)
@@ -46,6 +46,82 @@ FindPrintMonitor(PCWSTR pwszName)
     return NULL;
 }
 
+static LONG WINAPI CreateKey(HANDLE hcKey, LPCWSTR pszSubKey, DWORD dwOptions, REGSAM samDesired, PSECURITY_ATTRIBUTES pSecurityAttributes, PHANDLE phckResult, PDWORD pdwDisposition, HANDLE hSpooler)
+{
+    FIXME("stub\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+static LONG WINAPI OpenKey(HANDLE hcKey, LPCWSTR pszSubKey, REGSAM samDesired, PHANDLE phkResult, HANDLE hSpooler)
+{
+    FIXME("stub\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+static LONG WINAPI CloseKey(HANDLE hcKey, HANDLE hSpooler)
+{
+    FIXME("stub\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+static LONG WINAPI DeleteKey(HANDLE hcKey, LPCWSTR pszSubKey, HANDLE hSpooler)
+{
+    FIXME("stub\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+static LONG WINAPI EnumKey(HANDLE hcKey, DWORD dwIndex, LPWSTR pszName, PDWORD pcchName, PFILETIME pftLastWriteTime, HANDLE hSpooler)
+{
+    FIXME("stub\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+static LONG WINAPI QueryInfoKey(HANDLE hcKey, PDWORD pcSubKeys, PDWORD pcbKey, PDWORD pcValues, PDWORD pcbValue, PDWORD pcbData, PDWORD pcbSecurityDescriptor, PFILETIME pftLastWriteTime,
+                HANDLE hSpooler)
+{
+    FIXME("stub\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+static LONG WINAPI SetValue(HANDLE hcKey, LPCWSTR pszValue, DWORD dwType, const BYTE* pData, DWORD cbData, HANDLE hSpooler)
+{
+    FIXME("stub\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+static LONG WINAPI DeleteValue(HANDLE hcKey, LPCWSTR pszValue, HANDLE hSpooler)
+{
+    FIXME("stub\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+static LONG WINAPI EnumValue(HANDLE hcKey, DWORD dwIndex, LPWSTR pszValue, PDWORD pcbValue, PDWORD pType, PBYTE pData, PDWORD pcbData, HANDLE hSpooler)
+{
+    FIXME("stub\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+static LONG WINAPI QueryValue(HANDLE hcKey, LPCWSTR pszValue, PDWORD pType, PBYTE pData, PDWORD pcbData, HANDLE hSpooler)
+{
+    FIXME("stub\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+static MONITORREG MonReg =
+{
+    sizeof(MONITORREG),
+    CreateKey,
+    OpenKey,
+    CloseKey,
+    DeleteKey,
+    EnumKey,
+    QueryInfoKey,
+    SetValue,
+    DeleteValue,
+    EnumValue,
+    QueryValue
+};
+
 BOOL
 InitializePrintMonitorList(void)
 {
@@ -124,6 +200,8 @@ InitializePrintMonitorList(void)
             goto Cleanup;
         }
 
+        memset( pPrintMonitor, 0, sizeof(LOCAL_PRINT_MONITOR));
+
         // Allocate memory for the Print Monitor Name.
         pPrintMonitor->pwszName = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR));
         if (!pPrintMonitor->pwszName)
@@ -163,6 +241,8 @@ InitializePrintMonitorList(void)
             continue;
         }
 
+        pPrintMonitor->hModule = hinstPrintMonitor;
+
         // Try to find a Level 2 initialization routine first.
         pfnInitializePrintMonitor2 = (PInitializePrintMonitor2)GetProcAddress(hinstPrintMonitor, "InitializePrintMonitor2");
         if (pfnInitializePrintMonitor2)
@@ -172,6 +252,8 @@ InitializePrintMonitorList(void)
             MonitorInit.bLocal = TRUE;
 
             // TODO: Fill the other fields.
+            MonitorInit.hckRegistryRoot = hKey;
+            MonitorInit.pMonitorReg = &MonReg;
 
             // Call the Level 2 initialization routine.
             pPrintMonitor->pMonitor = (PMONITOR2)pfnInitializePrintMonitor2(&MonitorInit, &pPrintMonitor->hMonitor);
@@ -180,7 +262,7 @@ InitializePrintMonitorList(void)
                 ERR("InitializePrintMonitor2 failed for \"%S\" with error %lu!\n", pPrintMonitor->pwszFileName, GetLastError());
                 continue;
             }
-
+            FIXME("InitializePrintMonitor2 loaded.\n");
             pPrintMonitor->bIsLevel2 = TRUE;
         }
         else
@@ -219,6 +301,8 @@ InitializePrintMonitorList(void)
 
         // Add this Print Monitor to the list.
         InsertTailList(&PrintMonitorList, &pPrintMonitor->Entry);
+        FIXME("InitializePrintMonitorList Handle %p\n",pPrintMonitor->hMonitor);
+        pPrintMonitor->refcount++;
 
         // Don't let the cleanup routine free this.
         pPrintMonitor = NULL;
@@ -253,6 +337,7 @@ Cleanup:
     return (dwErrorCode == ERROR_SUCCESS);
 }
 
+
 static void
 _LocalGetMonitorLevel1(PLOCAL_PRINT_MONITOR pPrintMonitor, PMONITOR_INFO_1W* ppMonitorInfo, PBYTE* ppMonitorInfoEnd, PDWORD pcbNeeded)
 {
@@ -367,3 +452,354 @@ Cleanup:
     SetLastError(dwErrorCode);
     return (dwErrorCode == ERROR_SUCCESS);
 }
+
+BOOL
+AddPrintMonitorList( LPCWSTR pName, LPWSTR DllName )
+{
+    const WCHAR wszMonitorsPath[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors\\";
+    const DWORD cchMonitorsPath = _countof(wszMonitorsPath) - 1;
+
+    WCHAR wszRegRoot[MAX_PATH] = {0};
+
+    DWORD cchPrintMonitorName;
+    DWORD dwErrorCode;
+    HINSTANCE hinstPrintMonitor = NULL;
+    HKEY hKey = NULL;
+    MONITORINIT MonitorInit;
+    PInitializePrintMonitor pfnInitializePrintMonitor;
+    PInitializePrintMonitor2 pfnInitializePrintMonitor2;
+    PLOCAL_PRINT_MONITOR pPrintMonitor = NULL;
+    PWSTR pwszRegistryPath = NULL;
+
+    FIXME("AddPrintMonitorList( %S, %S)\n",pName, DllName);
+
+    StringCbCopyW(wszRegRoot, sizeof(wszRegRoot), wszMonitorsPath);
+    StringCbCatW(wszRegRoot, sizeof(wszRegRoot), pName);
+
+    // Open the key containing Print Monitors.
+    dwErrorCode = (DWORD)RegOpenKeyW( HKEY_LOCAL_MACHINE, wszRegRoot, &hKey );
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RegOpenKeyExW %S failed with status %lu!\n", wszRegRoot, dwErrorCode);
+        goto Cleanup;
+    }
+
+    // Create a new LOCAL_PRINT_MONITOR structure for it.
+    pPrintMonitor = DllAllocSplMem(sizeof(LOCAL_PRINT_MONITOR));
+    if (!pPrintMonitor)
+    {
+        dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+        ERR("DllAllocSplMem failed!\n");
+        goto Cleanup;
+    }
+
+    memset( pPrintMonitor, 0, sizeof(LOCAL_PRINT_MONITOR));
+
+    // Allocate memory for the Print Monitor Name.
+    pPrintMonitor->pwszName = AllocSplStr( pName );
+    if (!pPrintMonitor->pwszName)
+    {
+        dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+        ERR("DllAllocSplMem failed!\n");
+        goto Cleanup;
+    }
+
+    cchPrintMonitorName = wcslen(pPrintMonitor->pwszName);
+
+    if ( DllName == NULL )
+    {
+        DWORD namesize;
+
+        dwErrorCode = RegQueryValueExW( hKey, L"Driver", NULL, NULL, NULL, &namesize );
+
+        if ( dwErrorCode == ERROR_SUCCESS )
+        {
+            DllName = DllAllocSplMem(namesize);
+
+            RegQueryValueExW( hKey, L"Driver", NULL, NULL, (LPBYTE)DllName, &namesize );
+
+            pPrintMonitor->pwszFileName = DllName;
+        }
+        else
+        {
+            ERR("DllName not found\n");
+            goto Cleanup;
+        }
+    }
+    else
+    {
+        pPrintMonitor->pwszFileName = AllocSplStr( DllName );
+    }
+
+    // Try to load it.
+    hinstPrintMonitor = LoadLibraryW(pPrintMonitor->pwszFileName);
+    if (!hinstPrintMonitor)
+    {
+        ERR("LoadLibraryW failed for \"%S\" with error %lu!\n", pPrintMonitor->pwszFileName, GetLastError());
+        dwErrorCode = GetLastError();
+        goto Cleanup;
+    }
+
+    pPrintMonitor->hModule = hinstPrintMonitor;
+
+    // Try to find a Level 2 initialization routine first.
+    pfnInitializePrintMonitor2 = (PInitializePrintMonitor2)GetProcAddress(hinstPrintMonitor, "InitializePrintMonitor2");
+    if (pfnInitializePrintMonitor2)
+    {
+        // Prepare a MONITORINIT structure.
+        MonitorInit.cbSize = sizeof(MONITORINIT);
+        MonitorInit.bLocal = TRUE;
+
+        // TODO: Fill the other fields.
+        MonitorInit.hckRegistryRoot = hKey;
+        MonitorInit.pMonitorReg = &MonReg;
+
+        // Call the Level 2 initialization routine.
+        pPrintMonitor->pMonitor = (PMONITOR2)pfnInitializePrintMonitor2(&MonitorInit, &pPrintMonitor->hMonitor);
+        if (!pPrintMonitor->pMonitor)
+        {
+            ERR("InitializePrintMonitor2 failed for \"%S\" with error %lu!\n", pPrintMonitor->pwszFileName, GetLastError());
+            goto Cleanup;
+        }
+
+        pPrintMonitor->bIsLevel2 = TRUE;
+    }
+    else
+    {
+        // Try to find a Level 1 initialization routine then.
+        pfnInitializePrintMonitor = (PInitializePrintMonitor)GetProcAddress(hinstPrintMonitor, "InitializePrintMonitor");
+        if (pfnInitializePrintMonitor)
+        {
+            // Construct the registry path.
+            pwszRegistryPath = DllAllocSplMem((cchMonitorsPath + 1 + cchPrintMonitorName + 1) * sizeof(WCHAR));
+            if (!pwszRegistryPath)
+            {
+                dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+                ERR("DllAllocSplMem failed!\n");
+                goto Cleanup;
+            }
+
+            CopyMemory(pwszRegistryPath, wszMonitorsPath, cchMonitorsPath * sizeof(WCHAR));
+            pwszRegistryPath[cchMonitorsPath] = L'\\';
+            CopyMemory(&pwszRegistryPath[cchMonitorsPath + 1], pPrintMonitor->pwszName, (cchPrintMonitorName + 1) * sizeof(WCHAR));
+
+            // Call the Level 1 initialization routine.
+            pPrintMonitor->pMonitor = (LPMONITOREX)pfnInitializePrintMonitor(pwszRegistryPath);
+            if (!pPrintMonitor->pMonitor)
+            {
+                ERR("InitializePrintMonitor failed for \"%S\" with error %lu!\n", pPrintMonitor->pwszFileName, GetLastError());
+                goto Cleanup;
+            }
+        }
+        else
+        {
+            ERR("No initialization routine found for \"%S\"!\n", pPrintMonitor->pwszFileName);
+            dwErrorCode = ERROR_PROC_NOT_FOUND;
+            goto Cleanup;
+        }
+    }
+    // Add this Print Monitor to the list.
+    InsertTailList(&PrintMonitorList, &pPrintMonitor->Entry);
+    FIXME("AddPrintMonitorList Handle %p\n",pPrintMonitor->hMonitor);
+
+    pPrintMonitor->refcount++;
+
+    // Don't let the cleanup routine free this.
+    pPrintMonitor = NULL;
+
+    dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+    if (pwszRegistryPath)
+        DllFreeSplMem(pwszRegistryPath);
+
+    if (pPrintMonitor)
+    {
+        if (pPrintMonitor->pwszFileName)
+            DllFreeSplMem(pPrintMonitor->pwszFileName);
+
+        if (pPrintMonitor->pwszName)
+            DllFreeSplMem(pPrintMonitor->pwszName);
+
+        DllFreeSplMem(pPrintMonitor);
+    }
+
+    // Outside the loop
+    if (hKey)
+        RegCloseKey(hKey);
+
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+LocalAddMonitor(PWSTR pName, DWORD Level, PBYTE pMonitors)
+{
+    PPRINTENV_T env;
+    LPMONITOR_INFO_2W mi2w;
+    HKEY hroot = NULL;
+    HKEY hentry = NULL;
+    DWORD disposition;
+    BOOL res = FALSE;
+    const WCHAR wszMonitorsPath[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors\\";
+
+    mi2w = (LPMONITOR_INFO_2W) pMonitors;
+
+    FIXME("LocalAddMonitor(%s, %d, %p): %s %s %s\n", debugstr_w(pName), Level, pMonitors,
+        debugstr_w(mi2w->pName), debugstr_w(mi2w->pEnvironment), debugstr_w(mi2w->pDLLName));
+
+    if (copy_servername_from_name(pName, NULL))
+    {
+        FIXME("server %s not supported\n", debugstr_w(pName));
+        SetLastError(ERROR_ACCESS_DENIED);
+        return FALSE;
+    }
+
+    if (!mi2w->pName || (!mi2w->pName[0]) )
+    {
+        FIXME("pName not valid : %s\n", debugstr_w(mi2w->pName));
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    env = validate_envW(mi2w->pEnvironment);
+    if (!env)
+        return FALSE;   /* ERROR_INVALID_ENVIRONMENT */
+
+    if (!mi2w->pDLLName || (!mi2w->pDLLName[0]) )
+    {
+        FIXME("pDLLName not valid : %s\n", debugstr_w(mi2w->pDLLName));
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if (RegCreateKeyW(HKEY_LOCAL_MACHINE, wszMonitorsPath, &hroot) != ERROR_SUCCESS) {
+        ERR("unable to create key %s\n", debugstr_w(wszMonitorsPath));
+        return FALSE;
+    }
+
+    if (RegCreateKeyExW(hroot, mi2w->pName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_QUERY_VALUE, NULL, &hentry, &disposition) == ERROR_SUCCESS)
+    {
+        /* Some installers set options for the port before calling AddMonitor.
+           We query the "Driver" entry to verify that the monitor is installed,
+           before we return an error.
+           When a user installs two print monitors at the same time with the
+           same name, a race condition is possible but silently ignored. */
+
+        DWORD   namesize = 0;
+
+        if ((disposition == REG_OPENED_EXISTING_KEY) &&
+            (RegQueryValueExW(hentry, L"Driver", NULL, NULL, NULL, &namesize) == ERROR_SUCCESS))
+        {
+            FIXME("monitor %s already exists\n", debugstr_w(mi2w->pName));
+            /* 9x use ERROR_ALREADY_EXISTS */
+            SetLastError(ERROR_PRINT_MONITOR_ALREADY_INSTALLED);
+        }
+        else
+        {
+            INT len = (lstrlenW(mi2w->pDLLName) +1) * sizeof(WCHAR);
+
+            res = (RegSetValueExW(hentry, L"Driver", 0, REG_SZ, (LPBYTE) mi2w->pDLLName, len) == ERROR_SUCCESS);
+
+            /* Load and initialize the monitor. SetLastError() is called on failure */
+
+            res = AddPrintMonitorList( mi2w->pName, mi2w->pDLLName );
+
+            if ( !res )
+            {
+                RegDeleteKeyW(hroot, mi2w->pName);
+            }
+            else
+                SetLastError(ERROR_SUCCESS); /* Monitor installer depends on this */
+        }
+
+        RegCloseKey(hentry);
+    }
+
+    RegCloseKey(hroot);
+    return res;
+}
+
+BOOL WINAPI
+LocalDeleteMonitor(PWSTR pName, PWSTR pEnvironment, PWSTR pMonitorName)
+{
+    HKEY hroot = NULL;
+    LONG lres;
+    PLOCAL_PRINT_MONITOR pPrintMonitor;
+    const WCHAR wszMonitorsPath[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors\\";
+
+    FIXME("LocalDeleteMonitor(%s, %s, %s)\n",debugstr_w(pName),debugstr_w(pEnvironment),
+           debugstr_w(pMonitorName));
+
+    lres = copy_servername_from_name(pName, NULL);
+    if (lres)
+    {
+        FIXME("server %s not supported\n", debugstr_w(pName));
+        SetLastError(ERROR_INVALID_NAME);
+        return FALSE;
+    }
+
+    /*  pEnvironment is ignored in Windows for the local Computer */
+    if (!pMonitorName || !pMonitorName[0])
+    {
+        ERR("pMonitorName %s is invalid\n", debugstr_w(pMonitorName));
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    pPrintMonitor = FindPrintMonitor( pMonitorName );
+    if ( pPrintMonitor )
+    {
+       if ( pPrintMonitor->refcount ) pPrintMonitor->refcount--;
+
+       if ( pPrintMonitor->refcount == 0 )
+       {       /* Unload the monitor if it's loaded */
+       RemoveEntryList(&pPrintMonitor->Entry);
+
+       if ( pPrintMonitor->bIsLevel2 )
+       {
+           PMONITOR2 pm2 = pPrintMonitor->pMonitor;
+           if ( pm2 && pm2->pfnShutdown )
+           {
+               pm2->pfnShutdown(pPrintMonitor->hMonitor);
+           }
+       }
+
+       if ( pPrintMonitor->hModule )
+           FreeLibrary(pPrintMonitor->hModule);
+
+       if (pPrintMonitor->pwszFileName)
+           DllFreeSplStr(pPrintMonitor->pwszFileName);
+
+       if (pPrintMonitor->pwszName)
+           DllFreeSplStr(pPrintMonitor->pwszName);
+
+       DllFreeSplMem(pPrintMonitor);
+       pPrintMonitor = NULL;
+       }
+    }
+    else
+    {
+       FIXME("Could not find %s\n", debugstr_w(pMonitorName));
+    }
+
+    if (RegCreateKeyW(HKEY_LOCAL_MACHINE, wszMonitorsPath, &hroot) != ERROR_SUCCESS)
+    {
+        ERR("unable to create key %s\n", debugstr_w(wszMonitorsPath));
+        return FALSE;
+    }
+
+    if (RegDeleteTreeW(hroot, pMonitorName) == ERROR_SUCCESS)
+    {
+        FIXME("%s deleted\n", debugstr_w(pMonitorName));
+        RegCloseKey(hroot);
+        return TRUE;
+    }
+
+    FIXME("%s does not exist\n", debugstr_w(pMonitorName));
+    RegCloseKey(hroot);
+
+    /* NT: ERROR_UNKNOWN_PRINT_MONITOR (3000), 9x: ERROR_INVALID_PARAMETER (87) */
+    SetLastError(ERROR_UNKNOWN_PRINT_MONITOR);
+    return FALSE;
+}
index f1a966c..f82bbd2 100644 (file)
@@ -33,6 +33,29 @@ FindPort(PCWSTR pwszName)
     return NULL;
 }
 
+BOOL
+CreatePortEntry( PCWSTR pwszName, PLOCAL_PRINT_MONITOR pPrintMonitor )
+{
+    PLOCAL_PORT pPort;
+    DWORD cbPortName = (wcslen( pwszName ) + 1) * sizeof(WCHAR);
+
+    // Create a new LOCAL_PORT structure for it.
+    pPort = DllAllocSplMem(sizeof(LOCAL_PORT) + cbPortName);
+    if (!pPort)
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+    }
+
+    pPort->pPrintMonitor = pPrintMonitor;
+    pPort->pwszName = wcscpy( (PWSTR)(pPort+1), pwszName );
+
+    // Insert it into the list and advance to the next port.
+    InsertTailList(&_PortList, &pPort->Entry);
+
+    return TRUE;
+}
+
 BOOL
 InitializePortList(void)
 {
@@ -189,3 +212,288 @@ LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNe
 
     return bReturnValue;
 }
+
+BOOL WINAPI
+LocalAddPortEx(PWSTR pName, DWORD Level, PBYTE lpBuffer, PWSTR lpMonitorName)
+{
+    DWORD lres;
+    BOOL res = FALSE;
+    PLOCAL_PORT pPort;
+    PLOCAL_PRINT_MONITOR pPrintMonitor;
+    PORT_INFO_1W * pi = (PORT_INFO_1W *) lpBuffer;
+
+    FIXME("LocalAddPortEx(%S, %lu, %p, %S)\n", pName, Level, lpBuffer, lpMonitorName);
+
+    lres = copy_servername_from_name(pName, NULL);
+    if ( lres )
+    {
+        FIXME("server %s not supported\n", debugstr_w(pName));
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if ( Level != 1 )
+    {
+        SetLastError(ERROR_INVALID_LEVEL);
+        return FALSE;
+    }
+
+    if ((!pi) || (!lpMonitorName) || (!lpMonitorName[0]))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    pPrintMonitor = FindPrintMonitor( lpMonitorName );
+    if (!pPrintMonitor )
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    pPort = FindPort( pi->pName );
+    if ( pPort )
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnAddPortEx )
+    {
+        res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnAddPortEx(pPrintMonitor->hMonitor, pName, Level, lpBuffer, lpMonitorName);
+    }
+    else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnAddPortEx )
+    {
+        res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnAddPortEx(pName, Level, lpBuffer, lpMonitorName);
+    }
+    else
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+    }
+
+    if ( res )
+    {
+        res = CreatePortEntry( pi->pName, pPrintMonitor );
+    }
+
+    return res;
+}
+
+//
+// Local (AP, CP & DP) is still around, seems to be a backup if a failure was encountered.. New way, WinSpool->LocalUI->XcvDataW.
+//
+BOOL WINAPI
+LocalAddPort(LPWSTR pName, HWND hWnd, LPWSTR pMonitorName)
+{
+    DWORD lres;
+    BOOL res = FALSE;
+    PLOCAL_PRINT_MONITOR pPrintMonitor;
+
+    FIXME("LocalAddPort(%S, %p, %s)\n", pName, hWnd, debugstr_w(pMonitorName));
+
+    lres = copy_servername_from_name(pName, NULL);
+    if (lres)
+    {
+        FIXME("server %s not supported\n", debugstr_w(pName));
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    /* an empty Monitorname is Invalid */
+    if (!pMonitorName[0])
+    {
+        SetLastError(ERROR_NOT_SUPPORTED);
+        return FALSE;
+    }
+
+    pPrintMonitor = FindPrintMonitor( pMonitorName );
+    if (!pPrintMonitor )
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnAddPort )
+    {
+        res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnAddPort(pPrintMonitor->hMonitor, pName, hWnd, pMonitorName);
+    }
+    else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnAddPort )
+    {
+        res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnAddPort(pName, hWnd, pMonitorName);
+    }
+    else
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+    }
+
+    if ( res )
+    {
+        DWORD cbNeeded, cReturned, i;
+        PPORT_INFO_1 pPorts;
+
+        //
+        // Play it safe,,, we know its Monitor2.... This is ReactOS.
+        //
+        if ( LocalEnumPorts( pName, 1, NULL, 0, &cbNeeded, &cReturned ) )
+        {
+            pPorts = DllAllocSplMem( cbNeeded );
+            if (pPorts)
+            {
+                if ( LocalEnumPorts( pName, 1, (PBYTE)pPorts, cbNeeded, &cbNeeded, &cReturned ) )
+                {
+                    for ( i = 0; i < cReturned; i++ )
+                    {
+                        if ( !FindPort( pPorts[i].pName ) )
+                        {
+                            CreatePortEntry( pPorts[i].pName, pPrintMonitor );
+                        }
+                    }
+                }
+                DllFreeSplMem( pPorts );
+            }
+        }
+    }
+
+    return res;
+}
+
+BOOL WINAPI
+LocalConfigurePort(PWSTR pName, HWND hWnd, PWSTR pPortName)
+{
+    LONG lres;
+    DWORD res;
+    PLOCAL_PORT pPrintPort;
+    PLOCAL_PRINT_MONITOR pPrintMonitor;
+
+    FIXME("LocalConfigurePort(%S, %p, %S)\n", pName, hWnd, pPortName);
+
+    lres = copy_servername_from_name(pName, NULL);
+    if (lres)
+    {
+        FIXME("server %s not supported\n", debugstr_w(pName));
+        SetLastError(ERROR_INVALID_NAME);
+        return FALSE;
+    }
+
+    /* an empty Portname is Invalid, but can popup a Dialog */
+    if (!pPortName[0])
+    {
+        SetLastError(ERROR_NOT_SUPPORTED);
+        return FALSE;
+    }
+
+    pPrintPort = FindPort(pPortName);
+    if (!pPrintPort )
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    pPrintMonitor = pPrintPort->pPrintMonitor;
+
+    if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnConfigurePort )
+    {
+        res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnConfigurePort(pPrintMonitor->hMonitor, pName, hWnd, pPortName);
+    }
+    else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnConfigurePort )
+    {
+        res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnConfigurePort(pName, hWnd, pPortName);
+    }
+    else
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+    }
+
+    return res;
+}
+
+BOOL WINAPI
+LocalDeletePort(PWSTR pName, HWND hWnd, PWSTR pPortName)
+{
+    LONG lres;
+    DWORD res = FALSE;
+    PLOCAL_PORT pPrintPort;
+    PLOCAL_PRINT_MONITOR pPrintMonitor;
+
+    FIXME("LocalDeletePort(%S, %p, %S)\n", pName, hWnd, pPortName);
+
+    lres = copy_servername_from_name(pName, NULL);
+    if (lres)
+    {
+        FIXME("server %s not supported\n", debugstr_w(pName));
+        SetLastError(ERROR_INVALID_NAME);
+        return FALSE;
+    }
+
+    if (!pPortName[0])
+    {
+        SetLastError(ERROR_NOT_SUPPORTED);
+        return FALSE;
+    }
+
+    pPrintPort = FindPort(pPortName);
+    if (!pPrintPort )
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    pPrintMonitor = pPrintPort->pPrintMonitor;
+
+    if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnDeletePort )
+    {
+        res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnDeletePort(pPrintMonitor->hMonitor, pName, hWnd, pPortName);
+    }
+    else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnDeletePort )
+    {
+        res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnDeletePort(pName, hWnd, pPortName);
+    }
+
+    RemoveEntryList(&pPrintPort->Entry);
+
+    DllFreeSplMem(pPrintPort);
+
+    return res;
+}
+
+BOOL WINAPI
+LocalSetPort(PWSTR pName, PWSTR pPortName, DWORD dwLevel, PBYTE pPortInfo)
+{
+    LONG lres;
+    DWORD res = 0;
+    PPORT_INFO_3W ppi3w = (PPORT_INFO_3W)pPortInfo;
+    PLOCAL_PORT pPrintPort;
+
+    TRACE("LocalSetPort(%S, %S, %lu, %p)\n", pName, pPortName, dwLevel, pPortInfo);
+
+    lres = copy_servername_from_name(pName, NULL);
+    if (lres)
+    {
+        FIXME("server %s not supported\n", debugstr_w(pName));
+        SetLastError(ERROR_INVALID_NAME);
+        return FALSE;
+    }
+
+    if ((dwLevel < 1) || (dwLevel > 2))
+    {
+        SetLastError(ERROR_INVALID_LEVEL);
+        return FALSE;
+    }
+
+    if ( !ppi3w )
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    pPrintPort = FindPort(pPortName);
+    if ( !pPrintPort )
+    {
+        SetLastError(ERROR_UNKNOWN_PORT);
+        return FALSE;
+    }
+
+    FIXME("Add Status Support to Local Ports!\n");
+
+    return res;
+}
index 91a7f09..d8e0626 100644 (file)
@@ -22,6 +22,7 @@
 #include <winreg.h>
 #include <winspool.h>
 #include <winsplp.h>
+#include <winddiui.h>
 #include <dsrole.h>
 #include <secext.h>
 #include <ndk/rtlfuncs.h>
@@ -49,6 +50,7 @@ typedef HANDLE (WINAPI *POpenPrintProcessor)(LPWSTR, PPRINTPROCESSOROPENDATA);
 typedef BOOL (WINAPI *PPrintDocumentOnPrintProcessor)(HANDLE, LPWSTR);
 typedef LPMONITOREX(WINAPI *PInitializePrintMonitor)(PWSTR);
 typedef LPMONITOR2(WINAPI *PInitializePrintMonitor2)(PMONITORINIT, PHANDLE);
+typedef PMONITORUI(WINAPI *PInitializePrintMonitorUI)(VOID);
 
 // Forward declarations
 typedef struct _LOCAL_HANDLE            LOCAL_HANDLE, *PLOCAL_HANDLE;
@@ -69,8 +71,10 @@ typedef struct _SHD_HEADER              SHD_HEADER, *PSHD_HEADER;
 struct _LOCAL_PRINT_MONITOR
 {
     LIST_ENTRY Entry;
+    DWORD refcount;
     PWSTR pwszName;                             /** Name of the Print Monitor as read from the registry. */
     PWSTR pwszFileName;                         /** DLL File Name of the Print Monitor. */
+    HMODULE hModule;
     BOOL bIsLevel2;                             /** Whether this Print Monitor supplies an InitializePrintMonitor2 API (preferred) instead of InitializePrintMonitor. */
     PVOID pMonitor;                             /** For bIsLevel2 == TRUE:  LPMONITOR2 pointer returned by InitializePrintMonitor2.
                                                     For bIsLevel2 == FALSE: LPMONITOREX pointer returned by InitializePrintMonitor. */
@@ -241,6 +245,14 @@ struct _SHD_HEADER
     DWORD dwSPLSize;
 };
 
+// forms.c
+BOOL InitializeFormList(VOID);
+BOOL WINAPI LocalAddForm(HANDLE hPrinter, DWORD Level, PBYTE pForm);
+BOOL WINAPI LocalDeleteForm(HANDLE hPrinter, PWSTR pFormName);
+BOOL WINAPI LocalEnumForms(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned);
+BOOL WINAPI LocalGetForm(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded);
+BOOL WINAPI localSetForm(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm);
+
 // jobs.c
 extern SKIPLIST GlobalJobList;
 DWORD WINAPI CreateJob(PLOCAL_PRINTER_HANDLE pPrinterHandle);
@@ -275,11 +287,19 @@ extern LIST_ENTRY PrintMonitorList;
 PLOCAL_PRINT_MONITOR FindPrintMonitor(PCWSTR pwszName);
 BOOL InitializePrintMonitorList(void);
 BOOL WINAPI LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned);
+BOOL WINAPI LocalAddMonitor(PWSTR pName, DWORD Level, PBYTE pMonitors);
+BOOL WINAPI LocalDeleteMonitor(PWSTR pName, PWSTR pEnvironment, PWSTR pMonitorName);
 
 // ports.c
 PLOCAL_PORT FindPort(PCWSTR pwszName);
 BOOL InitializePortList(void);
 BOOL WINAPI LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned);
+BOOL WINAPI LocalAddPortEx(PWSTR pName, DWORD Level, PBYTE lpBuffer, PWSTR lpMonitorName);
+BOOL WINAPI LocalAddPort(LPWSTR pName, HWND hWnd, LPWSTR pMonitorName);
+BOOL WINAPI LocalConfigurePort(PWSTR pName, HWND hWnd, PWSTR pPortName);
+BOOL WINAPI LocalDeletePort(PWSTR pName, HWND hWnd, PWSTR pPortName);
+BOOL WINAPI LocalSetPort(PWSTR pName, PWSTR pPortName, DWORD dwLevel, PBYTE pPortInfo);
+BOOL CreatePortEntry( PCWSTR pwszName, PLOCAL_PRINT_MONITOR pPrintMonitor );
 
 // printerdata.c
 DWORD WINAPI LocalGetPrinterData(HANDLE hPrinter, PWSTR pValueName, PDWORD pType, PBYTE pData, DWORD nSize, PDWORD pcbNeeded);
@@ -287,9 +307,26 @@ DWORD WINAPI LocalGetPrinterDataEx(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pVal
 DWORD WINAPI LocalSetPrinterData(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData);
 DWORD WINAPI LocalSetPrinterDataEx(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData);
 
-// printerdriver.c
+// printerdrivers.c
+BOOL InitializePrinterDrivers(VOID);
+BOOL WINAPI LocalAddPrinterDriver(LPWSTR pName, DWORD level, LPBYTE pDriverInfo);
+BOOL WINAPI LocalAddPrinterDriverEx(LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags);
 BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded);
+BOOL WINAPI LocalGetPrinterDriverDirectory(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverDirectory, DWORD cbBuf, PDWORD pcbNeeded);
+BOOL WINAPI LocalGetPrinterDriverEx(HANDLE hPrinter,LPWSTR pEnvironment,DWORD Level,LPBYTE pDriverInfo,DWORD cbBuf,LPDWORD pcbNeeded,DWORD dwClientMajorVersion,DWORD dwClientMinorVersion,PDWORD pdwServerMajorVersion,PDWORD pdwServerMinorVersion );
+BOOL WINAPI LocalEnumPrinterDrivers(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned);
+
+// wine codes
+typedef struct _PRINTENV_T
+{
+    LPCWSTR  envname;
+    LPCWSTR  subdir;
+    DWORD    driverversion;
+    LPCWSTR  versionregpath;
+    LPCWSTR  versionsubdir;
+} PRINTENV_T, *PPRINTENV_T;
 
+PPRINTENV_T validate_envW(LPCWSTR env);
 
 // printers.c
 extern SKIPLIST PrinterList;
@@ -297,6 +334,7 @@ BOOL InitializePrinterList(void);
 BOOL WINAPI LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned);
 BOOL WINAPI LocalGetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded);
 BOOL WINAPI LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDefault);
+DWORD WINAPI LocalPrinterMessageBox(HANDLE hPrinter, DWORD Error, HWND hWnd, LPWSTR pText, LPWSTR pCaption, DWORD dwType);
 BOOL WINAPI LocalReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead);
 DWORD WINAPI LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo);
 BOOL WINAPI LocalStartPagePrinter(HANDLE hPrinter);
@@ -304,6 +342,7 @@ BOOL WINAPI LocalWritePrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf, LPDWORD
 BOOL WINAPI LocalEndPagePrinter(HANDLE hPrinter);
 BOOL WINAPI LocalEndDocPrinter(HANDLE hPrinter);
 BOOL WINAPI LocalClosePrinter(HANDLE hPrinter);
+VOID BroadcastChange(PLOCAL_HANDLE pHandle);
 
 // printingthread.c
 DWORD WINAPI PrintingThreadProc(PLOCAL_JOB pJob);
@@ -324,5 +363,11 @@ BOOL WINAPI LocalCloseSpoolFileHandle(HANDLE hPrinter);
 // tools.c
 PWSTR AllocAndRegQueryWSZ(HKEY hKey, PCWSTR pwszValueName);
 PDEVMODEW DuplicateDevMode(PDEVMODEW pInput);
+// wine codes
+LONG copy_servername_from_name(LPCWSTR name, LPWSTR target);
+
+// Xcv.c
+BOOL WINAPI LocalXcvData(HANDLE hXcv, const WCHAR* pszDataName, BYTE* pInputData, DWORD cbInputData, BYTE* pOutputData, DWORD cbOutputData, DWORD* pcbOutputNeeded, DWORD* pdwStatus);
+
 
 #endif
index 67dd7a0..2a5ed36 100644 (file)
@@ -9,13 +9,75 @@
 #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;
@@ -32,6 +94,21 @@ DoInitPrinterDriversInternal(void)
     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;
 }
 
@@ -86,6 +163,47 @@ static DWORD dwDriverInfo5Offsets[] = {
     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)
 {
@@ -97,15 +215,14 @@ 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)
@@ -125,23 +242,26 @@ _LocalGetPrinterDriverLevel1(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_1W* ppD
 }
 
 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);
@@ -156,20 +276,24 @@ _LocalGetPrinterDriverLevel2(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_2W* ppD
 }
 
 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.
@@ -196,21 +320,25 @@ _LocalGetPrinterDriverLevel3(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_3W* ppD
 }
 
 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)
@@ -236,14 +364,14 @@ _LocalGetPrinterDriverLevel4(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_4W* ppD
 }
 
 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
 
@@ -275,6 +403,130 @@ _LocalGetPrinterDriverLevel5(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_5W* ppD
     (*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;
@@ -284,8 +536,6 @@ BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Le
 
     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)
@@ -296,8 +546,8 @@ BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Le
 
     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;
@@ -307,20 +557,12 @@ BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Le
     // 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;
     }
@@ -328,16 +570,7 @@ BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Le
     // 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;
 
@@ -345,3 +578,574 @@ Cleanup:
     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);
+}
index a278372..e63af1a 100644 (file)
@@ -346,6 +346,24 @@ Cleanup:
     return (dwErrorCode == ERROR_SUCCESS);
 }
 
+VOID
+BroadcastChange(PLOCAL_HANDLE pHandle)
+{
+    PLOCAL_PRINTER pPrinter;
+    PSKIPLIST_NODE pNode;
+    DWORD cchMachineName = 0;
+    WCHAR wszMachineName[MAX_PATH] = {0}; // if not local, use Machine Name then Printer Name... pPrinter->pJob->pwszMachineName?
+
+    for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
+    {
+        pPrinter = (PLOCAL_PRINTER)pNode->Element;
+
+        StringCchCopyW( &wszMachineName[cchMachineName], sizeof(wszMachineName), pPrinter->pwszPrinterName );
+
+        PostMessageW( HWND_BROADCAST, WM_DEVMODECHANGE, 0, (LPARAM)&wszMachineName );
+    }
+}
+
 /**
  * @name _LocalEnumPrintersCheckName
  *
@@ -607,7 +625,7 @@ _LocalGetPrinterLevel2(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_2W* ppPrinterInfo,
     size_t cbParameters;
     PWSTR p, Allocation;
     PCWSTR pwszStrings[10];
-
+    FIXME("LocalGetPrinterLevel2\n");
     // Calculate the string lengths.
     cbDevMode = pPrinter->pDefaultDevMode->dmSize + pPrinter->pDefaultDevMode->dmDriverExtra;
     cbPrinterName = (cchComputerName + wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
@@ -626,6 +644,7 @@ _LocalGetPrinterLevel2(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_2W* ppPrinterInfo,
         cbParameters = sizeof(wszEmpty);
 
         *pcbNeeded += sizeof(PRINTER_INFO_2W) + cbDevMode + cbPrinterName + cbShareName + cbPortName + cbDriverName + cbComment + cbLocation + cbSepFile + cbPrintProcessor + cbDatatype + cbParameters;
+        FIXME("LocalGetPrinterLevel2 Needed %d\n",*pcbNeeded);
         return;
     }
 
@@ -871,7 +890,7 @@ LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DW
     WCHAR wszComputerName[2 + MAX_COMPUTERNAME_LENGTH + 1 + 1] = { 0 };
     PLOCAL_PRINTER pPrinter;
 
-    TRACE("LocalEnumPrinters(%lu, %S, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
+    FIXME("LocalEnumPrinters(%lu, %S, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
 
     // Do no sanity checks or assertions for pcbNeeded and pcReturned here.
     // This is verified and required by localspl_apitest!
@@ -1283,6 +1302,7 @@ _LocalOpenXcvHandle(PWSTR pwszParameter, PHANDLE phPrinter)
         {
             // The caller supplied a non-existing Monitor name.
             dwErrorCode = ERROR_INVALID_NAME;
+            ERR("OpenXcvHandle failed on Monitor name! %lu\n", dwErrorCode);
             goto Failure;
         }
     }
@@ -1297,6 +1317,7 @@ _LocalOpenXcvHandle(PWSTR pwszParameter, PHANDLE phPrinter)
         {
             // The supplied port is unknown to all our Print Monitors.
             dwErrorCode = ERROR_INVALID_NAME;
+            ERR("OpenXcvHandle failed on Port name! %lu\n", dwErrorCode);
             goto Failure;
         }
 
@@ -1305,6 +1326,7 @@ _LocalOpenXcvHandle(PWSTR pwszParameter, PHANDLE phPrinter)
     else
     {
         dwErrorCode = ERROR_INVALID_NAME;
+        ERR("OpenXcvHandle failed on bad name! %lu\n", dwErrorCode);
         goto Failure;
     }
 
@@ -1318,6 +1340,7 @@ _LocalOpenXcvHandle(PWSTR pwszParameter, PHANDLE phPrinter)
     {
         // The XcvOpenPort function failed. Return its last error.
         dwErrorCode = GetLastError();
+        ERR("XcvOpenPort function failed! %lu\n", dwErrorCode);
         goto Failure;
     }
 
@@ -1348,6 +1371,7 @@ _LocalOpenXcvHandle(PWSTR pwszParameter, PHANDLE phPrinter)
 
     // Return it.
     *phPrinter = (HANDLE)pHandle;
+    ERR("OpenXcvHandle Success! %p\n", pXcvHandle);
     return ERROR_SUCCESS;
 
 Failure:
@@ -1360,6 +1384,16 @@ Failure:
     return dwErrorCode;
 }
 
+//
+// Dead API
+//
+DWORD WINAPI
+LocalPrinterMessageBox(HANDLE hPrinter, DWORD Error, HWND hWnd, LPWSTR pText, LPWSTR pCaption, DWORD dwType)
+{
+    SetLastError(ERROR_INVALID_HANDLE); // Yes....
+    return 0;
+}
+
 BOOL WINAPI
 LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDefault)
 {
@@ -1475,6 +1509,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
         //    "\\COMPUTERNAME\, XcvMonitor Local Port"
         //    ", XcvPort LPT1:"
         //    "\\COMPUTERNAME\, XcvPort LPT1:"
+        FIXME("OpenXcvHandle : %S\n",pwszSecondParameter);
         dwErrorCode = _LocalOpenXcvHandle(pwszSecondParameter, phPrinter);
     }
     else
@@ -1890,6 +1925,7 @@ Cleanup:
 static void
 _LocalClosePortHandle(PLOCAL_PORT_HANDLE pPortHandle)
 {
+    FIXME("LocalClosePortHandle\n");
     // Call the monitor's ClosePort function.
     if (pPortHandle->pPort->pPrintMonitor->bIsLevel2)
         ((PMONITOR2)pPortHandle->pPort->pPrintMonitor->pMonitor)->pfnClosePort(pPortHandle->hPort);
@@ -1900,6 +1936,7 @@ _LocalClosePortHandle(PLOCAL_PORT_HANDLE pPortHandle)
 static void
 _LocalClosePrinterHandle(PLOCAL_PRINTER_HANDLE pPrinterHandle)
 {
+    FIXME("LocalClosePrinterHandle\n");
     // Terminate any started job.
     if (pPrinterHandle->pJob)
         FreeJob(pPrinterHandle->pJob);
@@ -1924,7 +1961,7 @@ LocalClosePrinter(HANDLE hPrinter)
 {
     PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
 
-    TRACE("LocalClosePrinter(%p)\n", hPrinter);
+    FIXME("LocalClosePrinter(%p)\n", hPrinter);
 
     if (!pHandle)
     {
@@ -1948,12 +1985,12 @@ LocalClosePrinter(HANDLE hPrinter)
     {
         _LocalCloseXcvHandle(pHandle->pSpecificHandle);
     }
-
+    FIXME("LocalClosePrinter 1\n");
     // Free memory for the handle and the specific handle (if any).
     if (pHandle->pSpecificHandle)
         DllFreeSplMem(pHandle->pSpecificHandle);
-
+    FIXME("LocalClosePrinter 2\n");
     DllFreeSplMem(pHandle);
-
+    FIXME("LocalClosePrinter 3\n");
     return TRUE;
 }
index 475eff0..16c433e 100644 (file)
@@ -75,3 +75,56 @@ DuplicateDevMode(PDEVMODEW pInput)
 
     return pOutput;
 }
+
+/******************************************************************
+ * copy_servername_from_name  (internal)
+ *
+ * for an external server, the serverpart from the name is copied.
+ *
+ * RETURNS
+ *  the length (in WCHAR) of the serverpart (0 for the local computer)
+ *  (-length), when the name is too long
+ *
+ */
+LONG copy_servername_from_name(LPCWSTR name, LPWSTR target)
+{
+    LPCWSTR server;
+    LPWSTR  ptr;
+    WCHAR   buffer[MAX_COMPUTERNAME_LENGTH +1];
+    DWORD   len;
+    DWORD   serverlen;
+
+    if (target) *target = '\0';
+
+    if (name == NULL) return 0;
+    if ((name[0] != '\\') || (name[1] != '\\')) return 0;
+
+    server = &name[2];
+    /* skip over both backslash, find separator '\' */
+    ptr = wcschr(server, '\\');
+    serverlen = (ptr) ? ptr - server : lstrlenW(server);
+
+    /* servername is empty */
+    if (serverlen == 0) return 0;
+
+    FIXME("found %s\n", debugstr_wn(server, serverlen));
+
+    if (serverlen > MAX_COMPUTERNAME_LENGTH) return -serverlen;
+
+    if (target)
+    {
+        memcpy(target, server, serverlen * sizeof(WCHAR));
+        target[serverlen] = '\0';
+    }
+
+    len = ARRAYSIZE(buffer);
+    if (GetComputerNameW(buffer, &len))
+    {
+        if ((serverlen == len) && (wcsnicmp(server, buffer, len) == 0))
+        {
+            /* The requested Servername is our computername */
+            return 0;
+        }
+    }
+    return serverlen;
+}
diff --git a/win32ss/printing/providers/localspl/xcv.c b/win32ss/printing/providers/localspl/xcv.c
new file mode 100644 (file)
index 0000000..e9a0da4
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * PROJECT:     ReactOS Print Spooler Service
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Xcv* functions
+ * COPYRIGHT:   Copyright 2020 ReactOS
+ */
+
+#include "precomp.h"
+
+static DWORD
+_HandleAddPort(HANDLE hXcv, PBYTE pInputData, PDWORD pcbOutputNeeded, DWORD* pdwStatus)
+{
+    DWORD res;
+    PLOCAL_PRINT_MONITOR pPrintMonitor;
+    PLOCAL_XCV_HANDLE pXcv;
+    PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hXcv;
+    PWSTR pPortName = (PWSTR)pInputData;
+
+    FIXME("LocalXcvAddPort : %s\n", debugstr_w( pPortName ) );
+
+    // Check if this is a printer handle.
+    if (pHandle->HandleType != HandleType_Xcv)
+    {
+        ERR("LocalXcvAddPort : Invalid XCV Handle\n");
+        res = ERROR_INVALID_HANDLE;
+        goto Cleanup;
+    }
+
+    pXcv = (PLOCAL_XCV_HANDLE)pHandle->pSpecificHandle;
+
+    pPrintMonitor = pXcv->pPrintMonitor;
+    if (!pPrintMonitor )
+    {
+        res = ERROR_INVALID_PARAMETER;
+        goto Cleanup;
+    }
+
+    // Sanity checks
+    if (!pInputData || !pcbOutputNeeded)
+    {
+        res = ERROR_INVALID_PARAMETER;
+        goto Cleanup;
+    }
+
+    pPrintMonitor->refcount++;
+    if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnXcvDataPort )
+    {
+        res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnXcvDataPort(pXcv->hXcv, L"AddPort", pInputData, 0, NULL, 0, pcbOutputNeeded);
+    }
+    else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnXcvDataPort )
+    {
+        res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnXcvDataPort(pXcv->hXcv, L"AddPort", pInputData, 0, NULL, 0, pcbOutputNeeded);
+    }
+    pPrintMonitor->refcount--;
+
+    if ( res == ERROR_SUCCESS )
+    {