/*++ Copyright (c) 1996 Microsoft Corporation Module Name: winldap.h LDAP client 32 API header file Abstract: This module is the header file for the 32 bit LDAP client API for Windows NT and Windows 95. This API is based on RFC 1823 with some enhancements for LDAP v3. Notes about Unicode support : If you have UNICODE defined at compile time, you'll pull in the unicode versions of the calls. Note that your executable may then not work with other implementations of the LDAP API that don't support Unicode. If UNICODE is not defined, then we define the LDAP calls without the trailing 'A' (as in ldap_bind rather than ldap_bindA) so that your app may work with other implementations that don't support Unicode. The import library has all three forms of the call present... ldap_bindW, ldap_bindA, and ldap_bind. ldap_bindA simply calls ldap_bind. ldap_bind simply converts the arguments to unicode and calls ldap_bindW. The reason this is done is because we have to put UTF-8 on the wire, so if we converted from Unicode to single byte, we'd loose information. Since all core processing is done in Unicode, nothing is lost. Updates : 11/01/96 Modified for new API RFC draft. Environments : Win32 user mode --*/ // // Only pull in this header file once... controlled by LDAP_CLIENT_DEFINED // variable. // #ifndef LDAP_CLIENT_DEFINED #define LDAP_CLIENT_DEFINED #ifdef __cplusplus extern "C" { #endif #ifndef BASETYPES #include #endif #if !defined(_WINLDAP_) #define WINLDAPAPI DECLSPEC_IMPORT #else #define WINLDAPAPI __declspec(dllexport) #endif #ifndef LDAPAPI #define LDAPAPI __cdecl #endif // // The #define LDAP_UNICODE controls if we map the undecorated calls to // their unicode counterparts or just leave them defined as the normal // single byte entry points. // // If you want to write a UNICODE enabled application, you'd normally // just have UNICODE defined and then we'll default to using all LDAP // Unicode calls. // #ifndef LDAP_UNICODE #ifdef UNICODE #define LDAP_UNICODE 1 #else #define LDAP_UNICODE 0 #endif #endif // // Global constants // #define LDAP_PORT 389 #define LDAP_SSL_PORT 636 // // We currently support going to either v2 or v3 servers, though the API // is only a V2 API. We'll add support for result sets, server side // sorting, extended operations, etc as soon as they stabilize. // #define LDAP_VERSION1 1 #define LDAP_VERSION2 2 #define LDAP_VERSION3 3 #define LDAP_VERSION LDAP_VERSION2 // // All tags are CCFTTTTT. // CC Tag Class 00 = universal // 01 = application wide // 10 = context specific // 11 = private use // // F Form 0 primitive // 1 constructed // // TTTTT Tag Number // // // LDAP v2 & v3 commands. // #define LDAP_BIND_CMD 0x60L // application + constructed #define LDAP_UNBIND_CMD 0x42L // application + primitive #define LDAP_SEARCH_CMD 0x63L // application + constructed #define LDAP_MODIFY_CMD 0x66L // application + constructed #define LDAP_ADD_CMD 0x68L // application + constructed #define LDAP_DELETE_CMD 0x4aL // application + primitive #define LDAP_MODRDN_CMD 0x6cL // application + constructed #define LDAP_COMPARE_CMD 0x6eL // application + constructed #define LDAP_ABANDON_CMD 0x50L // application + primitive #define LDAP_SESSION_CMD 0x71L // not in base LDAP protocol #define LDAP_EXTENDED_CMD 0x77L // application + constructed // // Responses/Results for LDAP v2 & v3 // #define LDAP_RES_BIND 0x61L // application + constructed #define LDAP_RES_SEARCH_ENTRY 0x64L // application + constructed #define LDAP_RES_SEARCH_RESULT 0x65L // application + constructed #define LDAP_RES_MODIFY 0x67L // application + constructed #define LDAP_RES_ADD 0x69L // application + constructed #define LDAP_RES_DELETE 0x6bL // application + constructed #define LDAP_RES_MODRDN 0x6dL // application + constructed #define LDAP_RES_COMPARE 0x6fL // application + constructed #define LDAP_RES_SESSION 0x72L // not in base LDAP protocol #define LDAP_RES_REFERRAL 0x73L // application + constructed #define LDAP_RES_EXTENDED 0x78L // application + constructed #define LDAP_RES_ANY (-1L) #define LDAP_INVALID_CMD 0xff #define LDAP_INVALID_RES 0xff // // We'll make the error codes compatible with reference implementation // typedef enum { LDAP_SUCCESS = 0x00, LDAP_OPERATIONS_ERROR = 0x01, LDAP_PROTOCOL_ERROR = 0x02, LDAP_TIMELIMIT_EXCEEDED = 0x03, LDAP_SIZELIMIT_EXCEEDED = 0x04, LDAP_COMPARE_FALSE = 0x05, LDAP_COMPARE_TRUE = 0x06, LDAP_AUTH_METHOD_NOT_SUPPORTED = 0x07, LDAP_STRONG_AUTH_REQUIRED = 0x08, LDAP_REFERRAL_V2 = 0x09, LDAP_PARTIAL_RESULTS = 0x09, LDAP_REFERRAL = 0x0a, LDAP_ADMIN_LIMIT_EXCEEDED = 0x0b, LDAP_UNAVAILABLE_CRIT_EXTENSION = 0x0c, LDAP_CONFIDENTIALITY_REQUIRED = 0x0d, LDAP_NO_SUCH_ATTRIBUTE = 0x10, LDAP_UNDEFINED_TYPE = 0x11, LDAP_INAPPROPRIATE_MATCHING = 0x12, LDAP_CONSTRAINT_VIOLATION = 0x13, LDAP_ATTRIBUTE_OR_VALUE_EXISTS = 0x14, LDAP_INVALID_SYNTAX = 0x15, LDAP_NO_SUCH_OBJECT = 0x20, LDAP_ALIAS_PROBLEM = 0x21, LDAP_INVALID_DN_SYNTAX = 0x22, LDAP_IS_LEAF = 0x23, LDAP_ALIAS_DEREF_PROBLEM = 0x24, LDAP_INAPPROPRIATE_AUTH = 0x30, LDAP_INVALID_CREDENTIALS = 0x31, LDAP_INSUFFICIENT_RIGHTS = 0x32, LDAP_BUSY = 0x33, LDAP_UNAVAILABLE = 0x34, LDAP_UNWILLING_TO_PERFORM = 0x35, LDAP_LOOP_DETECT = 0x36, LDAP_NAMING_VIOLATION = 0x40, LDAP_OBJECT_CLASS_VIOLATION = 0x41, LDAP_NOT_ALLOWED_ON_NONLEAF = 0x42, LDAP_NOT_ALLOWED_ON_RDN = 0x43, LDAP_ALREADY_EXISTS = 0x44, LDAP_NO_OBJECT_CLASS_MODS = 0x45, LDAP_RESULTS_TOO_LARGE = 0x46, LDAP_AFFECTS_MULTIPLE_DSAS = 0x47, LDAP_OTHER = 0x50, LDAP_SERVER_DOWN = 0x51, LDAP_LOCAL_ERROR = 0x52, LDAP_ENCODING_ERROR = 0x53, LDAP_DECODING_ERROR = 0x54, LDAP_TIMEOUT = 0x55, LDAP_AUTH_UNKNOWN = 0x56, LDAP_FILTER_ERROR = 0x57, LDAP_USER_CANCELLED = 0x58, LDAP_PARAM_ERROR = 0x59, LDAP_NO_MEMORY = 0x5a, LDAP_CONNECT_ERROR = 0x5b, LDAP_NOT_SUPPORTED = 0x5c, LDAP_NO_RESULTS_RETURNED = 0x5e, LDAP_CONTROL_NOT_FOUND = 0x5d, LDAP_MORE_RESULTS_TO_RETURN = 0x5f, LDAP_CLIENT_LOOP = 0x60, LDAP_REFERRAL_LIMIT_EXCEEDED = 0x61 } LDAP_RETCODE; // // Bind methods. We support the following methods : // // Simple Clear text password... try not to use as it's not secure. // // MSN MSN (Microsoft Network) authentication. This package // may bring up UI to prompt the user for MSN credentials. // // DPA Normandy authentication... new MSN authentication. Same // usage as MSN. // // NTLM NT domain authentication. Use NULL credentials and // we'll try to use default logged in user credentials. // // Sicily Negotiate with the server for any of: MSN, DPA, NTLM // Should be used for LDAPv2 servers only. // // Negotiate Use GSSAPI Negotiate package to negotiate security // package of either Kerberos v5 or NTLM (or any other // package the client and server negotiate). Pass in // NULL credentials to specify default logged in user. // If Negotiate package is not installed on server or // client, this will fall back to Sicily negotiation. // // For all bind methods except for Simple, you may pass in a // SEC_WINNT_AUTH_IDENTITY_W (defined in rpcdce.h) to specify alternate // credentials. // // All bind methods other than simple are synchronous only calls. // Calling the asynchronous bind call for any of these messages will // return LDAP_PARAM_ERROR. // // Using any other method besides simple will cause WLDAP32 to pull in // the SSPI security DLLs (SECURITY.DLL etc). // // On non-Simple methods, if you specify NULL credentials, we'll attempt to use // the default logged in user. // #define LDAP_AUTH_SIMPLE 0x80L #define LDAP_AUTH_SASL 0x83L // don't use... should go away #define LDAP_AUTH_OTHERKIND 0x86L // The SICILY type covers package negotiation to MSN servers. // Each of the supported types can also be specified without // doing the package negotiation, assuming the caller knows // what the server supports. #define LDAP_AUTH_SICILY (LDAP_AUTH_OTHERKIND | 0x0200) #define LDAP_AUTH_MSN (LDAP_AUTH_OTHERKIND | 0x0800) #define LDAP_AUTH_NTLM (LDAP_AUTH_OTHERKIND | 0x1000) #define LDAP_AUTH_DPA (LDAP_AUTH_OTHERKIND | 0x2000) // This will cause the client to use the GSSAPI negotiation // package to determine the most appropriate authentication type. // This type should be used when talking to NT5. #define LDAP_AUTH_NEGOTIATE (LDAP_AUTH_OTHERKIND | 0x0400) // backward compatible #define for older constant name. #define LDAP_AUTH_SSPI LDAP_AUTH_NEGOTIATE // // Client applications typically don't have to encode/decode LDAP filters, // but if they do, we define the operators here. // // Filter types. #define LDAP_FILTER_AND 0xa0 // context specific + constructed - SET OF Filters. #define LDAP_FILTER_OR 0xa1 // context specific + constructed - SET OF Filters. #define LDAP_FILTER_NOT 0xa2 // context specific + constructed - Filter #define LDAP_FILTER_EQUALITY 0xa3 // context specific + constructed - AttributeValueAssertion. #define LDAP_FILTER_SUBSTRINGS 0xa4 // context specific + constructed - SubstringFilter #define LDAP_FILTER_GE 0xa5 // context specific + constructed - AttributeValueAssertion. #define LDAP_FILTER_LE 0xa6 // context specific + constructed - AttributeValueAssertion. #define LDAP_FILTER_PRESENT 0x87 // context specific + primitive - AttributeType. #define LDAP_FILTER_APPROX 0xa8 // context specific + constructed - AttributeValueAssertion. // Substring filter types #define LDAP_SUBSTRING_INITIAL 0x80L // class context specific #define LDAP_SUBSTRING_ANY 0x81L // class context specific #define LDAP_SUBSTRING_FINAL 0x82L // class context specific // // Possible values for ld_deref field. // "Never" - never deref aliases. return only the alias. // "Searching" - only deref aliases when searching, not when locating // the base object of a search. // "Finding" - dereference the alias when locating the base object but // not during a search. // "Always" - always dereference aliases. // #define LDAP_DEREF_NEVER 0 #define LDAP_DEREF_SEARCHING 1 #define LDAP_DEREF_FINDING 2 #define LDAP_DEREF_ALWAYS 3 // Special values for ld_sizelimit : #define LDAP_NO_LIMIT 0 // Flags for ld_options field : #define LDAP_OPT_DNS 0x00000001 // utilize DN & DNS #define LDAP_OPT_CHASE_REFERRALS 0x00000002 // chase referrals #define LDAP_OPT_RETURN_REFS 0x00000004 // return referrals to calling app // // LDAP structure per connection // #pragma pack(push, 4) typedef struct ldap { struct { ULONG sb_sd; UCHAR Reserved1[(10*sizeof(ULONG))+1]; ULONG sb_naddr; // notzero implies CLDAP available UCHAR Reserved2[(6*sizeof(ULONG))]; } ld_sb; // // Following parameters MAY match up to reference implementation of LDAP // PCHAR ld_host; ULONG ld_version; UCHAR ld_lberoptions; // // Safe to assume that these parameters are in same location as // reference implementation of LDAP API. // ULONG ld_deref; ULONG ld_timelimit; ULONG ld_sizelimit; ULONG ld_errno; PCHAR ld_matched; PCHAR ld_error; ULONG ld_msgid; UCHAR Reserved3[(6*sizeof(ULONG))+1]; // // Following parameters may match up to reference implementation of LDAP API. // ULONG ld_cldaptries; ULONG ld_cldaptimeout; ULONG ld_refhoplimit; ULONG ld_options; } LDAP, * PLDAP; // // Our timeval structure is a bit different from the reference implementation // since Win32 defines a _timeval structure that is different from the LDAP // one. // typedef struct l_timeval { LONG tv_sec; LONG tv_usec; } LDAP_TIMEVAL, * PLDAP_TIMEVAL; // // The berval structure is used to pass in any arbitrary octet string. It // is useful for attributes that cannot be represented using a null // terminated string. // typedef struct berval { ULONG bv_len; PCHAR bv_val; } LDAP_BERVAL, * PLDAP_BERVAL; // // The following structure has to be compatible with reference implementation. // typedef struct ldapmsg { ULONG lm_msgid; // message number for given connection ULONG lm_msgtype; // message type of the form LDAP_RES_xxx PVOID lm_ber; // ber form of message struct ldapmsg *lm_chain; // pointer to next result value struct ldapmsg *lm_next; // pointer to next message ULONG lm_time; // // new fields below not in reference implementation // PLDAP Connection; // connection from which we received response PVOID Request; // owning request (opaque structure) ULONG lm_returncode; // server's return code USHORT lm_referral; // index of referral within ref table BOOLEAN lm_chased; // has referral been chased already? BOOLEAN lm_eom; // is this the last entry for this message? } LDAPMessage, *PLDAPMessage; // // Controls... there are three types : // // 1) those passed to the server // 2) those passed to the client and handled by the client API // 3) those returned by the server // typedef struct ldapcontrolA { PCHAR ldctl_oid; struct berval ldctl_value; BOOLEAN ldctl_iscritical; } LDAPControlA, *PLDAPControlA; typedef struct ldapcontrolW { PWCHAR ldctl_oid; struct berval ldctl_value; BOOLEAN ldctl_iscritical; } LDAPControlW, *PLDAPControlW; #if LDAP_UNICODE #define LDAPControl LDAPControlW #define PLDAPControl PLDAPControlW #else #define LDAPControl LDAPControlA #define PLDAPControl PLDAPControlA #endif // // Client controls section : these are the client controls that wldap32.dll // supports. // // If you specify LDAP_CONTROL_REFERRALS in a control, the value field should // point to a ULONG of the following flags : // // LDAP_CHASE_SUBORDINATE_REFERRALS // LDAP_CHASE_EXTERNAL_REFERRALS // #define LDAP_CONTROL_REFERRALS_W L"1.2.840.113556.1.4.616" #define LDAP_CONTROL_REFERRALS "1.2.840.113556.1.4.616" // // Values required for Modification command These are options for the // mod_op field of LDAPMod structure // #define LDAP_MOD_ADD 0x00 #define LDAP_MOD_DELETE 0x01 #define LDAP_MOD_REPLACE 0x02 #define LDAP_MOD_BVALUES 0x80 // AND in this flag if berval structure used typedef struct ldapmodW { ULONG mod_op; PWCHAR mod_type; union { PWCHAR *modv_strvals; struct berval **modv_bvals; } mod_vals; } LDAPModW, *PLDAPModW; typedef struct ldapmodA { ULONG mod_op; PCHAR mod_type; union { PCHAR *modv_strvals; struct berval **modv_bvals; } mod_vals; } LDAPModA, *PLDAPModA; #if LDAP_UNICODE #define LDAPMod LDAPModW #define PLDAPMod PLDAPModW #else #define LDAPMod LDAPModA #define PLDAPMod PLDAPModA #endif #pragma pack(pop) // // macros compatible with reference implementation... // #define LDAP_IS_CLDAP( ld ) ( (ld)->ld_sb.sb_naddr > 0 ) #define mod_values mod_vals.modv_strvals #define mod_bvalues mod_vals.modv_bvals #define NAME_ERROR(n) ((n & 0xf0) == 0x20) // // function definitions for LDAP API // // // Create a connection block to an LDAP server. HostName can be NULL, in // which case we'll try to go off and find the "default" LDAP server. // // Note that if we have to go off and find the default server, we'll pull // in NETAPI32.DLL and ADVAPI32.DLL. // // If it returns NULL, an error occurred. Pick up error code with // GetLastError(). // // ldap_open actually opens the connection at the time of the call, // whereas ldap_init only opens the connection when an operation is performed // that requires it. // // multi-thread: ldap_open*, ldap_init*, and ldap_sslinit* calls are safe. // WINLDAPAPI LDAP * LDAPAPI ldap_openW( PWCHAR HostName, ULONG PortNumber ); WINLDAPAPI LDAP * LDAPAPI ldap_openA( PCHAR HostName, ULONG PortNumber ); WINLDAPAPI LDAP * LDAPAPI ldap_initW( PWCHAR HostName, ULONG PortNumber ); WINLDAPAPI LDAP * LDAPAPI ldap_initA( PCHAR HostName, ULONG PortNumber ); WINLDAPAPI LDAP * LDAPAPI ldap_sslinitW( PWCHAR HostName, ULONG PortNumber, int secure ); WINLDAPAPI LDAP * LDAPAPI ldap_sslinitA( PCHAR HostName, ULONG PortNumber, int secure ); // // when calling ldap_init, you can call ldap_connect explicitly to have the // library contact the server. This is useful for checking for server // availability. This call is not required however, since the other functions // will call it internally if it hasn't already been called. // WINLDAPAPI ULONG LDAPAPI ldap_connect( LDAP *ld, struct l_timeval *timeout ); #if LDAP_UNICODE #define ldap_open ldap_openW #define ldap_init ldap_initW #define ldap_sslinit ldap_sslinitW #else WINLDAPAPI LDAP * LDAPAPI ldap_open( PCHAR HostName, ULONG PortNumber ); WINLDAPAPI LDAP * LDAPAPI ldap_init( PCHAR HostName, ULONG PortNumber ); WINLDAPAPI LDAP * LDAPAPI ldap_sslinit( PCHAR HostName, ULONG PortNumber, int secure ); #endif // // This is similar to ldap_open except it creates a connection block for // UDP based Connectionless LDAP services. No TCP session is maintained. // // If it returns NULL, an error occurred. Pick up error code with // GetLastError(). // // multi-thread: cldap_open* calls are safe. // WINLDAPAPI LDAP * LDAPAPI cldap_openW( PWCHAR HostName, ULONG PortNumber ); WINLDAPAPI LDAP * LDAPAPI cldap_openA( PCHAR HostName, ULONG PortNumber ); #if LDAP_UNICODE #define cldap_open cldap_openW #else WINLDAPAPI LDAP * LDAPAPI cldap_open( PCHAR HostName, ULONG PortNumber ); #endif // // Call unbind when you're done with the connection, it will free all // resources associated with the connection. // // There is no ldap_close... use ldap_unbind even if you haven't called // ldap_bind on the connection. // // multi-thread: ldap_unbind* calls are safe EXCEPT don't use the LDAP * // stucture after it's been freed. // WINLDAPAPI ULONG LDAPAPI ldap_unbind( LDAP *ld ); WINLDAPAPI ULONG LDAPAPI ldap_unbind_s( LDAP *ld ); // calls ldap_unbind // // Calls to get and set options on connection blocks... use them rather // than modifying the LDAP block directly. // // // multi-thread: ldap_get_option is safe // multi-thread: ldap_set_option is not safe in that it affects the // connection as a whole. beware if threads share connections. WINLDAPAPI ULONG LDAPAPI ldap_get_option( LDAP *ld, int option, void *outvalue ); WINLDAPAPI ULONG LDAPAPI ldap_set_option( LDAP *ld, int option, void *invalue ); // // These are the values to pass to ldap_get/set_option : // #define LDAP_OPT_DESC 0x01 #define LDAP_OPT_DEREF 0x02 #define LDAP_OPT_SIZELIMIT 0x03 #define LDAP_OPT_TIMELIMIT 0x04 #define LDAP_OPT_THREAD_FN_PTRS 0x05 #define LDAP_OPT_REBIND_FN 0x06 #define LDAP_OPT_REBIND_ARG 0x07 #define LDAP_OPT_REFERRALS 0x08 #define LDAP_OPT_RESTART 0x09 #define LDAP_OPT_SSL 0x0a #define LDAP_OPT_IO_FN_PTRS 0x0b #define LDAP_OPT_CACHE_FN_PTRS 0x0d #define LDAP_OPT_CACHE_STRATEGY 0x0e #define LDAP_OPT_CACHE_ENABLE 0x0f #define LDAP_OPT_REFERRAL_HOP_LIMIT 0x10 #define LDAP_OPT_PROTOCOL_VERSION 0x11 // known by two names. #define LDAP_OPT_VERSION 0x11 // // These are new ones that we've defined, not in current RFC draft. // #define LDAP_OPT_HOST_NAME 0x30 #define LDAP_OPT_ERROR_NUMBER 0x31 #define LDAP_OPT_ERROR_STRING 0x32 #define LDAP_OPT_HOST_REACHABLE 0x3E // // These options control the keep-alive logic. Keep alives are sent as // ICMP ping messages (which currently don't go through firewalls). // // There are three values that control how this works : // PING_KEEP_ALIVE : min number of seconds since we last received a response // from the server before we send a keep-alive ping // PING_WAIT_TIME : number of milliseconds we wait for the response to // come back when we send a ping // PING_LIMIT : number of unanswered pings we send before we close the // connection. // // To disable the keep-alive logic, set any of the values (PING_KEEP_ALIVE, // PING_LIMIT, or PING_WAIT_TIME) to zero. // // The current default/min/max for these values are as follows : // // PING_KEEP_ALIVE : 120/5/maxInt seconds (may also be zero) // PING_WAIT_TIME : 2000/10/60000 milliseconds (may also be zero) // PING_LIMIT : 4/0/maxInt // #define LDAP_OPT_PING_KEEP_ALIVE 0x36 #define LDAP_OPT_PING_WAIT_TIME 0x37 #define LDAP_OPT_PING_LIMIT 0x38 // // These won't be in the RFC. Only use these if you're going to be dependent // on our implementation. // #define LDAP_OPT_DNSDOMAIN_NAME 0x3B // return DNS name of domain #define LDAP_OPT_GETDSNAME_FLAGS 0x3D // flags for DsGetDcName #define LDAP_OPT_PROMPT_CREDENTIALS 0x3F // prompt for creds? currently // only for DPA & NTLM if no creds // are loaded // // End of Microsoft only options // #define LDAP_OPT_ON ((void *) 1) #define LDAP_OPT_OFF ((void *) 0) // // For chasing referrals, we extend this a bit for LDAP_OPT_REFERRALS. If // the value is not LDAP_OPT_ON or LDAP_OPT_OFF, we'll treat them as the // following : // // LDAP_CHASE_SUBORDINATE_REFERRALS : chase subordinate referrals (or // references) returned in a v3 search // LDAP_CHASE_EXTERNAL_REFERRALS : chase external referrals. These are // returned possibly on any operation except bind. // // If you OR these flags together, it's equivalent to setting referrals to // LDAP_OPT_ON. // #define LDAP_CHASE_SUBORDINATE_REFERRALS 0x00000020 #define LDAP_CHASE_EXTERNAL_REFERRALS 0x00000040 // // Bind is required as the first operation to v2 servers, not so for v3 // servers. See above description of authentication methods. // // multi-thread: bind calls are not safe in that it affects the // connection as a whole. beware if threads share connections // and try to mulithread binds with other operations. WINLDAPAPI ULONG LDAPAPI ldap_simple_bindW( LDAP *ld, PWCHAR dn, PWCHAR passwd ); WINLDAPAPI ULONG LDAPAPI ldap_simple_bindA( LDAP *ld, PCHAR dn, PCHAR passwd ); WINLDAPAPI ULONG LDAPAPI ldap_simple_bind_sW( LDAP *ld, PWCHAR dn, PWCHAR passwd ); WINLDAPAPI ULONG LDAPAPI ldap_simple_bind_sA( LDAP *ld, PCHAR dn, PCHAR passwd ); WINLDAPAPI ULONG LDAPAPI ldap_bindW( LDAP *ld, PWCHAR dn, PWCHAR cred, ULONG method ); WINLDAPAPI ULONG LDAPAPI ldap_bindA( LDAP *ld, PCHAR dn, PCHAR cred, ULONG method ); WINLDAPAPI ULONG LDAPAPI ldap_bind_sW( LDAP *ld, PWCHAR dn, PWCHAR cred, ULONG method ); WINLDAPAPI ULONG LDAPAPI ldap_bind_sA( LDAP *ld, PCHAR dn, PCHAR cred, ULONG method ); #if 0 // // Pending discussions with the IETF... we won't implement the extended // form of bind until we determine what the API will look like. // WINLDAPAPI ULONG LDAPAPI ldap_bind_extW( LDAP *ld, PWCHAR dn, PWCHAR cred, ULONG method, PLDAPControlW *ServerControls, PLDAPControlW *ClientControls, ULONG TimeLimit, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_bind_extA( LDAP *ld, PCHAR dn, PCHAR cred, ULONG method, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG TimeLimit, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_bind_ext_sW( LDAP *ld, PWCHAR dn, PWCHAR cred, ULONG method, PLDAPControlW *ServerControls, PLDAPControlW *ClientControls, ULONG TimeLimit ); WINLDAPAPI ULONG LDAPAPI ldap_bind_ext_sA( LDAP *ld, PCHAR dn, PCHAR cred, ULONG method, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG TimeLimit ); #endif #if LDAP_UNICODE #define ldap_simple_bind ldap_simple_bindW #define ldap_simple_bind_s ldap_simple_bind_sW #define ldap_bind ldap_bindW #define ldap_bind_s ldap_bind_sW #if 0 #define ldap_bind_ext ldap_bind_extW #define ldap_bind_ext_s ldap_bind_ext_sW #endif #else WINLDAPAPI ULONG LDAPAPI ldap_simple_bind( LDAP *ld, PCHAR dn, PCHAR passwd ); WINLDAPAPI ULONG LDAPAPI ldap_simple_bind_s( LDAP *ld, PCHAR dn, PCHAR passwd ); WINLDAPAPI ULONG LDAPAPI ldap_bind( LDAP *ld, PCHAR dn, PCHAR cred, ULONG method ); WINLDAPAPI ULONG LDAPAPI ldap_bind_s( LDAP *ld, PCHAR dn, PCHAR cred, ULONG method ); #if 0 WINLDAPAPI ULONG LDAPAPI ldap_bind_ext( LDAP *ld, PCHAR dn, PCHAR cred, ULONG method, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG TimeLimit, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_bind_ext_s( LDAP *ld, PCHAR dn, PCHAR cred, ULONG method, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG TimeLimit ); #endif #endif // // Synchronous and asynch search routines. // // filter follows RFC 1960 with the addition that '(' ')' '*' ' ' '\' and // '\0' are all escaped with '\' // // Scope of search. This corresponds to the "scope" parameter on search #define LDAP_SCOPE_BASE 0x00 #define LDAP_SCOPE_ONELEVEL 0x01 #define LDAP_SCOPE_SUBTREE 0x02 // // multi-thread: ldap_search calls are not safe in that the message number // is returned rather than the return code. You have to look // at the connection block in an error case and the return code // may be overwritten by another thread inbetween. // // Use ldap_search_ext instead, as these are thread safe. // // ldap_search_s and ldap_search_ext* calls are thread safe. // WINLDAPAPI ULONG LDAPAPI ldap_searchW( LDAP *ld, PWCHAR base, // distinguished name or "" ULONG scope, // LDAP_SCOPE_xxxx PWCHAR filter, PWCHAR attrs[], // pointer to an array of PCHAR attribute names ULONG attrsonly // boolean on whether to only return attr names ); WINLDAPAPI ULONG LDAPAPI ldap_searchA( LDAP *ld, PCHAR base, // distinguished name or "" ULONG scope, // LDAP_SCOPE_xxxx PCHAR filter, PCHAR attrs[], // pointer to an array of PCHAR attribute names ULONG attrsonly // boolean on whether to only return attr names ); WINLDAPAPI ULONG LDAPAPI ldap_search_sW( LDAP *ld, PWCHAR base, ULONG scope, PWCHAR filter, PWCHAR attrs[], ULONG attrsonly, LDAPMessage **res ); WINLDAPAPI ULONG LDAPAPI ldap_search_sA( LDAP *ld, PCHAR base, ULONG scope, PCHAR filter, PCHAR attrs[], ULONG attrsonly, LDAPMessage **res ); WINLDAPAPI ULONG LDAPAPI ldap_search_stW( LDAP *ld, PWCHAR base, ULONG scope, PWCHAR filter, PWCHAR attrs[], ULONG attrsonly, struct l_timeval *timeout, LDAPMessage **res ); WINLDAPAPI ULONG LDAPAPI ldap_search_stA( LDAP *ld, PCHAR base, ULONG scope, PCHAR filter, PCHAR attrs[], ULONG attrsonly, struct l_timeval *timeout, LDAPMessage **res ); WINLDAPAPI ULONG LDAPAPI ldap_search_extW( LDAP *ld, PWCHAR base, ULONG scope, PWCHAR filter, PWCHAR attrs[], ULONG attrsonly, PLDAPControlW *ServerControls, PLDAPControlW *ClientControls, ULONG TimeLimit, ULONG SizeLimit, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_search_extA( LDAP *ld, PCHAR base, ULONG scope, PCHAR filter, PCHAR attrs[], ULONG attrsonly, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG TimeLimit, ULONG SizeLimit, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_search_ext_sW( LDAP *ld, PWCHAR base, ULONG scope, PWCHAR filter, PWCHAR attrs[], ULONG attrsonly, PLDAPControlW *ServerControls, PLDAPControlW *ClientControls, struct l_timeval *timeout, ULONG SizeLimit, LDAPMessage **res ); WINLDAPAPI ULONG LDAPAPI ldap_search_ext_sA( LDAP *ld, PCHAR base, ULONG scope, PCHAR filter, PCHAR attrs[], ULONG attrsonly, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, struct l_timeval *timeout, ULONG SizeLimit, LDAPMessage **res ); #if LDAP_UNICODE #define ldap_search ldap_searchW #define ldap_search_s ldap_search_sW #define ldap_search_st ldap_search_stW #define ldap_search_ext ldap_search_extW #define ldap_search_ext_s ldap_search_ext_sW #else WINLDAPAPI ULONG LDAPAPI ldap_search( LDAP *ld, PCHAR base, // distinguished name or "" ULONG scope, // LDAP_SCOPE_xxxx PCHAR filter, PCHAR attrs[], // pointer to an array of PCHAR attribute names ULONG attrsonly // boolean on whether to only return attr names ); WINLDAPAPI ULONG LDAPAPI ldap_search_s( LDAP *ld, PCHAR base, ULONG scope, PCHAR filter, PCHAR attrs[], ULONG attrsonly, LDAPMessage **res ); WINLDAPAPI ULONG LDAPAPI ldap_search_st( LDAP *ld, PCHAR base, ULONG scope, PCHAR filter, PCHAR attrs[], ULONG attrsonly, struct l_timeval *timeout, LDAPMessage **res ); WINLDAPAPI ULONG LDAPAPI ldap_search_ext( LDAP *ld, PCHAR base, ULONG scope, PCHAR filter, PCHAR attrs[], ULONG attrsonly, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG TimeLimit, ULONG SizeLimit, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_search_ext_s( LDAP *ld, PCHAR base, ULONG scope, PCHAR filter, PCHAR attrs[], ULONG attrsonly, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, struct l_timeval *timeout, ULONG SizeLimit, LDAPMessage **res ); #endif // // modify an existing entry // // // multi-thread: ldap_modify calls are not safe in that the message number // is returned rather than the return code. You have to look // at the connection block in an error case and the return code // may be overwritten by another thread inbetween. // // Use ldap_modify_ext instead, as these are thread safe. // // ldap_modify_s and ldap_modify_ext* calls are thread safe. // WINLDAPAPI ULONG LDAPAPI ldap_modifyW( LDAP *ld, PWCHAR dn, LDAPModW *mods[] ); WINLDAPAPI ULONG LDAPAPI ldap_modifyA( LDAP *ld, PCHAR dn, LDAPModA *mods[] ); WINLDAPAPI ULONG LDAPAPI ldap_modify_sW( LDAP *ld, PWCHAR dn, LDAPModW *mods[] ); WINLDAPAPI ULONG LDAPAPI ldap_modify_sA( LDAP *ld, PCHAR dn, LDAPModA *mods[] ); WINLDAPAPI ULONG LDAPAPI ldap_modify_extW( LDAP *ld, PWCHAR dn, LDAPModW *mods[], PLDAPControlW *ServerControls, PLDAPControlW *ClientControls, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_modify_extA( LDAP *ld, PCHAR dn, LDAPModA *mods[], PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_modify_ext_sW( LDAP *ld, PWCHAR dn, LDAPModW *mods[], PLDAPControlW *ServerControls, PLDAPControlW *ClientControls ); WINLDAPAPI ULONG LDAPAPI ldap_modify_ext_sA( LDAP *ld, PCHAR dn, LDAPModA *mods[], PLDAPControlA *ServerControls, PLDAPControlA *ClientControls ); #if LDAP_UNICODE #define ldap_modify ldap_modifyW #define ldap_modify_s ldap_modify_sW #define ldap_modify_ext ldap_modify_extW #define ldap_modify_ext_s ldap_modify_ext_sW #else WINLDAPAPI ULONG LDAPAPI ldap_modify( LDAP *ld, PCHAR dn, LDAPModA *mods[] ); WINLDAPAPI ULONG LDAPAPI ldap_modify_s( LDAP *ld, PCHAR dn, LDAPModA *mods[] ); WINLDAPAPI ULONG LDAPAPI ldap_modify_ext( LDAP *ld, PCHAR dn, LDAPModA *mods[], PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_modify_ext_s( LDAP *ld, PCHAR dn, LDAPModA *mods[], PLDAPControlA *ServerControls, PLDAPControlA *ClientControls ); #endif // // modrdn and modrdn2 function both as RenameObject and MoveObject. // // Note that to LDAP v2 servers, only rename within a given container // is supported... therefore NewDistinguishedName is actually NewRDN. // Here are some examples : // // This works to both v2 and v3 servers : // // DN = CN=Bob,OU=FOO,O=BAR // NewDN = CN=Joe // // result is: CN=Joe,OU=FOO,O=BAR // // This works to only v3 and above servers : // // DN = CN=Bob,OU=FOO,O=BAR // NewDN = CN=Joe,OU=FOOBAR,O=BAR // // result is: CN=Joe,OU=FOOBAR,O=BAR // // If you try the second example to a v2 server, we'll send the whole // NewDN over as the new RDN (rather than break up the parent OU and // child). The server will then give you back some unknown error. // // // multi-thread: ldap_modrdn and ldap_modrdn2 calls are not safe in that // the message number is returned rather than the return code. // You have to look at the connection block in an error case // and the return code may be overwritten by another thread // inbetween. // // Use ldap_rename_ext instead, as these are thread safe. // WINLDAPAPI ULONG LDAPAPI ldap_modrdn2W ( LDAP *ExternalHandle, PWCHAR DistinguishedName, PWCHAR NewDistinguishedName, INT DeleteOldRdn ); WINLDAPAPI ULONG LDAPAPI ldap_modrdn2A ( LDAP *ExternalHandle, PCHAR DistinguishedName, PCHAR NewDistinguishedName, INT DeleteOldRdn ); // // ldap_modrdn simply calls ldap_modrdn2 with a value of 1 for DeleteOldRdn. // WINLDAPAPI ULONG LDAPAPI ldap_modrdnW ( LDAP *ExternalHandle, PWCHAR DistinguishedName, PWCHAR NewDistinguishedName ); WINLDAPAPI ULONG LDAPAPI ldap_modrdnA ( LDAP *ExternalHandle, PCHAR DistinguishedName, PCHAR NewDistinguishedName ); WINLDAPAPI ULONG LDAPAPI ldap_modrdn2_sW ( LDAP *ExternalHandle, PWCHAR DistinguishedName, PWCHAR NewDistinguishedName, INT DeleteOldRdn ); WINLDAPAPI ULONG LDAPAPI ldap_modrdn2_sA ( LDAP *ExternalHandle, PCHAR DistinguishedName, PCHAR NewDistinguishedName, INT DeleteOldRdn ); WINLDAPAPI ULONG LDAPAPI ldap_modrdn_sW ( LDAP *ExternalHandle, PWCHAR DistinguishedName, PWCHAR NewDistinguishedName ); WINLDAPAPI ULONG LDAPAPI ldap_modrdn_sA ( LDAP *ExternalHandle, PCHAR DistinguishedName, PCHAR NewDistinguishedName ); #if LDAP_UNICODE #define ldap_modrdn2 ldap_modrdn2W #define ldap_modrdn ldap_modrdnW #define ldap_modrdn2_s ldap_modrdn2_sW #define ldap_modrdn_s ldap_modrdn_sW #else WINLDAPAPI ULONG LDAPAPI ldap_modrdn2 ( LDAP *ExternalHandle, PCHAR DistinguishedName, PCHAR NewDistinguishedName, INT DeleteOldRdn ); WINLDAPAPI ULONG LDAPAPI ldap_modrdn ( LDAP *ExternalHandle, PCHAR DistinguishedName, PCHAR NewDistinguishedName ); WINLDAPAPI ULONG LDAPAPI ldap_modrdn2_s ( LDAP *ExternalHandle, PCHAR DistinguishedName, PCHAR NewDistinguishedName, INT DeleteOldRdn ); WINLDAPAPI ULONG LDAPAPI ldap_modrdn_s ( LDAP *ExternalHandle, PCHAR DistinguishedName, PCHAR NewDistinguishedName ); #endif // // Extended Rename operations. These take controls and separate out the // parent from the RDN, for clarity. // WINLDAPAPI ULONG LDAPAPI ldap_rename_extW( LDAP *ld, PWCHAR dn, PWCHAR NewRDN, PWCHAR NewParent, INT DeleteOldRdn, PLDAPControlW *ServerControls, PLDAPControlW *ClientControls, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_rename_extA( LDAP *ld, PCHAR dn, PCHAR NewRDN, PCHAR NewParent, INT DeleteOldRdn, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_rename_ext_sW( LDAP *ld, PWCHAR dn, PWCHAR NewRDN, PWCHAR NewParent, INT DeleteOldRdn, PLDAPControlW *ServerControls, PLDAPControlW *ClientControls ); WINLDAPAPI ULONG LDAPAPI ldap_rename_ext_sA( LDAP *ld, PCHAR dn, PCHAR NewRDN, PCHAR NewParent, INT DeleteOldRdn, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls ); #if LDAP_UNICODE #define ldap_rename_ext ldap_rename_extW #define ldap_rename_ext_s ldap_rename_ext_sW #else WINLDAPAPI ULONG LDAPAPI ldap_rename_ext( LDAP *ld, PCHAR dn, PCHAR NewRDN, PCHAR NewParent, INT DeleteOldRdn, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_rename_ext_s( LDAP *ld, PCHAR dn, PCHAR NewRDN, PCHAR NewParent, INT DeleteOldRdn, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls ); #endif // // Add an entry to the tree // // // multi-thread: ldap_add calls are not safe in that the message number // is returned rather than the return code. You have to look // at the connection block in an error case and the return code // may be overwritten by another thread inbetween. // // Use ldap_add_ext instead, as these are thread safe. // // ldap_add_s and ldap_add_ext* calls are thread safe. // WINLDAPAPI ULONG LDAPAPI ldap_addW( LDAP *ld, PWCHAR dn, LDAPModW *attrs[] ); WINLDAPAPI ULONG LDAPAPI ldap_addA( LDAP *ld, PCHAR dn, LDAPModA *attrs[] ); WINLDAPAPI ULONG LDAPAPI ldap_add_sW( LDAP *ld, PWCHAR dn, LDAPModW *attrs[] ); WINLDAPAPI ULONG LDAPAPI ldap_add_sA( LDAP *ld, PCHAR dn, LDAPModA *attrs[] ); WINLDAPAPI ULONG LDAPAPI ldap_add_extW( LDAP *ld, PWCHAR dn, LDAPModW *attrs[], PLDAPControlW *ServerControls, PLDAPControlW *ClientControls, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_add_extA( LDAP *ld, PCHAR dn, LDAPModA *attrs[], PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_add_ext_sW( LDAP *ld, PWCHAR dn, LDAPModW *attrs[], PLDAPControlW *ServerControls, PLDAPControlW *ClientControls ); WINLDAPAPI ULONG LDAPAPI ldap_add_ext_sA( LDAP *ld, PCHAR dn, LDAPModA *attrs[], PLDAPControlA *ServerControls, PLDAPControlA *ClientControls ); #if LDAP_UNICODE #define ldap_add ldap_addW #define ldap_add_s ldap_add_sW #define ldap_add_ext ldap_add_extW #define ldap_add_ext_s ldap_add_ext_sW #else WINLDAPAPI ULONG LDAPAPI ldap_add( LDAP *ld, PCHAR dn, LDAPMod *attrs[] ); WINLDAPAPI ULONG LDAPAPI ldap_add_s( LDAP *ld, PCHAR dn, LDAPMod *attrs[] ); WINLDAPAPI ULONG LDAPAPI ldap_add_ext( LDAP *ld, PCHAR dn, LDAPModA *attrs[], PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_add_ext_s( LDAP *ld, PCHAR dn, LDAPModA *attrs[], PLDAPControlA *ServerControls, PLDAPControlA *ClientControls ); #endif // // Compare the attribute for a given entry to a known value. // // // multi-thread: ldap_compare calls are not safe in that the message number // is returned rather than the return code. You have to look // at the connection block in an error case and the return code // may be overwritten by another thread inbetween. // // Use ldap_compare_ext instead, as these are thread safe. // // ldap_compare_s and ldap_compare_ext* calls are thread safe. // WINLDAPAPI ULONG LDAPAPI ldap_compareW( LDAP *ld, PWCHAR dn, PWCHAR attr, PWCHAR value ); WINLDAPAPI ULONG LDAPAPI ldap_compareA( LDAP *ld, PCHAR dn, PCHAR attr, PCHAR value ); WINLDAPAPI ULONG LDAPAPI ldap_compare_sW( LDAP *ld, PWCHAR dn, PWCHAR attr, PWCHAR value ); WINLDAPAPI ULONG LDAPAPI ldap_compare_sA( LDAP *ld, PCHAR dn, PCHAR attr, PCHAR value ); #if LDAP_UNICODE #define ldap_compare ldap_compareW #define ldap_compare_s ldap_compare_sW #else WINLDAPAPI ULONG LDAPAPI ldap_compare( LDAP *ld, PCHAR dn, PCHAR attr, PCHAR value ); WINLDAPAPI ULONG LDAPAPI ldap_compare_s( LDAP *ld, PCHAR dn, PCHAR attr, PCHAR value ); #endif // // Extended Compare operations. These take controls and are thread safe. // They also allow you to specify a bval structure for the data, so that it // isn't translated from Unicode or ANSI to UTF8. Allows for comparison of // raw binary data. // // Specify either Data or Value as not NULL. If both are not NULL, the // berval Data will be used. // WINLDAPAPI ULONG LDAPAPI ldap_compare_extW( LDAP *ld, PWCHAR dn, PWCHAR Attr, PWCHAR Value, // either value or Data is not null, not both struct berval *Data, PLDAPControlW *ServerControls, PLDAPControlW *ClientControls, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_compare_extA( LDAP *ld, PCHAR dn, PCHAR Attr, PCHAR Value, // either value or Data is not null, not both struct berval *Data, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_compare_ext_sW( LDAP *ld, PWCHAR dn, PWCHAR Attr, PWCHAR Value, // either value or Data is not null, not both struct berval *Data, PLDAPControlW *ServerControls, PLDAPControlW *ClientControls ); WINLDAPAPI ULONG LDAPAPI ldap_compare_ext_sA( LDAP *ld, PCHAR dn, PCHAR Attr, PCHAR Value, // either value or Data is not null, not both struct berval *Data, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls ); #if LDAP_UNICODE #define ldap_compare_ext ldap_compare_extW #define ldap_compare_ext_s ldap_compare_ext_sW #else WINLDAPAPI ULONG LDAPAPI ldap_compare_ext( LDAP *ld, PCHAR dn, PCHAR Attr, PCHAR Value, // either value or Data is not null, not both struct berval *Data, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_compare_ext_s( LDAP *ld, PCHAR dn, PCHAR Attr, PCHAR Value, // either value or Data is not null, not both struct berval *Data, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls ); #endif // // Delete an object out of the tree // // // multi-thread: ldap_delete calls are not safe in that the message number // is returned rather than the return code. You have to look // at the connection block in an error case and the return code // may be overwritten by another thread inbetween. // // Use ldap_delete_ext instead, as these are thread safe. // // ldap_delete_s and ldap_delete_ext* calls are thread safe. // WINLDAPAPI ULONG LDAPAPI ldap_deleteW( LDAP *ld, PWCHAR dn ); WINLDAPAPI ULONG LDAPAPI ldap_deleteA( LDAP *ld, PCHAR dn ); WINLDAPAPI ULONG LDAPAPI ldap_delete_sW( LDAP *ld, PWCHAR dn ); WINLDAPAPI ULONG LDAPAPI ldap_delete_sA( LDAP *ld, PCHAR dn ); WINLDAPAPI ULONG LDAPAPI ldap_delete_extW( LDAP *ld, PWCHAR dn, PLDAPControlW *ServerControls, PLDAPControlW *ClientControls, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_delete_extA( LDAP *ld, PCHAR dn, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_delete_ext_sW( LDAP *ld, PWCHAR dn, PLDAPControlW *ServerControls, PLDAPControlW *ClientControls ); WINLDAPAPI ULONG LDAPAPI ldap_delete_ext_sA( LDAP *ld, PCHAR dn, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls ); #if LDAP_UNICODE #define ldap_delete ldap_deleteW #define ldap_delete_ext ldap_delete_extW #define ldap_delete_s ldap_delete_sW #define ldap_delete_ext_s ldap_delete_ext_sW #else WINLDAPAPI ULONG LDAPAPI ldap_delete( LDAP *ld, PCHAR dn ); WINLDAPAPI ULONG LDAPAPI ldap_delete_s( LDAP *ld, PCHAR dn ); WINLDAPAPI ULONG LDAPAPI ldap_delete_ext( LDAP *ld, PCHAR dn, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_delete_ext_s( LDAP *ld, PCHAR dn, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls ); #endif // // Give up on a request. No guarentee that it got there as there is no // response from the server. // // multi-thread: ldap_abandon calls are thread safe WINLDAPAPI ULONG LDAPAPI ldap_abandon( LDAP *ld, ULONG msgid ); // // Possible values for "all" field in ldap_result. We've enhanced it such // that if someone passes in LDAP_MSG_RECEIVED, we'll pass all values we've // received up to that point. // #define LDAP_MSG_ONE 0 #define LDAP_MSG_ALL 1 #define LDAP_MSG_RECEIVED 2 // // Get a response from a connection. One enhancement here is that ld can // be null, in which case we'll return responses from any server. Free // responses here with ldap_msgfree. // // For connection-less LDAP, you should pass in both a LDAP connection // handle and a msgid. This will ensure we know which request the app // is waiting on a reply to. ( we actively resend request until we get // a response.) // // multi-thread: ldap_result calls are thread safe WINLDAPAPI ULONG LDAPAPI ldap_result( LDAP *ld, ULONG msgid, ULONG all, struct l_timeval *timeout, LDAPMessage **res ); WINLDAPAPI ULONG LDAPAPI ldap_msgfree( LDAPMessage *res ); // // This parses a message and returns the error code. It optionally frees // the message by calling ldap_msgfree. // // multi-thread: ldap_result2error call is thread safe WINLDAPAPI ULONG LDAPAPI ldap_result2error( LDAP *ld, LDAPMessage *res, ULONG freeit // boolean.. free the message? ); // // Similar to ldap_result2error, this parses responses from the server and // returns the appropriate fields. Use this one if you want to get at the // referrals, matchingDNs, or server controls returned. // // multi-thread: ldap_parse_result call is thread safe WINLDAPAPI ULONG LDAPAPI ldap_parse_resultW ( LDAP *Connection, LDAPMessage *ResultMessage, ULONG *ReturnCode OPTIONAL, // returned by server PWCHAR *MatchedDNs OPTIONAL, // free with ldap_memfree PWCHAR *ErrorMessage OPTIONAL, // free with ldap_memfree PWCHAR **Referrals OPTIONAL, // free with ldap_value_freeW PLDAPControlW **ServerControls OPTIONAL, // free with ldap_free_controlsW BOOLEAN Freeit ); WINLDAPAPI ULONG LDAPAPI ldap_parse_resultA ( LDAP *Connection, LDAPMessage *ResultMessage, ULONG *ReturnCode OPTIONAL, // returned by server PCHAR *MatchedDNs OPTIONAL, // free with ldap_memfree PCHAR *ErrorMessage OPTIONAL, // free with ldap_memfree PCHAR **Referrals OPTIONAL, // free with ldap_value_freeA PLDAPControlA **ServerControls OPTIONAL, // free with ldap_free_controlsA BOOLEAN Freeit ); WINLDAPAPI ULONG LDAPAPI ldap_controls_freeA ( LDAPControlA **Controls ); WINLDAPAPI ULONG LDAPAPI ldap_control_freeA ( LDAPControlA *Controls ); WINLDAPAPI ULONG LDAPAPI ldap_controls_freeW ( LDAPControlW **Control ); WINLDAPAPI ULONG LDAPAPI ldap_control_freeW ( LDAPControlW *Control ); // // ldap_free_controls are old, use ldap_controls_free // WINLDAPAPI ULONG LDAPAPI ldap_free_controlsW ( LDAPControlW **Controls ); WINLDAPAPI ULONG LDAPAPI ldap_free_controlsA ( LDAPControlA **Controls ); #if LDAP_UNICODE #define ldap_parse_result ldap_parse_resultW #define ldap_controls_free ldap_controls_freeW #define ldap_control_free ldap_control_freeW #define ldap_free_controls ldap_free_controlsW #else WINLDAPAPI ULONG LDAPAPI ldap_parse_result ( LDAP *Connection, LDAPMessage *ResultMessage, ULONG *ReturnCode OPTIONAL, // returned by server PCHAR *MatchedDNs OPTIONAL, // free with ldap_memfree PCHAR *ErrorMessage OPTIONAL, // free with ldap_memfree PCHAR **Referrals OPTIONAL, // free with ldap_value_free PLDAPControlA **ServerControls OPTIONAL, // free with ldap_free_controls BOOLEAN Freeit ); WINLDAPAPI ULONG LDAPAPI ldap_controls_free ( LDAPControlA **Controls ); WINLDAPAPI ULONG LDAPAPI ldap_control_free ( LDAPControlA *Control ); WINLDAPAPI ULONG LDAPAPI ldap_free_controls ( LDAPControlA **Controls ); #endif // // ldap_err2string returns a pointer to a string describing the error. This // string should not be freed. // WINLDAPAPI PWCHAR LDAPAPI ldap_err2stringW( ULONG err ); WINLDAPAPI PCHAR LDAPAPI ldap_err2stringA( ULONG err ); #if LDAP_UNICODE #define ldap_err2string ldap_err2stringW #else WINLDAPAPI PCHAR LDAPAPI ldap_err2string( ULONG err ); #endif // // ldap_perror does nothing and is here just for compatibility. // WINLDAPAPI void LDAPAPI ldap_perror( LDAP *ld, PCHAR msg ); // // Return the first entry of a message. It is freed when the message is // freed so should not be freed explicitly. // WINLDAPAPI LDAPMessage *LDAPAPI ldap_first_entry( LDAP *ld, LDAPMessage *res ); // // Return the next entry of a message. It is freed when the message is // freed so should not be freed explicitly. // WINLDAPAPI LDAPMessage *LDAPAPI ldap_next_entry( LDAP *ld, LDAPMessage *entry ); // // Count the number of search entries returned by the server in a response // to a server request. // WINLDAPAPI ULONG LDAPAPI ldap_count_entries( LDAP *ld, LDAPMessage *res ); // // A BerElement really maps out to a C++ class object that does BER encoding. // Don't mess with it as it's opaque. // typedef struct berelement { PCHAR opaque; // this is an opaque structure used just for // compatibility with reference implementation } BerElement; #define NULLBER ((BerElement *) 0) // // For a given entry, return the first attribute. The pointer returned is // actually a buffer in the connection block (with allowances for // multi-threaded apps) so it should not be freed. // WINLDAPAPI PWCHAR LDAPAPI ldap_first_attributeW( LDAP *ld, LDAPMessage *entry, BerElement **ptr ); WINLDAPAPI PCHAR LDAPAPI ldap_first_attributeA( LDAP *ld, LDAPMessage *entry, BerElement **ptr ); #if LDAP_UNICODE #define ldap_first_attribute ldap_first_attributeW #else WINLDAPAPI PCHAR LDAPAPI ldap_first_attribute( LDAP *ld, LDAPMessage *entry, BerElement **ptr ); #endif // // Return the next attribute... again, the attribute pointer should not be // freed. // WINLDAPAPI PWCHAR LDAPAPI ldap_next_attributeW( LDAP *ld, LDAPMessage *entry, BerElement *ptr ); WINLDAPAPI PCHAR LDAPAPI ldap_next_attributeA( LDAP *ld, LDAPMessage *entry, BerElement *ptr ); #if LDAP_UNICODE #define ldap_next_attribute ldap_next_attributeW #else WINLDAPAPI PCHAR LDAPAPI ldap_next_attribute( LDAP *ld, LDAPMessage *entry, BerElement *ptr ); #endif // // Get a given attribute's list of values. This is used during parsing of // a search response. It returns a list of pointers to values, the list is // null terminated. // // If the values are generic octet strings and not null terminated strings, // use ldap_get_values_len instead. // // The returned value should be freed when your done with it by calling // ldap_value_free. // WINLDAPAPI PWCHAR *LDAPAPI ldap_get_valuesW( LDAP *ld, LDAPMessage *entry, PWCHAR attr ); WINLDAPAPI PCHAR *LDAPAPI ldap_get_valuesA( LDAP *ld, LDAPMessage *entry, PCHAR attr ); #if LDAP_UNICODE #define ldap_get_values ldap_get_valuesW #else WINLDAPAPI PCHAR *LDAPAPI ldap_get_values( LDAP *ld, LDAPMessage *entry, PCHAR attr ); #endif // // Get a given attribute's list of values. This is used during parsing of // a search response. It returns a list of berval structures to values, // the list is null terminated. // // If the values are null terminated strings, it may be easier to process them // by calling ldap_get_values instead. // // The returned value should be freed when your done with it by calling // ldap_value_free_len. // WINLDAPAPI struct berval **LDAPAPI ldap_get_values_lenW ( LDAP *ExternalHandle, LDAPMessage *Message, PWCHAR attr ); WINLDAPAPI struct berval **LDAPAPI ldap_get_values_lenA ( LDAP *ExternalHandle, LDAPMessage *Message, PCHAR attr ); #if LDAP_UNICODE #define ldap_get_values_len ldap_get_values_lenW #else WINLDAPAPI struct berval **LDAPAPI ldap_get_values_len ( LDAP *ExternalHandle, LDAPMessage *Message, PCHAR attr ); #endif // // Return the number of values in a list returned by ldap_get_values. // WINLDAPAPI ULONG LDAPAPI ldap_count_valuesW( PWCHAR *vals ); WINLDAPAPI ULONG LDAPAPI ldap_count_valuesA( PCHAR *vals ); #if LDAP_UNICODE #define ldap_count_values ldap_count_valuesW #else WINLDAPAPI ULONG LDAPAPI ldap_count_values( PCHAR *vals ); #endif // // Return the number of values in a list returned by ldap_get_values_len. // WINLDAPAPI ULONG LDAPAPI ldap_count_values_len( struct berval **vals ); // // Free structures returned by ldap_get_values. // WINLDAPAPI ULONG LDAPAPI ldap_value_freeW( PWCHAR *vals ); WINLDAPAPI ULONG LDAPAPI ldap_value_freeA( PCHAR *vals ); #if LDAP_UNICODE #define ldap_value_free ldap_value_freeW #else WINLDAPAPI ULONG LDAPAPI ldap_value_free( PCHAR *vals ); #endif // // Free structures returned by ldap_get_values_len. // WINLDAPAPI ULONG LDAPAPI ldap_value_free_len( struct berval **vals ); // // Get the distinguished name for a given search entry. It should be freed // by calling ldap_memfree. // WINLDAPAPI PWCHAR LDAPAPI ldap_get_dnW( LDAP *ld, LDAPMessage *entry ); WINLDAPAPI PCHAR LDAPAPI ldap_get_dnA( LDAP *ld, LDAPMessage *entry ); #if LDAP_UNICODE #define ldap_get_dn ldap_get_dnW #else WINLDAPAPI PCHAR LDAPAPI ldap_get_dn( LDAP *ld, LDAPMessage *entry ); #endif // // When using ldap_explode_dn, you should free the returned string by // calling ldap_value_free. // WINLDAPAPI PWCHAR *LDAPAPI ldap_explode_dnW( PWCHAR dn, ULONG notypes ); WINLDAPAPI PCHAR *LDAPAPI ldap_explode_dnA( PCHAR dn, ULONG notypes ); #if LDAP_UNICODE #define ldap_explode_dn ldap_explode_dnW #else WINLDAPAPI PCHAR *LDAPAPI ldap_explode_dn( PCHAR dn, ULONG notypes ); #endif // // When calling ldap_dn2ufn, you should free the returned string by calling // ldap_memfree. // WINLDAPAPI PWCHAR LDAPAPI ldap_dn2ufnW( PWCHAR dn ); WINLDAPAPI PCHAR LDAPAPI ldap_dn2ufnA( PCHAR dn ); #if LDAP_UNICODE #define ldap_dn2ufn ldap_dn2ufnW #else WINLDAPAPI PCHAR LDAPAPI ldap_dn2ufn( PCHAR dn ); #endif // // This is used to free strings back to the LDAP API heap. Don't pass in // values that you've gotten from ldap_open, ldap_get_values, etc. // WINLDAPAPI VOID LDAPAPI ldap_memfreeW( PWCHAR Block ); WINLDAPAPI VOID LDAPAPI ldap_memfreeA( PCHAR Block ); WINLDAPAPI VOID LDAPAPI ber_bvfree( struct berval *bv ); #if LDAP_UNICODE #define ldap_memfree ldap_memfreeW #else WINLDAPAPI VOID LDAPAPI ldap_memfree( PCHAR Block ); #endif // // The function ldap_ufn2dn attempts to "normalize" a user specified DN // to make it "proper". It follows RFC 1781 (add CN= if not present, // add OU= if none present, etc). If it runs into any problems at all // while normalizing, it simply returns a copy of what was passed in. // // It allocates the output string from the LDAP memory pool. If the pDn // comes back as non-NULL, you should free it when you're done with a call // to ldap_memfree. // WINLDAPAPI ULONG LDAPAPI ldap_ufn2dnW ( PWCHAR ufn, PWCHAR *pDn ); WINLDAPAPI ULONG LDAPAPI ldap_ufn2dnA ( PCHAR ufn, PCHAR *pDn ); #if LDAP_UNICODE #define ldap_ufn2dn ldap_ufn2dnW #else WINLDAPAPI ULONG LDAPAPI ldap_ufn2dn ( PCHAR ufn, PCHAR *pDn ); #endif #define LBER_USE_DER 0x01 #define LBER_USE_INDEFINITE_LEN 0x02 #define LBER_TRANSLATE_STRINGS 0x04 // // Call to initialize the LDAP library. Pass in a version structure with // lv_size set to sizeof( LDAP_VERSION ), lv_major set to LAPI_MAJOR_VER1, // and lv_minor set to LAPI_MINOR_VER1. Return value will be either // LDAP_SUCCESS if OK or LDAP_OPERATIONS_ERROR if can't be supported. // #define LAPI_MAJOR_VER1 1 #define LAPI_MINOR_VER1 1 typedef struct ldap_version_info { ULONG lv_size; ULONG lv_major; ULONG lv_minor; } LDAP_VERSION_INFO, *PLDAP_VERSION_INFO; WINLDAPAPI ULONG LDAPAPI ldap_startup ( PLDAP_VERSION_INFO version, HANDLE *Instance ); // // ldap_cleanup unloads the library when the refcount of opens goes to zero. // (i.e. if a DLL calls it within a program that is also using it, it won't // free all resources) // WINLDAPAPI ULONG LDAPAPI ldap_cleanup ( HANDLE hInstance ); // // Extended API to support allowing opaque blobs of data in search filters. // This API takes any filter element and converts it to a safe text string that // can safely be passed in a search filter. // An example of using this is : // // filter is something like guid=4826BF6CF0123444 // this will put out on the wire guid of binary 0x4826BF6CF0123444 // // call ldap_escape_filter_element with sourceFilterElement pointing to // raw data, sourceCount set appropriately to length of data. // // if destFilterElement is NULL, then return value is length required for // output buffer. // // if destFilterElement is not NULL, then the function will copy the source // into the dest buffer and ensure that it is of a safe format. // // then simply insert the dest buffer into your search filter after the // "attributetype=". // // this will put out on the wire guid of binary 0x004826BF6CF000123444 // // Note : don't call this for attribute values that are really strings, as // we won't do any conversion from what you passed in to UTF-8. Should only // be used for attributes that really are raw binary. // WINLDAPAPI ULONG LDAPAPI ldap_escape_filter_elementW ( PCHAR sourceFilterElement, ULONG sourceLength, PWCHAR destFilterElement, ULONG destLength ); WINLDAPAPI ULONG LDAPAPI ldap_escape_filter_elementA ( PCHAR sourceFilterElement, ULONG sourceLength, PCHAR destFilterElement, ULONG destLength ); #if LDAP_UNICODE #define ldap_escape_filter_element ldap_escape_filter_elementW #else WINLDAPAPI ULONG LDAPAPI ldap_escape_filter_element ( PCHAR sourceFilterElement, ULONG sourceLength, PCHAR destFilterElement, ULONG destLength ); #endif // // Misc extensions for additional debugging. // // Note that these do nothing on free builds. // WINLDAPAPI ULONG LDAPAPI ldap_set_dbg_flags( ULONG NewFlags ); typedef ULONG (_cdecl *DBGPRINT)( PCH Format, ... ); WINLDAPAPI VOID LDAPAPI ldap_set_dbg_routine( DBGPRINT DebugPrintRoutine ); // // These routines are possibly useful by other modules. Note that Win95 // doesn't by default have the UTF-8 codepage loaded. So a good way to // convert from UTF-8 to Unicode. // WINLDAPAPI int LDAPAPI LdapUTF8ToUnicode( LPCSTR lpSrcStr, int cchSrc, LPWSTR lpDestStr, int cchDest ); WINLDAPAPI int LDAPAPI LdapUnicodeToUTF8( LPCWSTR lpSrcStr, int cchSrc, LPSTR lpDestStr, int cchDest ); // // LDAPv3 features : // // Sort Keys... these are used to ask the server to sort the results // before sending the results back. LDAPv3 only and optional to implement // on the server side. Check supportedControl for an OID of // "1.2.840.113556.1.4.473" to see if the server supports it. // #define LDAP_SERVER_SORT_OID "1.2.840.113556.1.4.473" #define LDAP_SERVER_SORT_OID_W L"1.2.840.113556.1.4.473" #define LDAP_SERVER_RESP_SORT_OID "1.2.840.113556.1.4.474" #define LDAP_SERVER_RESP_SORT_OID_W L"1.2.840.113556.1.4.474" typedef struct ldapsearch LDAPSearch, *PLDAPSearch; typedef struct ldapsortkeyW { PWCHAR sk_attrtype; PWCHAR sk_matchruleoid; BOOLEAN sk_reverseorder; } LDAPSortKeyW, *PLDAPSortKeyW; typedef struct ldapsortkeyA { PCHAR sk_attrtype; PCHAR sk_matchruleoid; BOOLEAN sk_reverseorder; } LDAPSortKeyA, *PLDAPSortKeyA; #if LDAP_UNICODE #define LDAPSortKey LDAPSortKeyW #define PLDAPSortKey PLDAPSortKeyW #else #define LDAPSortKey LDAPSortKeyA #define PLDAPSortKey PLDAPSortKeyA #endif // // This API formats a list of sort keys into a search control. Call // ldap_control_free when you're finished with the control. // // Use this one rather than ldap_encode_sort_control as this is per RFC. // WINLDAPAPI ULONG LDAPAPI ldap_create_sort_controlA ( PLDAP ExternalHandle, PLDAPSortKeyA *SortKeys, UCHAR IsCritical, PLDAPControlA *Control ); WINLDAPAPI ULONG LDAPAPI ldap_create_sort_controlW ( PLDAP ExternalHandle, PLDAPSortKeyW *SortKeys, UCHAR IsCritical, PLDAPControlW *Control ); // // This API parses the sort control returned by the server. Use ldap_memfree // to free the attribute value, if it's returned. // WINLDAPAPI ULONG LDAPAPI ldap_parse_sort_controlA ( PLDAP ExternalHandle, PLDAPControlA *Control, ULONG *Result, PCHAR *Attribute ); WINLDAPAPI ULONG LDAPAPI ldap_parse_sort_controlW ( PLDAP ExternalHandle, PLDAPControlW *Control, ULONG *Result, PWCHAR *Attribute ); #if LDAP_UNICODE #define ldap_create_sort_control ldap_create_sort_controlW #define ldap_parse_sort_control ldap_parse_sort_controlW #else WINLDAPAPI ULONG LDAPAPI ldap_create_sort_control ( PLDAP ExternalHandle, PLDAPSortKeyA *SortKeys, UCHAR IsCritical, PLDAPControlA *Control ); WINLDAPAPI ULONG LDAPAPI ldap_parse_sort_control ( PLDAP ExternalHandle, PLDAPControlA *Control, ULONG *Result, PCHAR *Attribute ); #endif // // This API formats a list of sort keys into a search control. Call // ldap_memfree for both Control->ldctl_value.bv_val and // Control->currentControl->ldctl_oid when you're finished with the control. // // This is the old sort API that will be shortly pulled. Please use // ldap_create_sort_control defined above. // WINLDAPAPI ULONG LDAPAPI ldap_encode_sort_controlW ( PLDAP ExternalHandle, PLDAPSortKeyW *SortKeys, PLDAPControlW Control, BOOLEAN Criticality ); WINLDAPAPI ULONG LDAPAPI ldap_encode_sort_controlA ( PLDAP ExternalHandle, PLDAPSortKeyA *SortKeys, PLDAPControlA Control, BOOLEAN Criticality ); #if LDAP_UNICODE #define ldap_encode_sort_control ldap_encode_sort_controlW #else WINLDAPAPI ULONG LDAPAPI ldap_encode_sort_control ( PLDAP ExternalHandle, PLDAPSortKeyA *SortKeys, PLDAPControlA Control, BOOLEAN Criticality ); #endif // // LDAPv3: This is the RFC defined API for the simple paging of results // control. Use ldap_control_free to free the control allocated by // ldap_create_page_control. // WINLDAPAPI ULONG LDAPAPI ldap_create_page_controlW( PLDAP ExternalHandle, ULONG PageSize, struct berval *Cookie, UCHAR IsCritical, PLDAPControlW *Control ); WINLDAPAPI ULONG LDAPAPI ldap_create_page_controlA( PLDAP ExternalHandle, ULONG PageSize, struct berval *Cookie, UCHAR IsCritical, PLDAPControlA *Control ); WINLDAPAPI ULONG LDAPAPI ldap_parse_page_controlW ( PLDAP ExternalHandle, PLDAPControlW *ServerControls, ULONG *TotalCount, struct berval **Cookie // Use ber_bvfree to free ); WINLDAPAPI ULONG LDAPAPI ldap_parse_page_controlA ( PLDAP ExternalHandle, PLDAPControlA *ServerControls, ULONG *TotalCount, struct berval **Cookie // Use ber_bvfree to free ); #if LDAP_UNICODE #define ldap_create_page_control ldap_create_page_controlW #define ldap_parse_page_control ldap_parse_page_controlW #else WINLDAPAPI ULONG LDAPAPI ldap_create_page_control( PLDAP ExternalHandle, ULONG PageSize, struct berval *Cookie, UCHAR IsCritical, PLDAPControlA *Control ); WINLDAPAPI ULONG LDAPAPI ldap_parse_page_control ( PLDAP ExternalHandle, PLDAPControlA *ServerControls, ULONG *TotalCount, struct berval **Cookie // Use ber_bvfree to free ); #endif // // LDAPv3: This is the interface for simple paging of results. To ensure // that the server supports it, check the supportedControl property off of // the root for an OID of 1.2.840.113556.1.4.319. If it is there, then it // supports this feature. // // If you're going to specify sort keys, see section above on sort keys on // now to tell if they're supported by the server. // // You first call ldap_search_init_page. If it returns a non-NULL LDAPSearch // block, then it worked ok. Otherwise call LdapGetLastError to find error. // // With a valid LDAPSearch block (there are opaque), call ldap_get_next_page // or ldap_get_next_page_s. If you call ldap_get_next_page, you MUST call // ldap_get_paged_count for each set of results that you get for that message. // This allows the library to save off the cookie that the server sent to // resume the search. // // Other than calling ldap_get_paged_count, the results you get back from // ldap_get_next_page can be treated as any other search result, and should // be freed when you're done by calling ldap_msgfree. // // When the end of the search is hit, you'll get a return code of // LDAP_NO_RESULTS_RETURNED. At this point, (or any point after LDAPSearch // structure has been allocated), you call ldap_search_abandon_page. You // need to call this even after you get a return code of // LDAP_NO_RESULTS_RETURNED. // // If you call ldap_get_next_page_s, you don't need to call // ldap_get_paged_count. // #define LDAP_PAGED_RESULT_OID_STRING "1.2.840.113556.1.4.319" #define LDAP_PAGED_RESULT_OID_STRING_W L"1.2.840.113556.1.4.319" WINLDAPAPI PLDAPSearch LDAPAPI ldap_search_init_pageW( PLDAP ExternalHandle, PWCHAR DistinguishedName, ULONG ScopeOfSearch, PWCHAR SearchFilter, PWCHAR AttributeList[], ULONG AttributesOnly, PLDAPControlW *ServerControls, PLDAPControlW *ClientControls, ULONG PageTimeLimit, ULONG TotalSizeLimit, PLDAPSortKeyW *SortKeys ); WINLDAPAPI PLDAPSearch LDAPAPI ldap_search_init_pageA( PLDAP ExternalHandle, PCHAR DistinguishedName, ULONG ScopeOfSearch, PCHAR SearchFilter, PCHAR AttributeList[], ULONG AttributesOnly, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG PageTimeLimit, ULONG TotalSizeLimit, PLDAPSortKeyA *SortKeys ); #if LDAP_UNICODE #define ldap_search_init_page ldap_search_init_pageW #else WINLDAPAPI PLDAPSearch LDAPAPI ldap_search_init_page( PLDAP ExternalHandle, PCHAR DistinguishedName, ULONG ScopeOfSearch, PCHAR SearchFilter, PCHAR AttributeList[], ULONG AttributesOnly, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG PageTimeLimit, ULONG TotalSizeLimit, PLDAPSortKeyA *SortKeys ); #endif WINLDAPAPI ULONG LDAPAPI ldap_get_next_page( PLDAP ExternalHandle, PLDAPSearch SearchHandle, ULONG PageSize, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_get_next_page_s( PLDAP ExternalHandle, PLDAPSearch SearchHandle, struct l_timeval *timeout, ULONG PageSize, ULONG *TotalCount, LDAPMessage **Results ); WINLDAPAPI ULONG LDAPAPI ldap_get_paged_count( PLDAP ExternalHandle, PLDAPSearch SearchBlock, ULONG *TotalCount, PLDAPMessage Results ); WINLDAPAPI ULONG LDAPAPI ldap_search_abandon_page( PLDAP ExternalHandle, PLDAPSearch SearchBlock ); // // These functions return subordinate referrals (references) that are returned // in search responses. There are two types of referrals. External referrals // where the naming context doesn't reside on the server (e.g. server says "I // don't have the data, look over there") and Subordinate referrals (or // references) where some data has been returned and the referrals are passed // to other naming contexts below the current one (e.g. servers says "Here's // some data from the tree I hold, go look here, there, and over there for // more data that is further down in the tree."). // // These routines handle the latter. For external references, use // ldap_parse_result. // // Return the first reference from a message. It is freed when the message is // freed so should not be freed explicitly. // WINLDAPAPI LDAPMessage *LDAPAPI ldap_first_reference( LDAP *ld, LDAPMessage *res ); // // Return the next entry of a message. It is freed when the message is // freed so should not be freed explicitly. // WINLDAPAPI LDAPMessage *LDAPAPI ldap_next_reference( LDAP *ld, LDAPMessage *entry ); // // Count the number of subordinate references returned by the server in a // response to a search request. // WINLDAPAPI ULONG LDAPAPI ldap_count_references( LDAP *ld, LDAPMessage *res ); // // We return the list of subordinate referrals in a search response message. // WINLDAPAPI ULONG LDAPAPI ldap_parse_referenceW ( LDAP *Connection, LDAPMessage *ResultMessage, PWCHAR **Referrals // free with ldap_value_freeW ); WINLDAPAPI ULONG LDAPAPI ldap_parse_referenceA ( LDAP *Connection, LDAPMessage *ResultMessage, PCHAR **Referrals // free with ldap_value_freeA ); #if LDAP_UNICODE #define ldap_parse_reference ldap_parse_referenceW #else WINLDAPAPI ULONG LDAPAPI ldap_parse_reference ( LDAP *Connection, LDAPMessage *ResultMessage, PCHAR **Referrals // free with ldap_value_free ); #endif // // These APIs allow a client to send an extended request (free for all) to // an LDAPv3 (or above) server. The functionality is fairly open... you can // send any request you'd like. Note that since we don't know if you'll // be receiving a single or multiple responses, you'll have to explicitly tell // us when you're done with the request by calling ldap_close_extended_op. // // These are thread safe. // WINLDAPAPI ULONG LDAPAPI ldap_extended_operationW( LDAP *ld, PWCHAR Oid, struct berval *Data, PLDAPControlW *ServerControls, PLDAPControlW *ClientControls, ULONG *MessageNumber ); WINLDAPAPI ULONG LDAPAPI ldap_extended_operationA( LDAP *ld, PCHAR Oid, struct berval *Data, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG *MessageNumber ); #if LDAP_UNICODE #define ldap_extended_operation ldap_extended_operationW #else WINLDAPAPI ULONG LDAPAPI ldap_extended_operation( LDAP *ld, PCHAR Oid, struct berval *Data, PLDAPControlA *ServerControls, PLDAPControlA *ClientControls, ULONG *MessageNumber ); #endif WINLDAPAPI ULONG LDAPAPI ldap_close_extended_op( LDAP *ld, ULONG MessageNumber ); // // Some enhancements that will probably never make it into the RFC related // to callouts to allow external caching of connections. // // Call ldap_set_option( conn, LDAP_OPT_REFERRAL_CALLBACK, &referralRoutines ) // where referralRoutines is the address of an LDAP_REFERRAL_CALLBACK // structure with your routines. They may be NULL, in which case we'll // obviously not make the calls. // // Any connections that are created will inherit the current callbacks from // the primary connection that the request was initiated on. // #define LDAP_OPT_REFERRAL_CALLBACK 0x70 // // This first routine is called when we're about to chase a referral. We // callout to it to see if there is already a connection cached that we // can use. If so, the callback routine returns the pointer to the // connection to use in ConnectionToUse. If not, it sets // *ConnectionToUse to NULL. // // For a return code, it should return 0 if we should continue to chase the // referral. If it returns a non-zero return code, we'll treat that as the // error code for chasing the referral. This allows caching of host names // that are not reachable, if we decide to add that in the future. // typedef ULONG (_cdecl QUERYFORCONNECTION)( PLDAP PrimaryConnection, PLDAP ReferralFromConnection, PWCHAR NewDN, PCHAR HostName, ULONG PortNumber, PVOID SecAuthIdentity, // if null, use CurrentUser below PVOID CurrentUserToken, // pointer to current user's LUID PLDAP *ConnectionToUse ); // // This next function is called when we've created a new connection while // chasing a referral. Note that it gets assigned the same callback functions // as the PrimaryConnection. If the return code is FALSE, then the call // back function doesn't want to cache the connection and it will be // destroyed after the operation is complete. If TRUE is returned, we'll // assume that the callee has taken ownership of the connection and it will // not be destroyed after the operation is complete. // // If the ErrorCodeFromBind field is not 0, then the bind operation to // that server failed. // typedef BOOLEAN (_cdecl NOTIFYOFNEWCONNECTION) ( PLDAP PrimaryConnection, PLDAP ReferralFromConnection, PWCHAR NewDN, PCHAR HostName, PLDAP NewConnection, ULONG PortNumber, PVOID SecAuthIdentity, // if null, use CurrentUser below PVOID CurrentUser, // pointer to current user's LUID ULONG ErrorCodeFromBind ); // // This next function is called when we've successfully called off to the // QueryForConnection call and received a connection OR when we called off // to the NotifyOfNewConnection call and it returned TRUE. We call this // function when we're dereferencing the connection after we're done with it. // // Return code is currently ignored, but the function should return // LDAP_SUCCESS if all went well. // typedef ULONG (_cdecl DEREFERENCECONNECTION)( PLDAP PrimaryConnection, PLDAP ConnectionToDereference ); typedef struct LdapReferralCallback { ULONG SizeOfCallbacks; // set to sizeof( LDAP_REFERRAL_CALLBACK ) QUERYFORCONNECTION *QueryForConnection; NOTIFYOFNEWCONNECTION *NotifyRoutine; DEREFERENCECONNECTION *DereferenceRoutine; } LDAP_REFERRAL_CALLBACK, *PLDAP_REFERRAL_CALLBACK; // // Thread Safe way to get last error code returned by LDAP API is to call // LdapGetLastError(); // WINLDAPAPI ULONG LDAPAPI LdapGetLastError( VOID ); // // Translate from LdapError to closest Win32 error code. // WINLDAPAPI ULONG LDAPAPI LdapMapErrorToWin32( ULONG LdapError ); #ifdef __cplusplus } #endif #endif // LDAP_CLIENT_DEFINED