title: LDAP binding on Windows vs. VCE
body: <p>I have been given the simple task to do Windows authentication against the AD from a Windows Compact 7 device in a C# app. Now - 14 days later I'm still struggling, so any help would be greatly appreciated.</p>
  
  <p>Anyway - what I’ve managed to come up with so far is doing Windows authentication on my PC using the wldap32.dll. I’m far from a C++ expert, and with Visual C++ even less so, so bear with me.
  Here is my C++ code:</p>
  
  <pre><code>EXPORT_METHOD unsigned long Authenticate(char *userName, char *password, char *domain)
  {
      unsigned long result = 0;
  
      unsigned short *uUserName = (unsigned short *)userName;
      unsigned short *uPassword = (unsigned short *)password;
      unsigned short *uDomain = (unsigned short *)domain;
  
      PWCHAR hostName = NULL;
      LDAP* pLdapConnection = NULL;
      ULONG version = LDAP_VERSION3;
  
      size_t origsize = strlen("ELLAB.COM") + 1;
      size_t convertedChars = 0;
      wchar_t wcstring[100];
      mbstowcs_s(&amp;convertedChars, wcstring, origsize, "ELLAB.COM", _TRUNCATE);
      wcscat_s(wcstring, L" (wchar_t *)");
      hostName = wcstring;
  
      //  Initialize a session. LDAP_PORT is the default port, 389.
      pLdapConnection = ldap_init(hostName, LDAP_PORT);
  
      if (pLdapConnection == NULL)
      {
          #ifdef DEBUG
          AfxMessageBox(_T("Unable to Init"));
          #endif // DEBUG
          result = 0xff;
      }
      else
      {
          //  Set the version to 3.0 (default is 2.0).
          result = ldap_set_option(pLdapConnection, LDAP_OPT_PROTOCOL_VERSION, (void*)&amp;version);
          if (result != LDAP_SUCCESS)
          {
              #ifdef DEBUG
              AfxMessageBox(_T("Unable to Set Optins"));
              #endif // DEBUG
          }
          else
          {
              // Connect to the server.
              result = ldap_connect(pLdapConnection, NULL);
              if (result != LDAP_SUCCESS)
              {
                  #ifdef DEBUG
                  AfxMessageBox(_T("Unable to Connect"));
                  #endif // DEBUG
              }
              else
              {
                  //  Be aware that the password itself is never sent over the network, and encryption is not used.
                  SEC_WINNT_AUTH_IDENTITY NtAuthIdentity;
                  ZeroMemory(&amp;NtAuthIdentity, sizeof(NtAuthIdentity));
                  NtAuthIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  
                  NtAuthIdentity.Domain = uDomain;
                  NtAuthIdentity.DomainLength = sizeof(uDomain);
                  NtAuthIdentity.User = uUserName;
                  NtAuthIdentity.UserLength = sizeof(uUserName);
                  NtAuthIdentity.Password = uPassword;
                  NtAuthIdentity.PasswordLength = sizeof(uPassword);
  
                  //if (ldap_bind_s(pLdapConnection, NULL, NULL, LDAP_AUTH_NEGOTIATE) == LDAP_SUCCESS)
                  result = ldap_bind_s(pLdapConnection, NULL, (PWCHAR)&amp;NtAuthIdentity, LDAP_AUTH_NTLM);
                  //if (result != LDAP_SUCCESS)
                  {
                      #ifdef DEBUG
                      AfxMessageBox(_T("Unable to Bind using ldap_bind_s"));
                      #endif // DEBUG
                      result = ldap_bind(pLdapConnection, NULL, (PWCHAR)&amp;NtAuthIdentity, LDAP_AUTH_NTLM);
                      if (result != LDAP_SUCCESS)
                      {
                          #ifdef DEBUG
                          AfxMessageBox(_T("Unable to Bind using ldap_bind"));
                          #endif // DEBUG
                      }
                  }
              }
  
          }
          //  Normal cleanup and exit.
          ldap_unbind(pLdapConnection);
      }
  
      return result;
  }
  </code></pre>
  
  <p>And my C# sample wrapper:</p>
  
  <pre><code>[DllImport(@"C:\Users\ckbn.ELLAB\Documents\Visual Studio 2015\Projects\WCE7_LDAP\Debug\LDAPHandler.dll", CharSet = CharSet.Unicode)]
      public static extern int Authenticate(string userName, string password, string domain);
  
      private void buttonAuthenticate_Click(object sender, EventArgs e)
      {
          try
          {
              textBoxResult.Text = "";
              LDAPReturns result = (LDAPReturns)Authenticate(textBoxUserName.Text, textBoxPassword.Text, textBoxDomain.Text);
              switch (result)
              {
                  case LDAPReturns.LDAP_SUCCESS:
                      textBoxResult.Text = "User '" + textBoxUserName.Text + "' is authenticated";
                      break;
                  default:
                      textBoxResult.Text = result.ToString();
                      break;
              }
          }
          catch (Exception ex) { textBoxResult.Text = "Failed: " + ex.ToString(); }
      }
  </code></pre>
  
  <p>So - using the above code I can authenticate with my own credentials on my PC. Running the same code on the WCE device, I can connect to the AD server, but when I try to ldap_bind_s, it returns LDAP_AUTH_METHOD_NOT_SUPPORTED. So I’m thinking the the ARM version of the wldap32.dll is different from the x86 version. </p>
  
  <p>Then I tried to use the ldap_bind (without ‘_s’) method. This is not working nighter on my PC nor on the WCE device and always returns 0xFFFF_FFFF.</p>
  
  <p>So basically my questions are:</p>
  
  <p>What does  LDAP_AUTH_METHOD_NOT_SUPPORTED means, and what other methods do I have on a WCE7 device? and</p>
  
  <p>What does it means when ldap_bind returns 0xFFFF_FFFF?</p>
  
  <p>But any input or suggestion would be highly appreciated. Thanks in advance!</p>