Bug 275624 - PrintDialog.setPrinterData does not work as expected
Bug 272331 - Setting fileName in PrinterData for PrintDialog does nothing
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java
index 048a9aa..f349a96 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java
@@ -711,6 +711,7 @@
 	public static final int GM_ADVANCED = 2;
 	public static final int GMDI_USEDISABLED = 0x1;
 	public static final int GMEM_FIXED = 0x0;
+	public static final int GMEM_MOVEABLE = 0x2;
 	public static final int GMEM_ZEROINIT = 0x40;
 	public static final int GN_CONTEXTMENU = 1000;
 	public static final int GPTR = 0x40;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Printing/win32/org/eclipse/swt/printing/PrintDialog.java b/bundles/org.eclipse.swt/Eclipse SWT Printing/win32/org/eclipse/swt/printing/PrintDialog.java
index 218d35a..6e2ae33 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT Printing/win32/org/eclipse/swt/printing/PrintDialog.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Printing/win32/org/eclipse/swt/printing/PrintDialog.java
@@ -292,9 +292,9 @@
 	int /*long*/ hwndParent = parent.handle;
 
 	/*
-	* Feature in Windows.  There is no API to set the orientation of a
-	* file dialog.  It is always inherited from the parent.  The fix is
-	* to create a hidden parent and set the orientation in the hidden
+	* Feature in Windows.  There is no API to set the BIDI orientation
+	* of a print dialog.  It is always inherited from the parent.  The fix
+	* is to create a hidden parent and set the orientation in the hidden
 	* parent for the dialog to inherit.
 	*/
 	boolean enabled = false;
@@ -324,28 +324,57 @@
 	pd.lStructSize = PRINTDLG.sizeof;
 	pd.hwndOwner = hwndOwner;
 	
-	/* Initialize PRINTDLG fields, including DEVMODE. */
-	pd.Flags = OS.PD_RETURNDEFAULT;
-	if (OS.PrintDlg(pd)) {
-		if (pd.hDevNames != 0) {
-			OS.GlobalFree(pd.hDevNames);
-			pd.hDevNames = 0;
+	boolean success = true;
+	if (printerData.name != null) {
+		/*
+		 * Initialize PRINTDLG DEVNAMES for the specified printer.
+		 * Note: Do not initialize DEVMODE dmDeviceName, because it truncates.
+		 */
+		TCHAR buffer = new TCHAR(0, printerData.name, true);
+		int size = buffer.length() * TCHAR.sizeof;
+		short[] offsets = new short[4]; // DEVNAMES (4 offsets)
+		int offsetsSize = offsets.length * 2; // 2 bytes each
+		offsets[1] = (short) ((offsetsSize) / TCHAR.sizeof); // offset 1 points to printer name
+		int /*long*/ hMem = OS.GlobalAlloc(OS.GMEM_MOVEABLE | OS.GMEM_ZEROINIT, offsetsSize + size);
+		int /*long*/ ptr = OS.GlobalLock(hMem);
+		OS.MoveMemory(ptr, offsets, offsetsSize);
+		OS.MoveMemory(ptr + offsetsSize, buffer, size);
+		OS.GlobalUnlock(hMem);
+		pd.hDevNames = hMem;
+	} else {
+		/*
+		 * Initialize PRINTDLG fields, including DEVMODE, for the default printer.
+		 */
+		pd.Flags = OS.PD_RETURNDEFAULT;
+		if (success = OS.PrintDlg(pd)) {
+			if (pd.hDevNames != 0) {
+				OS.GlobalFree(pd.hDevNames);
+				pd.hDevNames = 0;
+			}
 		}
+	}
 
+	if (success) {
 		/*
 		 * If user setup info from a previous print dialog was specified,
 		 * then restore the previous DEVMODE struct.
 		 */
 		byte devmodeData [] = printerData.otherData;
 		if (devmodeData != null && devmodeData.length != 0) {
-			int /*long*/ lpInitData = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, devmodeData.length);
-			OS.MoveMemory(lpInitData, devmodeData, devmodeData.length);
+			int /*long*/ hMem = OS.GlobalAlloc(OS.GMEM_MOVEABLE | OS.GMEM_ZEROINIT, devmodeData.length);
+			int /*long*/ ptr = OS.GlobalLock(hMem);
+			OS.MoveMemory(ptr, devmodeData, devmodeData.length);
+			OS.GlobalUnlock(hMem);
 			if (pd.hDevMode != 0) OS.GlobalFree(pd.hDevMode);
-			pd.hDevMode = lpInitData;
+			pd.hDevMode = hMem;
 		}
 		
 		/* Initialize the DEVMODE struct's fields from the printerData. */
 		int /*long*/ hMem = pd.hDevMode;
+		if (hMem == 0) {
+			hMem = OS.GlobalAlloc(OS.GMEM_MOVEABLE | OS.GMEM_ZEROINIT, DEVMODE.sizeof);
+			pd.hDevMode = hMem;
+		}
 		int /*long*/ ptr = OS.GlobalLock(hMem);
 		DEVMODE devmode = OS.IsUnicode ? (DEVMODE)new DEVMODEW () : new DEVMODEA ();
 		OS.MoveMemory(devmode, ptr, OS.IsUnicode ? OS.DEVMODEW_sizeof() : OS.DEVMODEA_sizeof());
@@ -396,7 +425,7 @@
 		String key = "org.eclipse.swt.internal.win32.runMessagesInIdle"; //$NON-NLS-1$
 		Object oldValue = display.getData(key);
 		display.setData(key, new Boolean(true));
-		boolean success = OS.PrintDlg(pd);
+		success = OS.PrintDlg(pd);
 		display.setData(key, oldValue);
 		if ((getStyle() & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) != 0) {
 			for (int i=0; i<shells.length; i++) {
@@ -433,15 +462,7 @@
 				i++;
 			}
 			String device = buffer.toString(deviceOffset, i);	
-	
-			int outputOffset = offsets[2];
-			i = 0;
-			while (outputOffset + i < size) {
-				if (buffer.tcharAt(outputOffset + i) == 0) break;
-				i++;
-			}
-			String output = buffer.toString(outputOffset, i);
-			
+
 			/* Create PrinterData object and set fields from PRINTDLG */
 			data = new PrinterData(driver, device);
 			if ((pd.Flags & OS.PD_PAGENUMS) != 0) {
@@ -452,7 +473,7 @@
 				data.scope = PrinterData.SELECTION;
 			}
 			data.printToFile = (pd.Flags & OS.PD_PRINTTOFILE) != 0;
-			if (data.printToFile) data.fileName = output;
+			if (data.printToFile) data.fileName = printerData.fileName;
 			data.copyCount = pd.nCopies;
 			data.collate = (pd.Flags & OS.PD_COLLATE) != 0;
 	
@@ -462,6 +483,8 @@
 			ptr = OS.GlobalLock(hMem);
 			data.otherData = new byte[size];
 			OS.MoveMemory(data.otherData, ptr, size);
+			
+			/* Set PrinterData fields from DEVMODE */
 			devmode = OS.IsUnicode ? (DEVMODE)new DEVMODEW () : new DEVMODEA ();
 			OS.MoveMemory(devmode, ptr, OS.IsUnicode ? OS.DEVMODEW_sizeof() : OS.DEVMODEA_sizeof());
 			if ((devmode.dmFields & OS.DM_ORIENTATION) != 0) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Printing/win32/org/eclipse/swt/printing/Printer.java b/bundles/org.eclipse.swt/Eclipse SWT Printing/win32/org/eclipse/swt/printing/Printer.java
index 9cbc548..dd71dd0 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT Printing/win32/org/eclipse/swt/printing/Printer.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Printing/win32/org/eclipse/swt/printing/Printer.java
@@ -353,7 +353,11 @@
 		di.lpszDocName = lpszDocName;
 	}
 	int /*long*/ lpszOutput = 0;
-	if (data.printToFile && data.fileName != null) {
+	if (data.printToFile) {
+		if (data.fileName == null) {
+			/* Prompt the user for a file name. */
+			data.fileName = "FILE:"; //$NON-NLS-1$
+		}
 		/* Use the character encoding for the default locale */
 		TCHAR buffer = new TCHAR(0, data.fileName, true);
 		int byteCount = buffer.length() * TCHAR.sizeof;