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.
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.