Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. C#
  4. LPWSTR in C#

LPWSTR in C#

Scheduled Pinned Locked Moved C#
csharpjsonquestionannouncement
4 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Y Offline
    Y Offline
    yyf
    wrote on last edited by
    #1

    This is the API I want to use: long LoginDlg ( long lDSType, **LPTSTR** lptstrDataSource, long lDSLength, **LPCTSTR** lpctstrUsername, **LPCTSTR** lpctstrPassword, ) I wrap it like this: [DllImport("user.dll")] int LoginDlg ( int lDSType, **string**lptstrDataSource, int lDSLength, **string**lpctstrUsername, **string**lpctstrPassword, ) Now I got the new version of this api, the only difference is using LPWSTR instead of LPTSTR long LoginDlg ( long lDSType, **LPWSTR** lptstrDataSource, long lDSLength, **LPCWSTR** lpctstrUsername, **LPCWSTR** lpctstrPassword, ) I use the same wrapper, it doesn't work as usual. Do you have any ideas what's wrong with my wrapper? Thanks in advance.

    H 1 Reply Last reply
    0
    • Y yyf

      This is the API I want to use: long LoginDlg ( long lDSType, **LPTSTR** lptstrDataSource, long lDSLength, **LPCTSTR** lpctstrUsername, **LPCTSTR** lpctstrPassword, ) I wrap it like this: [DllImport("user.dll")] int LoginDlg ( int lDSType, **string**lptstrDataSource, int lDSLength, **string**lpctstrUsername, **string**lpctstrPassword, ) Now I got the new version of this api, the only difference is using LPWSTR instead of LPTSTR long LoginDlg ( long lDSType, **LPWSTR** lptstrDataSource, long lDSLength, **LPCWSTR** lpctstrUsername, **LPCWSTR** lpctstrPassword, ) I use the same wrapper, it doesn't work as usual. Do you have any ideas what's wrong with my wrapper? Thanks in advance.

      H Offline
      H Offline
      Heath Stewart
      wrote on last edited by
      #2

      First, understand how the unmanaged code (i.e., native code) looks (essentially):

      typedef char CHAR;
      typedef CHAR* LPSTR;
      typedef wchar_t WCHAR;
      typedef WCHAR* LPWSTR;
      #ifdef UNICODE
      typedef WCHAR TCHAR;
      typedef WCHAR* LPTSTR;
      #else
      typedef CHAR TCHAR;
      typedef CHAR* LPSTR;
      #endif

      That means that any Unicode strings use "W" as a convention (this is true with most Microsoft APIs - as well as others' APIs - that take strings as parameters; they end with either "A" for ANSI or "W" for Unicode and are #define'd without either "A" or "W", which is the one you typically call). When you use P/Invoke or COM interop (both are interop features), you must dictate which string encoding to use. By default in C#, CharSet.Ansi is used. In most cases when calling Microsoft APIs (and others - those I mentioned above), you will want to use CharSet.Auto. Where do you use those? When declaring P/Invoke methods, you use them in the DllImportAttribute like so:

      // Note: following is only anexample.
      // You can more easily get the computer name by using Environment.MachineName.
      [DllImport("user32.dll", CharSet=CharSet.Auto)]
      static extern bool GetComputerName([Out] string name, ref int size);

      When you're declaring a struct with string members, you do the same in the StructLayoutAttribute. In both cases, you can override the string encoding using the MarshalAsAttribute. Lets say, for some reason, you had a struct with ANSI and Unicode versions, except for one string member that must always be ANSI:

      [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
      public struct Example
      {
      public string Field1;
      public string Field2;
      [MarshalAs(UnmanagedType.LPStr)] public string Field3;
      }

      We default to CharSet.Auto (saves typing and is easier to maintain) but override the unmanaged type as UnmanagedType.LPStr (as opposed to UnmanagedType.LPWStr), so that it's always ANSI. You can do the same with P/Invoke declarations. Just make sure you understand the unmanaged code well enough to know whether it's always ANSI or Unicode, or if it is platform dependent (i.e., ANSI on Windows, Unicode on Windows NT). This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Sustained Engineering Microsoft [

      Y 1 Reply Last reply
      0
      • H Heath Stewart

        First, understand how the unmanaged code (i.e., native code) looks (essentially):

        typedef char CHAR;
        typedef CHAR* LPSTR;
        typedef wchar_t WCHAR;
        typedef WCHAR* LPWSTR;
        #ifdef UNICODE
        typedef WCHAR TCHAR;
        typedef WCHAR* LPTSTR;
        #else
        typedef CHAR TCHAR;
        typedef CHAR* LPSTR;
        #endif

        That means that any Unicode strings use "W" as a convention (this is true with most Microsoft APIs - as well as others' APIs - that take strings as parameters; they end with either "A" for ANSI or "W" for Unicode and are #define'd without either "A" or "W", which is the one you typically call). When you use P/Invoke or COM interop (both are interop features), you must dictate which string encoding to use. By default in C#, CharSet.Ansi is used. In most cases when calling Microsoft APIs (and others - those I mentioned above), you will want to use CharSet.Auto. Where do you use those? When declaring P/Invoke methods, you use them in the DllImportAttribute like so:

        // Note: following is only anexample.
        // You can more easily get the computer name by using Environment.MachineName.
        [DllImport("user32.dll", CharSet=CharSet.Auto)]
        static extern bool GetComputerName([Out] string name, ref int size);

        When you're declaring a struct with string members, you do the same in the StructLayoutAttribute. In both cases, you can override the string encoding using the MarshalAsAttribute. Lets say, for some reason, you had a struct with ANSI and Unicode versions, except for one string member that must always be ANSI:

        [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
        public struct Example
        {
        public string Field1;
        public string Field2;
        [MarshalAs(UnmanagedType.LPStr)] public string Field3;
        }

        We default to CharSet.Auto (saves typing and is easier to maintain) but override the unmanaged type as UnmanagedType.LPStr (as opposed to UnmanagedType.LPWStr), so that it's always ANSI. You can do the same with P/Invoke declarations. Just make sure you understand the unmanaged code well enough to know whether it's always ANSI or Unicode, or if it is platform dependent (i.e., ANSI on Windows, Unicode on Windows NT). This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Sustained Engineering Microsoft [

        Y Offline
        Y Offline
        yyf
        wrote on last edited by
        #3

        According to my understanding, the new method is using Unicode all the time. So I wrap it like this now: [DllImport("user.dll", CharSet = CharSet.Unicode)] int LoginDlg ( int lDSType, string lptstrDataSource, int lDSLength, string lpctstrUsername, string lpctstrPassword, ) But why it still doesn't work?

        H 1 Reply Last reply
        0
        • Y yyf

          According to my understanding, the new method is using Unicode all the time. So I wrap it like this now: [DllImport("user.dll", CharSet = CharSet.Unicode)] int LoginDlg ( int lDSType, string lptstrDataSource, int lDSLength, string lpctstrUsername, string lpctstrPassword, ) But why it still doesn't work?

          H Offline
          H Offline
          Heath Stewart
          wrote on last edited by
          #4

          Since the function is defined externally, you have to modify it as such, and all P/Invoke functions are static (i.e., they aren't defined by a class). Your signature should look like this:

          [DllImport("user.dll", CharSet=CharSet.Unicode)]
          extern static int LoginDlg(
          int lDSType,
          string lptstrDataSource,
          int lDSLength,
          string lpctstrUsername,
          string lpctstrPassword);

          Drop the comma after lpctstrPassowrd and add a semi-colon after the declaration, as well. BTW, since the parameter names begin with either lp**t**str or lpc**t**str, they are most likely using platform-dependent string encodings. You best check your API documentation and thoroughly examine your headers. Using "t" typically means that a string is platform dependent, although thiscould be just a different naming convention for your APIs. If these are Microsoft APIs, I assure you they're platform-dependent strings and you should use CharSet.Auto. This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Sustained Engineering Microsoft [My Articles]

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups