Win32 LPTSTR -=> [MarshalAs(UnmanagedType.LPStr)] public string?

V

valentin tihomirov

There are three types of strings for P/Invoke marshalling: LPstr, LPTStr and
LPWStr. It is reasonable to guess that the types corrsepond to the Win32
platform types. However, I have mentioned and want to know why the platform
LPTSTR must be mapped as LPStr and fails when marshaled as LPTStr.


The Win32 structure documented at
http://msdn2.microsoft.com/en-us/library/ms535671.aspx has a lot of pointers
to strings:

typedef struct JOB_INFO_2 {
DWORD JobId;
LPTSTR pPrinterName;
LPTSTR pMachineName;
LPTSTR pUserName;
LPTSTR pDocument;
LPTSTR pNotifyName;
etc

As explained in System.Runtime.InteropServices.UnmanagedType Enumeration
http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.unmanagedtype(VS.71).aspx ,
LPTStr is different from LPStr in that the pointed to characters are
plarform-dependent. LPStr always potints to ANSI while LPTStr points to
Unicode chars in Windows NT. Since, the Win32 structure pointers are
'T'-labeled, I have chosen the UnmanagedType.LPTStr marshalling:
[StructLayout(LayoutKind.Sequential] public
struct JOB_INFO_2 {
public short JobId;
[MarshalAs(UnmanagedType.LPTStr)] public string pPrinterName;
[MarshalAs(UnmanagedType.LPTStr)] public string pMachineName;
...
This is how I managed to marshal LPTSTR lpPath of ADDJOB_INFO_1. However
this time, the strings contain garbage after marshalling. Since non-textual
fields unmarshalled correctly, I conclueded that the problem is in character
recognition. Since I run WinXP (unicode is native), the reason of
misinterpirtaion could be that the strings GetJob returns ANSI string
independently of the platform. Actually, my conjecture was raised earlier by
PRINTER_INFO_2 unmarshaling demo
http://www.codeproject.com/dotnet/NET_Printer_Library.asp?df=100&forumid=39971&exp=0&fr=26 ,
which declares pointers to ANSI chars despite the chars are claimed
platfrom-dependent in the MSDN. And it works! The strings are ANSI indeed.
They show '?' in the position of non-ansi characters.

So the question is -- why is the inconsistency needed? That is, why lpTstr
(plarform-dependent type) should be presented as lpstr (ansi) to .net
marshaller if there is a corrseponding special platform type lpTstr for the
purpose? Why LPTSTR is marshalled as UnmanagedType.LPTStr in the case of
ADDJOB_INFO_1 lpPath and as UnmanagedType.LPStr in the case of JOB_INFO_2
and PRINTER_INFO_2 if both structures refer LPTSTR-type strings?

The CharSet attribute does not affect the performance.
 
V

valentin tihomirov

I have discovered that the structure char encoding depents on the version of
the platform function you invoke (Ansi- of Wide- string) rather than on the
platform itself. EntryPoint attribute hardcodes the version to invoke, while
CharSet attribute chooses the version of the function to load depending on
the platform. Still do not know the moment at which the platform is
determined (compilation or execution).

Compiling and executing an app, which invokes a platform function, on
Windows XP, where the function is declared without EntryPoint nor CharSet
attributes, invoks functionA. Auto CharSet turns to the functionW.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top