[PRINTING]
authorColin Finck <colin@reactos.org>
Tue, 9 May 2017 15:44:42 +0000 (15:44 +0000)
committerColin Finck <colin@reactos.org>
Tue, 9 May 2017 15:44:42 +0000 (15:44 +0000)
- Implement GetDefaultPrinterA/W and SetDefaultPrinterA/W in winspool.drv. Also add tests for these functions.
- Set our "Dummy Printer on LPT1" as the default printer in the user registry.
- Return meaningful values for DeviceNotSelectedTimeout and TransmissionRetryTimeout in PRINTER_INFO_5 in localspl.

The Print dialog now preselects "Dummy Printer on LPT1" in all applications.
One more task done from the list at https://reactos.org/wiki/Printing :)

svn path=/trunk/; revision=74513

reactos/boot/bootdata/hivedef.inf
reactos/win32ss/printing/base/winspool/CMakeLists.txt
reactos/win32ss/printing/base/winspool/printers.c
reactos/win32ss/printing/base/winspool/winspool.spec
reactos/win32ss/printing/include/spoolss.h
reactos/win32ss/printing/providers/localspl/precomp.h
reactos/win32ss/printing/providers/localspl/printers.c
rostests/apitests/winspool/CMakeLists.txt
rostests/apitests/winspool/GetDefaultPrinter.c [new file with mode: 0644]
rostests/apitests/winspool/testlist.c

index 8532d85..1524322 100644 (file)
@@ -1837,13 +1837,13 @@ HKCU,"SOFTWARE\Microsoft\Windows\CurrentVersion\Run","kbswitch.exe",2,"kbswitch.
 
 HKCU,"SOFTWARE\Microsoft\Windows NT",,0x00000012
 HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion",,0x00000012
 
 HKCU,"SOFTWARE\Microsoft\Windows NT",,0x00000012
 HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion",,0x00000012
-HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Devices",,0x00000012
+HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Devices","Dummy Printer On LPT1",2,"winspool,LPT1:"
 HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Network",,0x00000012
 HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Network",,0x00000012
-HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\PrinterPorts",,0x00000012
+HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\PrinterPorts","Dummy Printer On LPT1",2,"winspool,LPT1:,15,45"
 HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Program Manager",,0x00000012
 
 HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows","DebugOptions",2,"2048"
 HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Program Manager",,0x00000012
 
 HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows","DebugOptions",2,"2048"
-HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows","device",2,""
+HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows","Device",2,"Dummy Printer On LPT1,winspool,LPT1:"
 HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows","Documents",2,""
 HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows","DosPrint",2,"no"
 HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows","load",2,""
 HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows","Documents",2,""
 HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows","DosPrint",2,"no"
 HKCU,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows","load",2,""
index f9c4f92..71d18ba 100644 (file)
@@ -26,6 +26,6 @@ add_library(winspool SHARED
 set_target_properties(winspool PROPERTIES SUFFIX ".drv")
 set_module_type(winspool win32dll UNICODE)
 target_link_libraries(winspool wine ${PSEH_LIB})
 set_target_properties(winspool PROPERTIES SUFFIX ".drv")
 set_module_type(winspool win32dll UNICODE)
 target_link_libraries(winspool wine ${PSEH_LIB})
-add_importlibs(winspool gdi32 rpcrt4 msvcrt kernel32 ntdll)
+add_importlibs(winspool advapi32 gdi32 rpcrt4 msvcrt kernel32 ntdll)
 add_pch(winspool precomp.h SOURCE)
 add_cd_file(TARGET winspool DESTINATION reactos/system32 FOR all)
 add_pch(winspool precomp.h SOURCE)
 add_cd_file(TARGET winspool DESTINATION reactos/system32 FOR all)
index a34a43f..53b113f 100644 (file)
@@ -7,6 +7,13 @@
 
 #include "precomp.h"
 
 
 #include "precomp.h"
 
+// Local Constants
+
+/** And the award for the most confusingly named setting goes to "Device", for storing the default printer of the current user.
+    Ok, I admit that this has historical reasons. It's still not straightforward in any way though! */
+static const WCHAR wszWindowsKey[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows";
+static const WCHAR wszDeviceValue[] = L"Device";
+
 static void
 _MarshallUpPrinterInfo(PBYTE* ppPrinterInfo, DWORD Level)
 {
 static void
 _MarshallUpPrinterInfo(PBYTE* ppPrinterInfo, DWORD Level)
 {
@@ -415,13 +422,131 @@ Cleanup:
 BOOL WINAPI
 GetDefaultPrinterA(LPSTR pszBuffer, LPDWORD pcchBuffer)
 {
 BOOL WINAPI
 GetDefaultPrinterA(LPSTR pszBuffer, LPDWORD pcchBuffer)
 {
-    return FALSE;
+    DWORD dwErrorCode;
+    PWSTR pwszBuffer = NULL;
+
+    // Sanity check.
+    if (!pcchBuffer)
+    {
+        dwErrorCode = ERROR_INVALID_PARAMETER;
+        goto Cleanup;
+    }
+
+    // Check if an ANSI buffer was given and if so, allocate a Unicode buffer of the same size.
+    if (pszBuffer && *pcchBuffer)
+    {
+        pwszBuffer = HeapAlloc(hProcessHeap, 0, *pcchBuffer * sizeof(WCHAR));
+        if (!pwszBuffer)
+        {
+            dwErrorCode = GetLastError();
+            ERR("HeapAlloc failed with error %lu!\n", dwErrorCode);
+            goto Cleanup;
+        }
+    }
+
+    if (!GetDefaultPrinterW(pwszBuffer, pcchBuffer))
+    {
+        dwErrorCode = GetLastError();
+        goto Cleanup;
+    }
+
+    dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+    if (pwszBuffer)
+        HeapFree(hProcessHeap, 0, pwszBuffer);
+
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
 }
 
 BOOL WINAPI
 GetDefaultPrinterW(LPWSTR pszBuffer, LPDWORD pcchBuffer)
 {
 }
 
 BOOL WINAPI
 GetDefaultPrinterW(LPWSTR pszBuffer, LPDWORD pcchBuffer)
 {
-    return FALSE;
+    DWORD cbNeeded;
+    DWORD cchInputBuffer;
+    DWORD dwErrorCode;
+    HKEY hWindowsKey = NULL;
+    PWSTR pwszDevice = NULL;
+    PWSTR pwszComma;
+
+    // Sanity check.
+    if (!pcchBuffer)
+    {
+        dwErrorCode = ERROR_INVALID_PARAMETER;
+        goto Cleanup;
+    }
+
+    cchInputBuffer = *pcchBuffer;
+
+    // Open the registry key where the default printer for the current user is stored.
+    dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszWindowsKey, 0, KEY_READ, &hWindowsKey);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
+        goto Cleanup;
+    }
+
+    // Determine the size of the required buffer.
+    dwErrorCode = (DWORD)RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, NULL, &cbNeeded);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
+        goto Cleanup;
+    }
+
+    // Allocate it.
+    pwszDevice = HeapAlloc(hProcessHeap, 0, cbNeeded);
+    if (!pwszDevice)
+    {
+        dwErrorCode = GetLastError();
+        ERR("HeapAlloc failed with error %lu!\n", dwErrorCode);
+        goto Cleanup;
+    }
+
+    // Now get the actual value.
+    dwErrorCode = RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, (PBYTE)pwszDevice, &cbNeeded);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
+        goto Cleanup;
+    }
+
+    // We get a string "<Printer Name>,winspool,<Port>:".
+    // Extract the printer name from it.
+    pwszComma = wcschr(pwszDevice, L',');
+    if (!pwszComma)
+    {
+        ERR("Found no or invalid default printer: %S!\n", pwszDevice);
+        dwErrorCode = ERROR_INVALID_NAME;
+        goto Cleanup;
+    }
+
+    // Store the length of the Printer Name (including the terminating NUL character!) in *pcchBuffer.
+    *pcchBuffer = pwszComma - pwszDevice + 1;
+
+    // Check if the supplied buffer is large enough.
+    if (cchInputBuffer < *pcchBuffer)
+    {
+        dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
+        goto Cleanup;
+    }
+
+    // Copy the default printer.
+    *pwszComma = 0;
+    CopyMemory(pszBuffer, pwszDevice, *pcchBuffer * sizeof(WCHAR));
+
+    dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+    if (hWindowsKey)
+        RegCloseKey(hWindowsKey);
+
+    if (pwszDevice)
+        HeapFree(hProcessHeap, 0, pwszDevice);
+
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
 }
 
 BOOL WINAPI
 }
 
 BOOL WINAPI
@@ -632,6 +757,147 @@ ResetPrinterW(HANDLE hPrinter, PPRINTER_DEFAULTSW pDefault)
     return FALSE;
 }
 
     return FALSE;
 }
 
+BOOL WINAPI
+SetDefaultPrinterA(LPCSTR pszPrinter)
+{
+    BOOL bReturnValue = FALSE;
+    DWORD cch;
+    PWSTR pwszPrinter = NULL;
+
+    if (pszPrinter)
+    {
+        // Convert pszPrinter to a Unicode string pwszPrinter
+        cch = strlen(pszPrinter);
+
+        pwszPrinter = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
+        if (!pwszPrinter)
+        {
+            ERR("HeapAlloc failed for pwszPrinter with last error %lu!\n", GetLastError());
+            goto Cleanup;
+        }
+
+        MultiByteToWideChar(CP_ACP, 0, pszPrinter, -1, pwszPrinter, cch + 1);
+    }
+
+    bReturnValue = SetDefaultPrinterW(pwszPrinter);
+
+Cleanup:
+    if (pwszPrinter)
+        HeapFree(hProcessHeap, 0, pwszPrinter);
+
+    return bReturnValue;
+}
+
+BOOL WINAPI
+SetDefaultPrinterW(LPCWSTR pszPrinter)
+{
+    const WCHAR wszDevicesKey[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Devices";
+
+    DWORD cbDeviceValueData;
+    DWORD cbPrinterValueData = 0;
+    DWORD cchPrinter;
+    DWORD dwErrorCode;
+    HKEY hDevicesKey = NULL;
+    HKEY hWindowsKey = NULL;
+    PWSTR pwszDeviceValueData = NULL;
+    WCHAR wszPrinter[MAX_PRINTER_NAME + 1];
+
+    // Open the Devices registry key.
+    dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszDevicesKey, 0, KEY_READ, &hDevicesKey);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
+        goto Cleanup;
+    }
+
+    // Did the caller give us a printer to set as default?
+    if (pszPrinter && *pszPrinter)
+    {
+        // Check if the given printer exists and query the value data size.
+        dwErrorCode = (DWORD)RegQueryValueExW(hDevicesKey, pszPrinter, NULL, NULL, NULL, &cbPrinterValueData);
+        if (dwErrorCode == ERROR_FILE_NOT_FOUND)
+        {
+            // The caller gave us an invalid printer name, return with ERROR_FILE_NOT_FOUND.
+            goto Cleanup;
+        }
+        else if (dwErrorCode != ERROR_SUCCESS)
+        {
+            ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
+            goto Cleanup;
+        }
+
+        cchPrinter = wcslen(pszPrinter);
+    }
+    else
+    {
+        // If there is already a default printer, we're done!
+        cchPrinter = _countof(wszPrinter);
+        if (GetDefaultPrinterW(wszPrinter, &cchPrinter))
+        {
+            dwErrorCode = ERROR_SUCCESS;
+            goto Cleanup;
+        }
+
+        // Otherwise, get us the first printer from the "Devices" key to later set it as default and query the value data size.
+        cchPrinter = _countof(wszPrinter);
+        dwErrorCode = (DWORD)RegEnumValueW(hDevicesKey, 0, wszPrinter, &cchPrinter, NULL, NULL, NULL, &cbPrinterValueData);
+        if (dwErrorCode != ERROR_MORE_DATA)
+            goto Cleanup;
+
+        pszPrinter = wszPrinter;
+    }
+
+    // We now need to query the value data, which has the format "winspool,<Port>:"
+    // and make "<Printer Name>,winspool,<Port>:" out of it.
+    // Allocate a buffer large enough for the final data.
+    cbDeviceValueData = (cchPrinter + 1) * sizeof(WCHAR) + cbPrinterValueData;
+    pwszDeviceValueData = HeapAlloc(hProcessHeap, 0, cbDeviceValueData);
+    if (!pwszDeviceValueData)
+    {
+        dwErrorCode = GetLastError();
+        ERR("HeapAlloc failed with error %lu\n", dwErrorCode);
+        goto Cleanup;
+    }
+
+    // Copy the Printer Name and a comma into it.
+    CopyMemory(pwszDeviceValueData, pszPrinter, cchPrinter * sizeof(WCHAR));
+    pwszDeviceValueData[cchPrinter] = L',';
+
+    // Append the value data, which has the format "winspool,<Port>:"
+    dwErrorCode = (DWORD)RegQueryValueExW(hDevicesKey, pszPrinter, NULL, NULL, (PBYTE)&pwszDeviceValueData[cchPrinter + 1], &cbPrinterValueData);
+    if (dwErrorCode != ERROR_SUCCESS)
+        goto Cleanup;
+
+    // Open the Windows registry key.
+    dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszWindowsKey, 0, KEY_SET_VALUE, &hWindowsKey);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
+        goto Cleanup;
+    }
+
+    // Store our new default printer.
+    dwErrorCode = (DWORD)RegSetValueExW(hWindowsKey, wszDeviceValue, 0, REG_SZ, (PBYTE)pwszDeviceValueData, cbDeviceValueData);
+    if (dwErrorCode != ERROR_SUCCESS)
+    {
+        ERR("RegSetValueExW failed with status %lu!\n", dwErrorCode);
+        goto Cleanup;
+    }
+
+Cleanup:
+    if (hDevicesKey)
+        RegCloseKey(hDevicesKey);
+
+    if (hWindowsKey)
+        RegCloseKey(hWindowsKey);
+
+    if (pwszDeviceValueData)
+        HeapFree(hProcessHeap, 0, pwszDeviceValueData);
+
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
 BOOL WINAPI
 SetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD Command)
 {
 BOOL WINAPI
 SetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD Command)
 {
index 9dcd522..21140cd 100644 (file)
 199 stub EnumPrinterDriversA
 200 stdcall EnumPrinterDriversW(wstr wstr long ptr long ptr ptr)
 201 stdcall GetDefaultPrinterA(ptr ptr)
 199 stub EnumPrinterDriversA
 200 stdcall EnumPrinterDriversW(wstr wstr long ptr long ptr ptr)
 201 stdcall GetDefaultPrinterA(ptr ptr)
-202 stub SetDefaultPrinterA
+202 stdcall SetDefaultPrinterA(str)
 203 stdcall GetDefaultPrinterW(ptr ptr)
 203 stdcall GetDefaultPrinterW(ptr ptr)
-204 stub SetDefaultPrinterW
+204 stdcall SetDefaultPrinterW(wstr)
 205 stub -noname SplReadPrinter
 206 stub -noname AddPerMachineConnectionA
 207 stub -noname AddPerMachineConnectionW
 205 stub -noname SplReadPrinter
 206 stub -noname AddPerMachineConnectionA
 207 stub -noname AddPerMachineConnectionW
index d877baa..86875cc 100644 (file)
@@ -1,13 +1,16 @@
 /*
  * PROJECT:     ReactOS Printing Include files
  * LICENSE:     GNU LGPLv2 or any later version as published by the Free Software Foundation
 /*
  * PROJECT:     ReactOS Printing Include files
  * LICENSE:     GNU LGPLv2 or any later version as published by the Free Software Foundation
- * PURPOSE:     Undocumented APIs of the Spooler Router "spoolss.dll"
+ * PURPOSE:     Undocumented APIs of the Spooler Router "spoolss.dll" and internally shared interfaces
  * COPYRIGHT:   Copyright 2015-2017 Colin Finck <colin@reactos.org>
  */
 
 #ifndef _REACTOS_SPOOLSS_H
 #define _REACTOS_SPOOLSS_H
 
  * COPYRIGHT:   Copyright 2015-2017 Colin Finck <colin@reactos.org>
  */
 
 #ifndef _REACTOS_SPOOLSS_H
 #define _REACTOS_SPOOLSS_H
 
+// Constants
+#define MAX_PRINTER_NAME        220
+
 typedef struct _MARSHALL_DOWN_INFO
 {
     DWORD dwOffset;             /** Byte offset of this element within the structure or MAXDWORD to indicate the end of the array */
 typedef struct _MARSHALL_DOWN_INFO
 {
     DWORD dwOffset;             /** Byte offset of this element within the structure or MAXDWORD to indicate the end of the array */
index b57fd65..8419d5a 100644 (file)
@@ -36,7 +36,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(localspl);
 #define IS_VALID_PRIORITY(P)    (P >= MIN_PRIORITY && P <= MAX_PRIORITY)
 
 // Constants
 #define IS_VALID_PRIORITY(P)    (P >= MIN_PRIORITY && P <= MAX_PRIORITY)
 
 // Constants
-#define MAX_PRINTER_NAME        220
 #define SHD_WIN2003_SIGNATURE   0x4968
 
 // Function pointers
 #define SHD_WIN2003_SIGNATURE   0x4968
 
 // Function pointers
index 435c612..4bbcf6e 100644 (file)
@@ -75,6 +75,12 @@ static DWORD dwPrinterInfo5Offsets[] = {
     MAXDWORD
 };
 
     MAXDWORD
 };
 
+/** These values serve no purpose anymore, but are still used in PRINTER_INFO_5 and
+    HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\PrinterPorts */
+static const DWORD dwDeviceNotSelectedTimeout = 15000;
+static const DWORD dwTransmissionRetryTimeout = 45000;
+
+
 /**
  * @name _PrinterListCompareRoutine
  *
 /**
  * @name _PrinterListCompareRoutine
  *
@@ -765,8 +771,8 @@ _LocalGetPrinterLevel5(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_5W* ppPrinterInfo,
 
     // Set the general fields.
     (*ppPrinterInfo)->Attributes = pPrinter->dwAttributes;
 
     // Set the general fields.
     (*ppPrinterInfo)->Attributes = pPrinter->dwAttributes;
-    (*ppPrinterInfo)->DeviceNotSelectedTimeout = 0;
-    (*ppPrinterInfo)->TransmissionRetryTimeout = 0;
+    (*ppPrinterInfo)->DeviceNotSelectedTimeout = dwDeviceNotSelectedTimeout;
+    (*ppPrinterInfo)->TransmissionRetryTimeout = dwTransmissionRetryTimeout;
 
     // Set the pPrinterName field.
     pwszStrings[0] = DllAllocSplMem(cbPrinterName);
 
     // Set the pPrinterName field.
     pwszStrings[0] = DllAllocSplMem(cbPrinterName);
index 9c0c77c..7f39341 100644 (file)
@@ -3,6 +3,7 @@ list(APPEND SOURCE
     ClosePrinter.c
     EnumPrinters.c
     EnumPrintProcessorDatatypes.c
     ClosePrinter.c
     EnumPrinters.c
     EnumPrintProcessorDatatypes.c
+    GetDefaultPrinter.c
     GetPrintProcessorDirectory.c
     IsValidDevmode.c
     OpenPrinter.c
     GetPrintProcessorDirectory.c
     IsValidDevmode.c
     OpenPrinter.c
diff --git a/rostests/apitests/winspool/GetDefaultPrinter.c b/rostests/apitests/winspool/GetDefaultPrinter.c
new file mode 100644 (file)
index 0000000..1559913
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * PROJECT:     ReactOS Print Spooler DLL API Tests
+ * LICENSE:     GNU GPLv2 or any later version as published by the Free Software Foundation
+ * PURPOSE:     Tests for GetDefaultPrinterA/GetDefaultPrinterW/SetDefaultPrinterA/SetDefaultPrinterW
+ * COPYRIGHT:   Copyright 2017 Colin Finck <colin@reactos.org>
+ */
+
+#include <apitest.h>
+
+#define WIN32_NO_STATUS
+#include <windef.h>
+#include <winbase.h>
+#include <wingdi.h>
+#include <winspool.h>
+
+START_TEST(GetDefaultPrinter)
+{
+    DWORD cchDefaultPrinter;
+    PWSTR pwszDefaultPrinter;
+
+    // Don't supply any parameters, this has to fail with ERROR_INVALID_PARAMETER.
+    SetLastError(0xDEADBEEF);
+    ok(!GetDefaultPrinterW(NULL, NULL), "GetDefaultPrinterW returns TRUE!\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetDefaultPrinterW returns error %lu!\n", GetLastError());
+
+    // Determine the size of the required buffer. This has to bail out with ERROR_INSUFFICIENT_BUFFER.
+    cchDefaultPrinter = 0;
+    SetLastError(0xDEADBEEF);
+    ok(!GetDefaultPrinterW(NULL, &cchDefaultPrinter), "GetDefaultPrinterW returns TRUE!\n");
+    ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetDefaultPrinterW returns error %lu!\n", GetLastError());
+
+    // Try with a buffer large enough.
+    pwszDefaultPrinter = HeapAlloc(GetProcessHeap(), 0, cchDefaultPrinter * sizeof(WCHAR));
+    SetLastError(0xDEADBEEF);
+    ok(GetDefaultPrinterW(pwszDefaultPrinter, &cchDefaultPrinter), "GetDefaultPrinterW returns FALSE!\n");
+    ok(GetLastError() == ERROR_SUCCESS, "GetDefaultPrinterW returns error %lu!\n", GetLastError());
+
+    // SetDefaultPrinterW with NULL needs to succeed and leave the default printer unchanged.
+    SetLastError(0xDEADBEEF);
+    ok(SetDefaultPrinterW(NULL), "SetDefaultPrinterW returns FALSE!\n");
+    ok(GetLastError() == ERROR_SUCCESS, "SetDefaultPrinterW returns error %lu!\n", GetLastError());
+
+    // SetDefaultPrinterW with the previous default printer also needs to succeed.
+    SetLastError(0xDEADBEEF);
+    ok(SetDefaultPrinterW(pwszDefaultPrinter), "SetDefaultPrinterW returns FALSE!\n");
+    ok(GetLastError() == ERROR_SUCCESS, "SetDefaultPrinterW returns error %lu!\n", GetLastError());
+
+    HeapFree(GetProcessHeap(), 0, pwszDefaultPrinter);
+}
index 3cc4174..74a70fb 100644 (file)
@@ -13,6 +13,7 @@
 extern void func_ClosePrinter(void);
 extern void func_EnumPrinters(void);
 extern void func_EnumPrintProcessorDatatypes(void);
 extern void func_ClosePrinter(void);
 extern void func_EnumPrinters(void);
 extern void func_EnumPrintProcessorDatatypes(void);
+extern void func_GetDefaultPrinter(void);
 extern void func_GetPrintProcessorDirectoryA(void);
 extern void func_GetPrintProcessorDirectoryW(void);
 extern void func_IsValidDevmodeA(void);
 extern void func_GetPrintProcessorDirectoryA(void);
 extern void func_GetPrintProcessorDirectoryW(void);
 extern void func_IsValidDevmodeA(void);
@@ -25,6 +26,7 @@ const struct test winetest_testlist[] =
     { "ClosePrinter", func_ClosePrinter },
     { "EnumPrinters", func_EnumPrinters },
     { "EnumPrintProcessorDatatypes", func_EnumPrintProcessorDatatypes },
     { "ClosePrinter", func_ClosePrinter },
     { "EnumPrinters", func_EnumPrinters },
     { "EnumPrintProcessorDatatypes", func_EnumPrintProcessorDatatypes },
+    { "GetDefaultPrinter", func_GetDefaultPrinter },
     { "GetPrintProcessorDirectoryA", func_GetPrintProcessorDirectoryA },
     { "GetPrintProcessorDirectoryW", func_GetPrintProcessorDirectoryW },
     { "IsValidDevmodeA", func_IsValidDevmodeA },
     { "GetPrintProcessorDirectoryA", func_GetPrintProcessorDirectoryA },
     { "GetPrintProcessorDirectoryW", func_GetPrintProcessorDirectoryW },
     { "IsValidDevmodeA", func_IsValidDevmodeA },