473,385 Members | 1,901 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

permission to call SetPrinter from C#

Hi,

I try to change some printer settings using the win32 api OpenPrinter,
GetPrinter and SetPrinter. I copied most of the code from this or
related newsgroups. However, OpenPrinter, GetPrinter and ClosePrinter
works so far but I cannot change the printer settings. SetPrinter
returns the error code 5 ACCESS DENIED. I know I have to deal with the
desired access mask in the _DEFAULT_PRINTER structure when calling
OpenPrinter. Unfortunaltely the declaration of the DEFAULT_PRINTER
structure or class I found on the internet doesn't work with the
OpenPrinter function.

Here is the code (Warning: don't proceed with reading if you find bad code
offending! I'm not a programer and I'm new to C#)

public class Printer
{
[DllImport("winspool.drv",CharSet=CharSet.Unicode,E xactSpelling=false,
CallingConvention=CallingConvention.StdCall )]
public static extern bool OpenPrinter(string pPrinterName,ref IntPtr
phPrinter, PRINTER_DEFAULTS pDefaults);
[DllImport("winspool.drv",CharSet=CharSet.Unicode,E xactSpelling=true,
CallingConvention=CallingConvention.StdCall )]
public static extern bool ClosePrinter(IntPtr hPrinter);

[DllImport("winspool.drv", CharSet=CharSet.Auto)]
public static extern bool GetPrinterA(IntPtr hPrinter, int dwLevel,
IntPtr pPrinter, int cbBuf, ref int pcbNeeded);

[DllImport("WinSpool.drv",SetLastError=true)]
public static extern bool SetPrinter (IntPtr hPrinter, int dwLevel,
ref PRINTER_INFO_8 pPrinter, uint Command);

public struct PRINTER_DEFAULTS
{
public string pDataType;
public DEVMODE pDevMode;
public ACCESS_MASK DesiredAccess;
}

public struct PRINTER_DEFAULTS
{
public string pDataType;
public DEVMODE pDevMode;
public ACCESS_MASK DesiredAccess;
}
[Flags] public enum ACCESS_MASK

{

PRINTER_ACCESS_ADMINISTER = 4,

PRINTER_ACCESS_USE = 8,

PRINTER_ALL_ACCESS = 983052

}

}
class MyClass
{
[STAThread]
static void Main(string[] args)
{

int dwLevel = 8;
bool retVal = false;
printer.PRINTER_INFO_8 printerInfo = new printer.PRINTER_INFO_8();

System.IntPtr lhPrinter= new System.IntPtr();
printer.PRINTER_DEFAULTS pd = new printer.PRINTER_DEFAULTS();

pd.pDataType = "";
pd.pDevMode = new DEVMODE();
pd.DesiredAccess = printer.ACCESS_MASK.PRINTER_ALL_ACCESS;

retVal = printer.OpenPrinter("Printer", ref lhPrinter, pd);

.....

I appreciate your help!

- Stephan
Nov 15 '05 #1
6 10571
Stephan,

Your system date seems to be wrong.

[DllImport("winspool.drv",CharSet=CharSet.Unicode,E xactSpelling=false,
CallingConvention=CallingConvention.StdCall )]
public static extern bool OpenPrinter(string pPrinterName,ref IntPtr
phPrinter, PRINTER_DEFAULTS pDefaults);
[DllImport("winspool.drv",CharSet=CharSet.Unicode,E xactSpelling=true,
CallingConvention=CallingConvention.StdCall )]
public static extern bool ClosePrinter(IntPtr hPrinter);

[DllImport("winspool.drv", CharSet=CharSet.Auto)]
public static extern bool GetPrinterA(IntPtr hPrinter, int dwLevel,
IntPtr pPrinter, int cbBuf, ref int pcbNeeded);

[DllImport("WinSpool.drv",SetLastError=true)]
public static extern bool SetPrinter (IntPtr hPrinter, int dwLevel,
ref PRINTER_INFO_8 pPrinter, uint Command);
I'd declare these as

[DllImport("winspool.drv", CharSet=CharSet.Auto)]
public static extern bool OpenPrinter(string pPrinterName, out IntPtr
phPrinter, ref PRINTER_DEFAULTS pDefaults);

[DllImport("winspool.drv")]
public static extern bool ClosePrinter(IntPtr hPrinter);

[DllImport("winspool.drv", CharSet=CharSet.Auto)]
public static extern bool GetPrinter(IntPtr hPrinter, int dwLevel,
IntPtr pPrinter, int cbBuf, out int pcbNeeded);

[DllImport("winspool.drv", CharSet=CharSet.Auto)]
public static extern bool SetPrinter(IntPtr hPrinter, int dwLevel, ref
PRINTER_INFO_8 pPrinter, uint Command);

Note that the pDefaults parameter of OpenPrinter must be ref if
PRINTER_DEFAULTS is a struct.

public struct PRINTER_DEFAULTS
{
public string pDataType;
public DEVMODE pDevMode;
public ACCESS_MASK DesiredAccess;
}
Make this

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
public struct PRINTER_DEFAULTS
{
public string pDataType;
public IntPtr pDevMode;
public ACCESS_MASK DesiredAccess;
}

pDevMode is a *pointer to* a DEVMODE structure.

pd.DesiredAccess = printer.ACCESS_MASK.PRINTER_ALL_ACCESS;


Preferrably you should open the printer handle with the least possible
access rights. It makes it more likely that your code will work also
for non-admins. If SetPrinter is all you want to do, I believe
PRINTER_ACCESS_ADMINISTER should be enough.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Nov 15 '05 #2
I have a similar issue..

I actually followed the method described at http://support.microsoft.com/default...kb;en-us;14028

However my version is in C# using the normal "SAFE" calls i.e. Marshal.whateve

And I still get the "Error 5: Access is denied." error from the "setprinter" call

I have Administrator rights with my local login on my Windows 2000 pc.

I'd really appreciate it if anyone has any suggestions or can see something that I am blatantly doing wrong. =

My Code is below. Everything seems to work until I get to the "SetPrinter" call
I haven't cleaned up the code i.e. No code to free up allocated memory yet

Declarations
[DllImport("kernel32.dll", EntryPoint="GetLastError", SetLastError=false,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
internal static extern Int32 GetLastError()

[DllImport("winspool.Drv", EntryPoint="ClosePrinter", SetLastError=true,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)
static extern bool ClosePrinter(IntPtr hPrinter)

[DllImport("winspool.Drv", EntryPoint="DocumentPropertiesA", SetLastError=true,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)
private static extern long DocumentProperties (IntPtr hwnd, IntPtr hPrinter,
[MarshalAs(UnmanagedType.LPStr)] string pDeviceNameg,
IntPtr pDevModeOutput, IntPtr pDevModeInput, IntPtr fMode)

[DllImport("winspool.Drv", EntryPoint="GetPrinterA", SetLastError=true, CharSet=CharSet.Ansi
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)
private static extern bool GetPrinter(IntPtr hPrinter, Int32 dwLevel,
IntPtr pPrinter, Int32 dwBuf, out Int32 dwNeeded)

[DllImport("winspool.Drv", EntryPoint="OpenPrinterA", SetLastError=true, CharSet=CharSet.Ansi,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)
static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter,
out IntPtr hPrinter, PRINTER_DEFAULTS pd)

[DllImport("winspool.drv", CharSet=CharSet.Auto, SetLastError=true)
private static extern bool SetPrinter(IntPtr hPrinter, int Level, IntPtr pPrinter, int Command)

// Wrapper for Win32 message formatter
[DllImport("kernel32.dll", CharSet=System.Runtime.InteropServices.CharSet.Aut o)
private unsafe static exter
int FormatMessage( int dwFlags
ref IntPtr pMessageSource
int dwMessageID
int dwLanguageID
ref string lpBuffer
int nSize
IntPtr* pArguments)

[StructLayout(LayoutKind.Sequential)
private struct PRINTER_DEFAULT

public int pDatatype
public int pDevMode
public int DesiredAccess
[StructLayout(LayoutKind.Sequential)
private struct PRINTER_INFO_

[MarshalAs(UnmanagedType.LPStr)] public string pServerName;
[MarshalAs(UnmanagedType.LPStr)] public string pPrinterName;
[MarshalAs(UnmanagedType.LPStr)] public string pShareName;
[MarshalAs(UnmanagedType.LPStr)] public string pPortName;
[MarshalAs(UnmanagedType.LPStr)] public string pDriverName;
[MarshalAs(UnmanagedType.LPStr)] public string pComment;
[MarshalAs(UnmanagedType.LPStr)] public string pLocation;
public IntPtr pDevMode;
[MarshalAs(UnmanagedType.LPStr)] public string pSepFile;
[MarshalAs(UnmanagedType.LPStr)] public string pPrintProcessor;
[MarshalAs(UnmanagedType.LPStr)] public string pDatatype;
[MarshalAs(UnmanagedType.LPStr)] public string pParameters;
public IntPtr pSecurityDescriptor;
public Int32 Attributes;
public Int32 Priority;
public Int32 DefaultPriority;
public Int32 StartTime;
public Int32 UntilTime;
public Int32 Status;
public Int32 cJobs;
public Int32 AveragePPM;
private const short CCDEVICENAME = 32
private const short CCFORMNAME = 32

[StructLayout(LayoutKind.Sequential)]
private struct DEVMODE
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCDEVICENAME)]
public string dmDeviceName

public short dmSpecVersion
public short dmDriverVersion
public short dmSize
public short dmDriverExtra
public int dmFields;
public short dmOrientation;
public short dmPaperSize;
public short dmPaperLength;
public short dmPaperWidth;
public short dmScale;
public short dmCopies;
public short dmDefaultSource;
public short dmPrintQuality;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCFORMNAME)]
public string dmFormName;

public short dmUnusedPadding;
public short dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
}

public const int DM_DUPLEX = 0x1000;
public const int DM_IN_BUFFER = 8;

public const int DM_OUT_BUFFER = 2;
public const int PRINTER_ACCESS_ADMINISTER = 0x4;
public const int PRINTER_ACCESS_USE = 0x8;
public const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
public const int PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE);

And the actual logic:

public bool SetPrinterDuplex(string sPrinterName, int nDuplexSetting)
{
IntPtr hPrinter;
PRINTER_DEFAULTS pd = new PRINTER_DEFAULTS();
PRINTER_INFO_2 pinfo = new PRINTER_INFO_2();
DEVMODE dm;
IntPtr ptrDM;
IntPtr ptrPrinterInfo;

int lastError;
byte[] yDevModeData;
byte[] yPInfoMemory;
int nBytesNeeded;
int nRet;
System.Int32 nJunk;

//On Error GoTo cleanup

if ((nDuplexSetting < 1) || (nDuplexSetting > 3) )
{
throw new ArgumentOutOfRangeException("nDuplexSetting","nDup lexSetting is incorrect.");
}
else
{
//if no printername provided, check if there is a default printer and use it instead
if (sPrinterName.Trim() == "")
{
PrintDocument printDocument1 = new PrintDocument();
sPrinterName = printDocument1.PrinterSettings.PrinterName + "\0";
}

//open the printer
pd.DesiredAccess = PRINTER_ALL_ACCESS;
nRet = Convert.ToInt32(OpenPrinter(sPrinterName, out hPrinter, pd));

if ((nRet == 0) || (hPrinter == IntPtr.Zero))
{
return false;
}

//get the size of the Printer Info structure
GetPrinter(hPrinter, 2, IntPtr.Zero, 0, out nBytesNeeded);
if (nBytesNeeded <= 0)
{
return false;
}

// Allocate enough space for PRINTER_INFO_2...
ptrPrinterInfo = Marshal.AllocCoTaskMem(nBytesNeeded);

// The second GetPrinter fills in all the current settings, so all you
// need to do is modify what you're interested in...
nRet = Convert.ToInt32(GetPrinter(hPrinter, 2, ptrPrinterInfo, nBytesNeeded, out nJunk));
if (nRet == 0)
{
return false;
}

pinfo = (PRINTER_INFO_2)Marshal.PtrToStructure(ptrPrinterI nfo, typeof(PRINTER_INFO_2));

if (pinfo.pDevMode == IntPtr.Zero)
{
// If GetPrinter didn't fill in the DEVMODE, try to get it by calling
// DocumentProperties...

//get the size of the devmode structure
nRet = (int)DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
if (nRet <= 0)
{
return false;
}

ptrDM = Marshal.AllocCoTaskMem(nRet);

nRet = (int)DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, ptrDM,
IntPtr.Zero, (IntPtr)DM_OUT_BUFFER);
if ((nRet < 0) || (ptrDM == IntPtr.Zero))
{
//Cannot get the DEVMODE structure.
return false;
}

pinfo.pDevMode = ptrDM;

}

dm = (DEVMODE)Marshal.PtrToStructure(pinfo.pDevMode, typeof(DEVMODE));
if (!Convert.ToBoolean(dm.dmFields & DM_DUPLEX))
{
//You cannot modify the duplex flag for this printer
//because it does not support duplex or the driver does not support setting
//it from the Windows API.
return false;
}

//update fields
dm.dmDuplex = (short)nDuplexSetting;
dm.dmFields = DM_DUPLEX;

Marshal.StructureToPtr(dm,pinfo.pDevMode,true);

//pinfo.pDevMode = ptrDM;
pinfo.pSecurityDescriptor = IntPtr.Zero;

//update driver dependent part of the DEVMODE
nRet = (int)DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, pinfo.pDevMode
, pinfo.pDevMode, (IntPtr)(DM_IN_BUFFER | DM_OUT_BUFFER));
if (nRet < 0)
{
//Unable to set duplex setting to this printer.
return false;
}

Marshal.StructureToPtr(pinfo,ptrPrinterInfo,true);

lastError = Marshal.GetLastWin32Error();

nRet = Convert.ToInt16(SetPrinter(hPrinter, 2, ptrPrinterInfo, 0));
if (nRet == 0)
{
//Unable to set shared printer settings.
lastError = Marshal.GetLastWin32Error();
string myErrMsg = GetErrorMessage(lastError);

return false;
}
}
if (hPrinter != IntPtr.Zero)
ClosePrinter(hPrinter);

return Convert.ToBoolean(nRet);

}//End SetPrinterDuplex

Nov 15 '05 #3
Joseph,
And I still get the "Error 5: Access is denied." error from the "setprinter" call.


I'm surprised that you don't get an error earlier.

In the OpenPrinter declaration, the PRINTER_DEFAULTS parameter should
be passed by ref.

And the DocumentProperties return type should be an int, not a long.

Also, you seem to be forgetting to free the memory you allocate with
Marshal.AllocCoTaskMem.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Nov 15 '05 #4
Thanks for the suggestions
I made the changes and ran it again and now I seem to get passed the "Access denied" error however it now comes up with a different error

"Error 1797: The printer driver is unknown.\r\n

Could it be the way I have declared my structures or API's?
Nov 15 '05 #5
Joseph,
I made the changes and ran it again and now I seem to get passed the "Access denied" error however it now comes up with a different error:


Which call is it that's failing?

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Nov 15 '05 #6
check weather u r trying to change the network priner. Following link may help you

http://support.microsoft.com/default...&NoWebContent=
984534805

regard
umesh.

Nov 16 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Yitzhak | last post by:
I am having "Permission denied" error while calling LogEvent method of WScript.Shell component. Basically, ASP page calls Windows Script Host Shell component to log events to the OS Application...
3
by: HikksNotAtHome | last post by:
In Mozilla 1.4b, when the URL is set to a local URL, it works as expected. function showIt(){ var xmlhttp = new XMLHttpRequest(); xmlhttp.open("GET", "blank.html" ,true);...
12
by: Russ | last post by:
Hello. My new dev machine is running XP Pro. In the past all equipment has only used Windows 2000. I have had a lot of problems getting my projects up and running on the new machine. The current...
10
by: Joe M | last post by:
I was wondering if someone could lend me a hand with a C# problem I am having I am trying to use the “setPrinter†api to change the duplex setting (under printing preferences on printer...
3
by: Chua Wen Ching | last post by:
Hi there, I had applied this security permissions in my class library based on fxcop standards. Before namespace: using System.Runtime.InteropServices; using System.Security.Permissions;
0
by: Mike Ripplinger | last post by:
Hi there. I'm trying to write a program that purges the print queue for a selected printer. I was hoping to do this by simply calling the external prnqctl.vbs script, but this program has to run...
0
by: Benjamin Gavin | last post by:
Hi all, I am running into a rather bizarre problem with one of my web applications. I'm in the process of applying the PrincipalPermissionAttribute to a number of pages and I've stumbled into a...
0
by: Francisco Araujo | last post by:
I have been trying to change printer settings thru SetPrinter API and it works successfully for local printers, but with network printers i don't get neither an error message or anything else. ...
1
by: Charlie | last post by:
I am trying to make an XMLHttpRequest which violates the default "same- origin"policy in Firefox. I checked the archives and found a method that should work but it does not. Below is the test code...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.