Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

957 lines
20 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: drt.cxx
  7. //
  8. // Contents: Main for OleDs DRT
  9. //
  10. //
  11. // History: 28-Oct-94 KrishnaG, created OleDs DRT
  12. // 28-Oct-94 ChuckC, rewritten.
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "precomp.h"
  16. DWORD
  17. LdapOpen(
  18. WCHAR *domainName,
  19. int portno,
  20. HLDAP * phLdapHandle
  21. )
  22. {
  23. int ldaperr = 0;
  24. void *ldapOption;
  25. HLDAP hLdapHandle = NULL;
  26. DWORD dwError = 0;
  27. hLdapHandle = ldap_init(domainName, portno );
  28. if (hLdapHandle == NULL ) {
  29. dwError = ERROR_BAD_NETPATH;
  30. goto error;
  31. }
  32. //
  33. // Now process versioning
  34. //
  35. ldapOption = (void *) LDAP_VERSION3;
  36. ldaperr = ldap_set_option(
  37. hLdapHandle,
  38. LDAP_OPT_VERSION,
  39. &(ldapOption)
  40. );
  41. if (ldaperr) {
  42. dwError = CheckAndSetExtendedError(hLdapHandle, ldaperr);
  43. goto error;
  44. }
  45. ldaperr = ldap_set_option(
  46. hLdapHandle,
  47. LDAP_OPT_DNSDOMAIN_NAME ,
  48. &(domainName)
  49. );
  50. if (ldaperr) {
  51. dwError = CheckAndSetExtendedError(hLdapHandle, ldaperr);
  52. goto error;
  53. }
  54. ldapOption = LDAP_OPT_ON;
  55. ldaperr = ldap_set_option(
  56. hLdapHandle,
  57. LDAP_OPT_ENCRYPT ,
  58. &(ldapOption)
  59. );
  60. if (ldaperr) {
  61. dwError = CheckAndSetExtendedError(hLdapHandle, ldaperr);
  62. goto error;
  63. }
  64. ldaperr = ldap_set_option(
  65. hLdapHandle,
  66. LDAP_OPT_SIGN ,
  67. &(ldapOption)
  68. );
  69. if (ldaperr) {
  70. dwError = CheckAndSetExtendedError(hLdapHandle, ldaperr);
  71. goto error;
  72. }
  73. ldaperr = ldap_connect(hLdapHandle, NULL);
  74. if (ldaperr) {
  75. dwError = CheckAndSetExtendedError(hLdapHandle, ldaperr);
  76. goto error;
  77. }
  78. //
  79. // Disabled Callback function support and chasing external referrals
  80. // KrishnaG - do I need to support this.
  81. *phLdapHandle = hLdapHandle;
  82. return(dwError);
  83. error:
  84. if (hLdapHandle != NULL) {
  85. ldaperr = ldap_unbind( hLdapHandle );
  86. }
  87. return (dwError);
  88. }
  89. DWORD
  90. LdapBind(
  91. HLDAP hLdapHandle
  92. )
  93. {
  94. int ldaperr = 0;
  95. ldaperr = ldap_bind_s(hLdapHandle, NULL, NULL, LDAP_AUTH_SSPI);
  96. return (ldaperr);
  97. }
  98. DWORD
  99. LdapSearchHelper(
  100. HLDAP hLdapHandle,
  101. WCHAR *base,
  102. int scope,
  103. WCHAR *filter,
  104. WCHAR *attrs[],
  105. int attrsonly,
  106. struct l_timeval *timeout,
  107. LDAPMessage **res
  108. )
  109. {
  110. int nCount = 0;
  111. int j = 0;
  112. int ldaperr = 0;
  113. DWORD dwError = 0;
  114. if ( timeout == NULL )
  115. {
  116. ldaperr = ldap_search_s(
  117. hLdapHandle,
  118. base,
  119. scope,
  120. filter,
  121. attrs,
  122. attrsonly,
  123. res
  124. );
  125. dwError = CheckAndSetExtendedError(hLdapHandle, ldaperr);
  126. }
  127. else
  128. {
  129. ldaperr = ldap_search_st(
  130. hLdapHandle,
  131. base,
  132. scope,
  133. filter,
  134. attrs,
  135. attrsonly,
  136. timeout,
  137. res
  138. );
  139. dwError = CheckAndSetExtendedError(hLdapHandle, ldaperr);
  140. }
  141. //
  142. // Is there an error with checking the no of results
  143. //
  144. return (dwError);
  145. }
  146. DWORD
  147. LdapSearchS(
  148. HLDAP hLdapHandle,
  149. WCHAR *base,
  150. int scope,
  151. WCHAR *filter,
  152. WCHAR *attrs[],
  153. int attrsonly,
  154. LDAPMessage **res
  155. )
  156. {
  157. DWORD dwError = 0;
  158. dwError = LdapSearchHelper(
  159. hLdapHandle,
  160. base,
  161. scope,
  162. filter,
  163. attrs,
  164. attrsonly,
  165. NULL,
  166. res
  167. );
  168. //
  169. // Is there a check needed for connection errors
  170. //
  171. return(dwError);
  172. }
  173. DWORD
  174. LdapSearchST(
  175. HLDAP hLdapHandle,
  176. WCHAR *base,
  177. int scope,
  178. WCHAR *filter,
  179. WCHAR *attrs[],
  180. int attrsonly,
  181. struct l_timeval *timeout,
  182. LDAPMessage **res
  183. )
  184. {
  185. DWORD dwError = 0;
  186. dwError = LdapSearchHelper(
  187. hLdapHandle,
  188. base,
  189. scope,
  190. filter,
  191. attrs,
  192. attrsonly,
  193. timeout,
  194. res
  195. );
  196. return(dwError);
  197. }
  198. //
  199. // Completely new functionality - block ported from YihsinS code in ADSI
  200. //
  201. DWORD
  202. LdapAbandon(
  203. HLDAP hLdapHandle,
  204. int msgid
  205. )
  206. {
  207. // No error code, 0 if success, -1 otherwise
  208. return ldap_abandon( hLdapHandle, msgid );
  209. }
  210. DWORD
  211. LdapResult(
  212. HLDAP hLdapHandle,
  213. int msgid,
  214. int all,
  215. struct l_timeval *timeout,
  216. LDAPMessage **res,
  217. int *restype
  218. )
  219. {
  220. DWORD dwError = 0;
  221. int ldaperr = 0;
  222. *restype = ldap_result( hLdapHandle, msgid, all, timeout, res );
  223. if ( *restype == -1 ) // error
  224. ldaperr = LdapGetLastError();
  225. if (ldaperr) {
  226. if (!ldap_count_entries( hLdapHandle, *res )) {
  227. dwError = CheckAndSetExtendedError( hLdapHandle, ldaperr);
  228. }
  229. }else {
  230. dwError = 0;
  231. }
  232. return(dwError);
  233. }
  234. void
  235. LdapMsgFree(
  236. LDAPMessage *res
  237. )
  238. {
  239. ldap_msgfree( res ); // Returns the type of message freed which
  240. // is not interesting
  241. }
  242. int
  243. LdapResult2Error(
  244. HLDAP hLdapHandle,
  245. LDAPMessage *res,
  246. int freeit
  247. )
  248. {
  249. return ldap_result2error( hLdapHandle, res, freeit );
  250. }
  251. DWORD
  252. LdapFirstEntry(
  253. HLDAP hLdapHandle,
  254. LDAPMessage *res,
  255. LDAPMessage **pfirst
  256. )
  257. {
  258. DWORD dwError = 0;
  259. int ldaperr = 0;
  260. *pfirst = ldap_first_entry( hLdapHandle, res );
  261. if ( *pfirst == NULL )
  262. {
  263. ldaperr = LdapGetLastError();
  264. dwError = CheckAndSetExtendedError( hLdapHandle, ldaperr);
  265. }
  266. return(dwError);
  267. }
  268. DWORD
  269. LdapNextEntry(
  270. HLDAP hLdapHandle,
  271. LDAPMessage *entry,
  272. LDAPMessage **pnext
  273. )
  274. {
  275. DWORD dwError = 0;
  276. int ldaperr = 0;
  277. *pnext = ldap_next_entry( hLdapHandle, entry );
  278. if ( *pnext == NULL )
  279. {
  280. ldaperr = LdapGetLastError();
  281. dwError = CheckAndSetExtendedError( hLdapHandle, ldaperr);
  282. }
  283. return(dwError);
  284. }
  285. int
  286. LdapCountEntries(
  287. HLDAP hLdapHandle,
  288. LDAPMessage *res
  289. )
  290. {
  291. return ldap_count_entries( hLdapHandle, res );
  292. }
  293. DWORD
  294. LdapFirstAttribute(
  295. HLDAP hLdapHandle,
  296. LDAPMessage *entry,
  297. void **ptr,
  298. WCHAR **pattr
  299. )
  300. {
  301. // NOTE: The return value from ldap_first_attribute is static and
  302. // should not be freed
  303. *pattr = ldap_first_attribute( hLdapHandle, entry,
  304. (struct berelement **) ptr ); // static data
  305. if ( *pattr == NULL )
  306. {
  307. DWORD dwError = 0;
  308. int ldaperr = 0;
  309. // Error occurred or end of attributes
  310. ldaperr = LdapGetLastError();
  311. CheckAndSetExtendedError( hLdapHandle, ldaperr);
  312. return(dwError);
  313. }
  314. return NO_ERROR;
  315. }
  316. DWORD
  317. LdapNextAttribute(
  318. HLDAP hLdapHandle,
  319. LDAPMessage *entry,
  320. void *ptr,
  321. WCHAR **pattr
  322. )
  323. {
  324. // NOTE: The return value from ldap_next_attribute is static and
  325. // should not be freed
  326. *pattr = ldap_next_attribute( hLdapHandle, entry,
  327. (struct berelement *) ptr ); // static data
  328. #if 0 // Ignore the error code here since at the end of the enumeration,
  329. // we will probably get an error code here ( both Andy and umich's
  330. // dll will return errors sometimes. No error returned from NTDS,
  331. // but errors are returned from Exchange server )
  332. if ( *pattr == NULL )
  333. {
  334. DWORD hr = NO_ERROR;
  335. int ldaperr = 0;
  336. // Error occurred or end of attributes
  337. ldaperr = LdapGetLastError();
  338. dwError = CheckAndSetExtendedError( hLdapHandle, ldaperr);
  339. return(dwError);
  340. }
  341. #endif
  342. return S_OK;
  343. }
  344. //
  345. // NOTE: LdapGetValues return S_OK if attribute [attr] has no values
  346. // (*[pvalues] =NULL, *[pcount]=0) but all else ok.
  347. //
  348. DWORD
  349. LdapGetValues(
  350. HLDAP hLdapHandle,
  351. LDAPMessage *entry,
  352. WCHAR *attr,
  353. WCHAR ***pvalues,
  354. int *pcount
  355. )
  356. {
  357. DWORD dwError = 0;
  358. int ldaperr = 0;
  359. *pvalues = ldap_get_values( hLdapHandle, entry, attr );
  360. if ( *pvalues == NULL ) {
  361. *pcount=0;
  362. //
  363. // ldap_get_values succeeds if attribute has no values
  364. // but all else ok. (confiremed with anoopa)
  365. //
  366. ldaperr = LdapGetLastError();
  367. if (ldaperr) {
  368. dwError = CheckAndSetExtendedError( hLdapHandle, ldaperr);
  369. }
  370. //
  371. // KrishnaG if *pvalues is NULL which means I don't get back a
  372. // value - return an ERROR
  373. //
  374. return(ERROR_DS_NO_ATTRIBUTE_OR_VALUE);
  375. }
  376. *pcount = ldap_count_values( *pvalues );
  377. return S_OK;
  378. }
  379. //
  380. // NOTE: LdapGetValuesLen return S_OK if attribute [attr] has no values
  381. // (*[pvalues] =NULL, *[pcount]=0) but all else ok.
  382. //
  383. DWORD
  384. LdapGetValuesLen(
  385. HLDAP hLdapHandle,
  386. LDAPMessage *entry,
  387. WCHAR *attr,
  388. struct berval ***pvalues,
  389. int *pcount
  390. )
  391. {
  392. //
  393. // NOTE: this can contain binary data as well as strings,
  394. // strings are ascii, no conversion is done here
  395. //
  396. char *pszAttrA = NULL;
  397. DWORD dwError = 0;
  398. int ldaperr = 0;
  399. *pvalues = ldap_get_values_len( hLdapHandle, entry, attr );
  400. if ( *pvalues == NULL ){
  401. *pcount=0;
  402. //
  403. // ldap_get_values succeeds if attribute has no values
  404. // but all else ok. (confiremed with anoopa)
  405. //
  406. ldaperr = LdapGetLastError();
  407. if (ldaperr) {
  408. dwError = CheckAndSetExtendedError( hLdapHandle,ldaperr);
  409. }
  410. return(ERROR_DS_NO_ATTRIBUTE_OR_VALUE);
  411. }
  412. *pcount = ldap_count_values_len( *pvalues );
  413. return S_OK;
  414. }
  415. void
  416. LdapValueFree(
  417. WCHAR **vals
  418. )
  419. {
  420. ldap_value_free( vals );
  421. }
  422. void
  423. LdapValueFreeLen(
  424. struct berval **vals
  425. )
  426. {
  427. ldap_value_free_len( vals );
  428. }
  429. void
  430. LdapMemFree(
  431. WCHAR *pszString
  432. )
  433. {
  434. ldap_memfree( pszString );
  435. }
  436. void
  437. LdapAttributeFree(
  438. WCHAR *pszString
  439. )
  440. {
  441. // String from ldap_first/next_attribute should not be freed,
  442. // so do nothing here
  443. }
  444. DWORD
  445. LdapGetDn(
  446. HLDAP hLdapHandle,
  447. LDAPMessage *entry,
  448. WCHAR **pdn
  449. )
  450. {
  451. int ldaperr = 0;
  452. DWORD dwError = 0;
  453. *pdn = ldap_get_dn( hLdapHandle, entry );
  454. if ( *pdn == NULL )
  455. {
  456. // Error occurred
  457. ldaperr = LdapGetLastError();
  458. dwError = CheckAndSetExtendedError( hLdapHandle, ldaperr);
  459. return(dwError);
  460. }
  461. return(dwError);
  462. }
  463. DWORD
  464. CheckAndSetExtendedError(
  465. HLDAP hLdapHandle,
  466. int ldaperr
  467. )
  468. {
  469. DWORD dwErr = NO_ERROR;
  470. switch (ldaperr) {
  471. case LDAP_SUCCESS :
  472. dwErr = NO_ERROR;
  473. break;
  474. case LDAP_OPERATIONS_ERROR :
  475. dwErr = ERROR_DS_OPERATIONS_ERROR;
  476. break;
  477. case LDAP_PROTOCOL_ERROR :
  478. dwErr = ERROR_DS_PROTOCOL_ERROR;
  479. break;
  480. case LDAP_TIMELIMIT_EXCEEDED :
  481. dwErr = ERROR_DS_TIMELIMIT_EXCEEDED;
  482. break;
  483. case LDAP_SIZELIMIT_EXCEEDED :
  484. dwErr = ERROR_DS_SIZELIMIT_EXCEEDED;
  485. break;
  486. case LDAP_COMPARE_FALSE :
  487. dwErr = ERROR_DS_COMPARE_FALSE;
  488. break;
  489. case LDAP_COMPARE_TRUE :
  490. dwErr = ERROR_DS_COMPARE_TRUE;
  491. break;
  492. case LDAP_AUTH_METHOD_NOT_SUPPORTED :
  493. dwErr = ERROR_DS_AUTH_METHOD_NOT_SUPPORTED;
  494. break;
  495. case LDAP_STRONG_AUTH_REQUIRED :
  496. dwErr = ERROR_DS_STRONG_AUTH_REQUIRED;
  497. break;
  498. case LDAP_PARTIAL_RESULTS :
  499. //
  500. // Make sure we handle
  501. // partial results.
  502. //
  503. dwErr = ERROR_MORE_DATA;
  504. break;
  505. case LDAP_REFERRAL :
  506. dwErr = ERROR_DS_REFERRAL;
  507. break;
  508. case LDAP_ADMIN_LIMIT_EXCEEDED :
  509. dwErr = ERROR_DS_ADMIN_LIMIT_EXCEEDED;
  510. break;
  511. case LDAP_UNAVAILABLE_CRIT_EXTENSION :
  512. dwErr = ERROR_DS_UNAVAILABLE_CRIT_EXTENSION;
  513. break;
  514. case LDAP_CONFIDENTIALITY_REQUIRED :
  515. dwErr = ERROR_DS_CONFIDENTIALITY_REQUIRED;
  516. break;
  517. case LDAP_NO_SUCH_ATTRIBUTE :
  518. dwErr = ERROR_DS_NO_ATTRIBUTE_OR_VALUE;
  519. break;
  520. case LDAP_UNDEFINED_TYPE :
  521. dwErr = ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED;
  522. break;
  523. case LDAP_INAPPROPRIATE_MATCHING :
  524. dwErr = ERROR_DS_INAPPROPRIATE_MATCHING;
  525. break;
  526. case LDAP_CONSTRAINT_VIOLATION :
  527. dwErr = ERROR_DS_CONSTRAINT_VIOLATION;
  528. break;
  529. case LDAP_ATTRIBUTE_OR_VALUE_EXISTS :
  530. dwErr = ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS;
  531. break;
  532. case LDAP_INVALID_SYNTAX :
  533. dwErr = ERROR_DS_INVALID_ATTRIBUTE_SYNTAX;
  534. break;
  535. case LDAP_NO_SUCH_OBJECT :
  536. dwErr = ERROR_DS_NO_SUCH_OBJECT;
  537. break;
  538. case LDAP_ALIAS_PROBLEM :
  539. dwErr = ERROR_DS_ALIAS_PROBLEM;
  540. break;
  541. case LDAP_INVALID_DN_SYNTAX :
  542. dwErr = ERROR_DS_INVALID_DN_SYNTAX;
  543. break;
  544. case LDAP_IS_LEAF :
  545. dwErr = ERROR_DS_IS_LEAF;
  546. break;
  547. case LDAP_ALIAS_DEREF_PROBLEM :
  548. dwErr = ERROR_DS_ALIAS_DEREF_PROBLEM;
  549. break;
  550. case LDAP_INAPPROPRIATE_AUTH :
  551. dwErr = ERROR_DS_INAPPROPRIATE_AUTH;
  552. break;
  553. case LDAP_INVALID_CREDENTIALS :
  554. dwErr = ERROR_LOGON_FAILURE;
  555. break;
  556. case LDAP_INSUFFICIENT_RIGHTS :
  557. dwErr = ERROR_ACCESS_DENIED;
  558. break;
  559. case LDAP_BUSY :
  560. dwErr = ERROR_DS_BUSY;
  561. break;
  562. case LDAP_UNAVAILABLE :
  563. dwErr = ERROR_DS_UNAVAILABLE;
  564. break;
  565. case LDAP_UNWILLING_TO_PERFORM :
  566. dwErr = ERROR_DS_UNWILLING_TO_PERFORM;
  567. break;
  568. case LDAP_LOOP_DETECT :
  569. dwErr = ERROR_DS_LOOP_DETECT;
  570. break;
  571. case LDAP_NAMING_VIOLATION :
  572. dwErr = ERROR_DS_NAMING_VIOLATION;
  573. break;
  574. case LDAP_OBJECT_CLASS_VIOLATION :
  575. dwErr = ERROR_DS_OBJ_CLASS_VIOLATION;
  576. break;
  577. case LDAP_NOT_ALLOWED_ON_NONLEAF :
  578. dwErr = ERROR_DS_CANT_ON_NON_LEAF;
  579. break;
  580. case LDAP_NOT_ALLOWED_ON_RDN :
  581. dwErr = ERROR_DS_CANT_ON_RDN;
  582. break;
  583. case LDAP_ALREADY_EXISTS :
  584. dwErr = ERROR_OBJECT_ALREADY_EXISTS;
  585. break;
  586. case LDAP_NO_OBJECT_CLASS_MODS :
  587. dwErr = ERROR_DS_CANT_MOD_OBJ_CLASS;
  588. break;
  589. case LDAP_RESULTS_TOO_LARGE :
  590. dwErr = ERROR_DS_OBJECT_RESULTS_TOO_LARGE;
  591. break;
  592. case LDAP_AFFECTS_MULTIPLE_DSAS :
  593. dwErr = ERROR_DS_AFFECTS_MULTIPLE_DSAS;
  594. break;
  595. case LDAP_OTHER :
  596. dwErr = ERROR_GEN_FAILURE;
  597. break;
  598. case LDAP_SERVER_DOWN :
  599. dwErr = ERROR_DS_SERVER_DOWN;
  600. break;
  601. case LDAP_LOCAL_ERROR :
  602. dwErr = ERROR_DS_LOCAL_ERROR;
  603. break;
  604. case LDAP_ENCODING_ERROR :
  605. dwErr = ERROR_DS_ENCODING_ERROR;
  606. break;
  607. case LDAP_DECODING_ERROR :
  608. dwErr = ERROR_DS_DECODING_ERROR;
  609. break;
  610. case LDAP_TIMEOUT :
  611. dwErr = ERROR_TIMEOUT;
  612. break;
  613. case LDAP_AUTH_UNKNOWN :
  614. dwErr = ERROR_DS_AUTH_UNKNOWN;
  615. break;
  616. case LDAP_FILTER_ERROR :
  617. dwErr = ERROR_DS_FILTER_UNKNOWN;
  618. break;
  619. case LDAP_USER_CANCELLED :
  620. dwErr = ERROR_CANCELLED;
  621. break;
  622. case LDAP_PARAM_ERROR :
  623. dwErr = ERROR_DS_PARAM_ERROR;
  624. break;
  625. case LDAP_NO_MEMORY :
  626. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  627. break;
  628. case LDAP_CONNECT_ERROR :
  629. dwErr = ERROR_CONNECTION_REFUSED;
  630. break;
  631. case LDAP_NOT_SUPPORTED :
  632. dwErr = ERROR_DS_NOT_SUPPORTED;
  633. break;
  634. case LDAP_NO_RESULTS_RETURNED :
  635. dwErr = ERROR_DS_NO_RESULTS_RETURNED;
  636. break;
  637. case LDAP_CONTROL_NOT_FOUND :
  638. dwErr = ERROR_DS_CONTROL_NOT_FOUND;
  639. break;
  640. case LDAP_MORE_RESULTS_TO_RETURN :
  641. dwErr = ERROR_MORE_DATA;
  642. break;
  643. case LDAP_CLIENT_LOOP :
  644. dwErr = ERROR_DS_CLIENT_LOOP;
  645. break;
  646. case LDAP_REFERRAL_LIMIT_EXCEEDED :
  647. dwErr = ERROR_DS_REFERRAL_LIMIT_EXCEEDED;
  648. break;
  649. default:
  650. dwErr = ERROR_DS_BUSY;
  651. }
  652. return(dwErr);
  653. }
  654. DWORD
  655. LdapAddS(
  656. HLDAP hLdapHandle,
  657. WCHAR *dn,
  658. LDAPModW *attrs[]
  659. )
  660. {
  661. DWORD dwError = 0;
  662. int ldaperr = 0;
  663. ldaperr = ldap_add_s( hLdapHandle, dn, attrs );
  664. dwError = CheckAndSetExtendedError(hLdapHandle, ldaperr);
  665. return(dwError);
  666. }
  667. DWORD
  668. LdapModifyS(
  669. HLDAP hLdapHandle,
  670. WCHAR *dn,
  671. LDAPModW *mods[]
  672. )
  673. {
  674. DWORD dwError = 0;
  675. int ldaperr = 0;
  676. ldaperr = ldap_modify_s( hLdapHandle, dn, mods);
  677. dwError = CheckAndSetExtendedError(hLdapHandle, ldaperr);
  678. return(dwError);
  679. }
  680. DWORD
  681. LdapDeleteS(
  682. HLDAP hLdapHandle,
  683. WCHAR *dn
  684. )
  685. {
  686. DWORD dwError = 0;
  687. int ldaperr = 0;
  688. ldaperr = ldap_delete_s( hLdapHandle, dn );
  689. dwError = CheckAndSetExtendedError(hLdapHandle, ldaperr);
  690. return(dwError);
  691. }
  692. DWORD
  693. LdapRename(
  694. HLDAP hLdapHandle,
  695. WCHAR *oldDn,
  696. WCHAR *newDn
  697. )
  698. {
  699. DWORD dwError = 0;
  700. dwError = ldap_modrdn_s (hLdapHandle, oldDn, newDn);
  701. // dwError = ldap_rename_ext_s(hLdapHandle, dn, newName, parentNode, TRUE, NULL, NULL);
  702. return(dwError);
  703. }