I'm trying to open a raw printer connection and the StartDocPrinter call is failing. Win32Error is 122 (ERROR_INSUFFICIENT_BUFFER).
This executable works fine on the same computer when run as a normal user or as administrator, but fails when run as the "local system" user. (Though I've had it work on several other computers running as the "local system" user.) I really don't want to consider running it as a different user, since it's running through a service and would probably involve several other large changes to the system.
using System;
using System.Runtime.InteropServices;
namespace EPLTest
{
class Program
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class DOCINFOA
{
[MarshalAs(UnmanagedType.LPStr)]
public string pDocName;
[MarshalAs(UnmanagedType.LPStr)]
public string pOutputFile;
[MarshalAs(UnmanagedType.LPStr)]
public string pDataType;
}
[DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);
[DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
[DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EndDocPrinter(IntPtr hPrinter);
static void Main(string[] args)
{
IntPtr hPrinter;
if (!OpenPrinter("ZDesigner LP2824 Raw".Normalize(), out hPrinter, IntPtr.Zero))
{
Console.WriteLine("OpenPrinter Error:" + Marshal.GetLastWin32Error());
return;
}
Console.WriteLine("hPrinter: " + hPrinter.ToString("x8"));
DOCINFOA di = new DOCINFOA { pDocName = "Barcode Test", pDataType = "RAW" };
if (StartDocPrinter(hPrinter, 1, di))
{
Console.WriteLine("StartDocPrinter Success");
// Printing code omitted for brevity
EndDocPrinter(hPrinter);
}
else
{
Console.WriteLine("StartDocPrinter Error:" + Marshal.GetLastWin32Error());
}
ClosePrinter(hPrinter);
}
}
}
Sample output:
hPrinter: 010b7e3c
StartDocPrinter Error:122
Any ideas?
Related
I have dot matrix printer, but when I print it some of the characters doesn't accept, like degrees(°), diameter(Ø), number with power of two(2²) and etc. Take a look at the photos.
EXAMPLE OUTPUT
When printing it shows a black SQUARE.
This is the line code.
MyPrinter.Print((char)15 + " itemname.Text " + "\r\n");
This is the Class code
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class DOCINFOA
{
[MarshalAs(UnmanagedType.LPStr)] public string pDocName;
[MarshalAs(UnmanagedType.LPStr)] public string pOutputFile;
[MarshalAs(UnmanagedType.LPStr)] public string pDataType;
}
[DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);
[DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
[DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EndDocPrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartPagePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EndPagePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);
/*=================================================*/
private IntPtr HandlePrinter;
public PrinterSettings ps;
public LPrinter()
{
HandlePrinter = IntPtr.Zero;
ps = new PrinterSettings();
}
public PrintDialog pd = new PrintDialog();
public string PrinterName
{
get
{
return ps.PrinterName;
}
set
{
ps.PrinterName = value;
}
}
public bool Open(string DocName)
{
// see if printer is already open
if (HandlePrinter != IntPtr.Zero) return false;
// opens the printer
bool risp = OpenPrinter(ps.PrinterName, out HandlePrinter, IntPtr.Zero);
if (risp == false) return false;
// starts a print job
DOCINFOA MyDocInfo = new DOCINFOA();
MyDocInfo.pDocName = DocName;
MyDocInfo.pOutputFile = null;
MyDocInfo.pDataType = "RAW";
if (StartDocPrinter(HandlePrinter, 1, MyDocInfo))
{
StartPagePrinter(HandlePrinter); //starts a page
return true;
}
else return false;
}
public bool Close()
{
if (HandlePrinter == IntPtr.Zero) return false;
if (!EndPagePrinter(HandlePrinter)) return false;
if (!EndDocPrinter(HandlePrinter)) return false;
if (!ClosePrinter(HandlePrinter)) return false;
HandlePrinter = IntPtr.Zero;
return true;
}
public bool Print(string outputstring)
{
if (HandlePrinter == IntPtr.Zero) return false;
IntPtr buf = Marshal.StringToCoTaskMemAnsi(outputstring);
Int32 done = 0;
bool ok = WritePrinter(HandlePrinter, buf, outputstring.Length, out done);
Marshal.FreeCoTaskMem(buf);
if (!ok) return false;
else return true;
}
Hope someone can help me to fix this.
I'm currently developing an app that have to move a file to another application folder. But the other application must have a specific permissions on files that are copied.
When I use the Win32 API to MoveFileFromApp (it's uwp app), it doesn't update the security attributes to inherit the folder.
here is the code of MoveFile (C#)
[DllImport("api-ms-win-core-file-fromapp-l1-1-0.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
internal static extern bool MoveFileFromApp(
string lpExistingFileName, string lpNewFileName);
Does anyone know how to set these security permissions for the folder automatically during the moving process ?
Thank you very much !
I tried to use SetNamedSecurityInfo method by P/Invoke in UWP app with the following code. The error ERROR_ACCESS_DENIED(error code is 5) always exists in UWP app. But in Win32, the usage of SetNamedSecurityInfo method with the value UNPROTECTED_DACL_SECURITY_INFORMATION to inherit the security attributes is successful.
In UWP, there are some limitations on file system access permission. Though the SetNamedSecurityInfo method can be called successfully, it does not work as expected.
The code to use SetNamedSecurityInfo method in UWP:
public uint DACL_SECURITY_INFORMATION = 0x00000004;
public uint UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000;
public uint ACL_REVISION = 0x2;
[StructLayout(LayoutKind.Sequential)]
public struct ACL
{
public byte AclRevision;
public byte Sbz1;
public ushort AclSize;
public ushort AceCount;
public ushort Sbz2;
}
public enum SE_OBJECT_TYPE
{
SE_UNKNOWN_OBJECT_TYPE = 0,
SE_FILE_OBJECT,
SE_SERVICE,
SE_PRINTER,
SE_REGISTRY_KEY,
SE_LMSHARE,
SE_KERNEL_OBJECT,
SE_WINDOW_OBJECT,
SE_DS_OBJECT,
SE_DS_OBJECT_ALL,
SE_PROVIDER_DEFINED_OBJECT,
SE_WMIGUID_OBJECT,
SE_REGISTRY_WOW64_32KEY,
SE_REGISTRY_WOW64_64KEY,
}
[DllImport("api-ms-win-core-file-fromapp-l1-1-0.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool MoveFileFromAppW(
string lpExistingFileName,
string lpNewFileName);
[DllImport("advapi32.DLL", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern uint SetNamedSecurityInfo(
string lpFileName,
SE_OBJECT_TYPE ObjectType,
uint SecurityInfo,
IntPtr psidOwner,
IntPtr psidGroup,
ref ACL pDacl,
IntPtr pSacl);
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool InitializeAcl(ref ACL pAcl, int nAclLength, uint dwAclRevision);
[DllImport("api-ms-win-core-file-fromapp-l1-1-0.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall,
SetLastError = true)]
internal static extern bool MoveFileFromApp(
string lpExistingFileName,
string lpNewFileName
);
public void SetFilePermission(string FileName)
{//Use the method to let the file inherit the security attributes from parent object
bool ret = false;
ACL pDacl = new ACL();
ret = InitializeAcl(ref pDacl, Marshal.SizeOf<ACL>(), ACL_REVISION);
uint SecurityInfo = DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION;
uint err = SetNamedSecurityInfo(FileName, SE_OBJECT_TYPE.SE_FILE_OBJECT, SecurityInfo, IntPtr.Zero, IntPtr.Zero, ref pDacl, IntPtr.Zero);
}
I was trying to get Accent Color for use in my WPF app, and i found one class in GitHub that always is the same.
static class UxTheme
{
[DllImport("uxtheme.dll", EntryPoint = "#98", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
public static extern uint GetImmersiveUserColorSetPreference(bool forceCheckRegistry, bool skipCheckOnFail);
[DllImport("uxtheme.dll", EntryPoint = "#94", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
public static extern uint GetImmersiveColorSetCount();
[DllImport("uxtheme.dll", EntryPoint = "#95", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
public static extern uint GetImmersiveColorFromColorSetEx(uint immersiveColorSet, uint immersiveColorType,
bool ignoreHighContrast, uint highContrastCacheMode);
[DllImport("uxtheme.dll", EntryPoint = "#96", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
public static extern uint GetImmersiveColorTypeFromName(IntPtr name);
[DllImport("uxtheme.dll", EntryPoint = "#100", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
public static extern IntPtr GetImmersiveColorNamedTypeByIndex(uint index);
}
I was finding uxtheme documentation in SDK and MSDN but this methods aren't.
I dumpbin uxtheme.dll and surprise! they are unnamed functions. (Except #95 & #98).
How can i get signatures of the uxtheme (or others) library? Then, i can try-error guessing the functions i need.
I am working with wtsapi32.dll. (Window Terminal Service api)
I am trying to get user info from method WTSQueryUserConfig.
[DllImport("wtsapi32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool WTSQueryUserConfig(
[MarshalAs(UnmanagedType.LPStr)] string pServerName,
[MarshalAs(UnmanagedType.LPStr)] string pUserName,
WTS_CONFIG_CLASS wtsConfigClass,
out StringBuilder pBuffer,
out int dataLength);
I have problem with user with SAM-Account-Name in japanese (unicode).
I have modified my class with (unicode version):
[DllImport("wtsapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool WTSQueryUserConfigW(
[MarshalAs(UnmanagedType.LPStr)] string pServerName,
[MarshalAs(UnmanagedType.LPStr)] string pUserName,
WTS_CONFIG_CLASS wtsConfigClass,
out StringBuilder pBuffer,
out int dataLength);
But I call this method with japanese SAM-Account-Name it does not work.
Users without unicode characters works fine with non-unicode version method.
Finally I only used the charset configuration for the input parameters
[DllImport("wtsapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool WTSQueryUserConfigW(
string pServerName,
string pUserName,
WindowsTerminalServiceConfig wtsConfigClass,
out StringBuilder pBuffer,
out int dataLength);
I try use a dll created in c in c#, but I get the error "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
I see very topics here, but i'm not solve the problem. It's possible help me?
My C# code is:
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32")]
public static extern bool FreeLibrary(IntPtr hModule);
[DllImport("lib.dll", EntryPoint = "LoadRes", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private static extern SRes LoadRes([MarshalAs(UnmanagedType.LPStr)]string str, bool type);
SRes sres = new SRes();
string path="C:\\123456.fil";
System.IntPtr load = LoadLibrary("lib.dll");
System.IntPtr adress = GetProcAddress(load, "LoadRes");
sres = LoadRes(path, true);
My code to export in c is
__declspec(dllexport) SRes LoadRes( const char *filename, bool header_only );
Thank's for help!!