Source code of Windows XP (NT5)
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.

1360 lines
29 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1997.
  5. //
  6. // File: pathmgmt.cxx
  7. //
  8. // Contents:
  9. //
  10. // Functions:
  11. //
  12. // History: 25-April-97 KrishnaG Created.
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "ldapc.hxx"
  16. #pragma hdrstop
  17. #define STRING_LENGTH(p) ( p ? wcslen(p) : 0)
  18. HRESULT
  19. BuildADsParentPathFromObjectInfo2(
  20. POBJECTINFO pObjectInfo,
  21. LPWSTR *ppszParent,
  22. LPWSTR *ppszCommonName
  23. )
  24. {
  25. DWORD i = 0;
  26. DWORD dwNumComponents = 0;
  27. HRESULT hr = S_OK;
  28. LPWSTR pszComponent = NULL, pszValue = NULL;
  29. hr = ComputeAllocateParentCommonNameSize(pObjectInfo, ppszParent, ppszCommonName);
  30. BAIL_ON_FAILURE(hr);
  31. hr = BuildADsParentPathFromObjectInfo(
  32. pObjectInfo,
  33. *ppszParent,
  34. *ppszCommonName
  35. );
  36. BAIL_ON_FAILURE(hr);
  37. RRETURN(hr);
  38. error:
  39. if (*ppszParent) {
  40. FreeADsMem(*ppszParent);
  41. }
  42. if (*ppszCommonName) {
  43. FreeADsMem(*ppszCommonName);
  44. }
  45. RRETURN(hr);
  46. }
  47. HRESULT
  48. BuildADsParentPath(
  49. LPWSTR szBuffer,
  50. LPWSTR *ppszParent,
  51. LPWSTR *ppszCommonName
  52. )
  53. {
  54. OBJECTINFO ObjectInfo;
  55. POBJECTINFO pObjectInfo = &ObjectInfo;
  56. HRESULT hr = S_OK;
  57. LPWSTR pszCommonName = NULL;
  58. LPWSTR pszParent = NULL;
  59. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  60. hr = ADsObject(szBuffer, pObjectInfo);
  61. BAIL_ON_FAILURE(hr);
  62. // The length of pszParent or pszCommon is definitely less than the
  63. // length of the total buffer.
  64. pszParent = (LPWSTR) AllocADsMem( (_tcslen(szBuffer) + 1) * sizeof(TCHAR));
  65. if ( pszParent == NULL )
  66. {
  67. hr = E_OUTOFMEMORY;
  68. BAIL_ON_FAILURE(hr);
  69. }
  70. pszCommonName = (LPWSTR) AllocADsMem( (_tcslen(szBuffer) + 1) * sizeof(TCHAR));
  71. if ( pszCommonName == NULL )
  72. {
  73. hr = E_OUTOFMEMORY;
  74. BAIL_ON_FAILURE(hr);
  75. }
  76. hr = BuildADsParentPathFromObjectInfo(
  77. pObjectInfo,
  78. pszParent,
  79. pszCommonName
  80. );
  81. BAIL_ON_FAILURE(hr);
  82. *ppszParent = pszParent;
  83. *ppszCommonName = pszCommonName;
  84. FreeObjectInfo( &ObjectInfo );
  85. RRETURN(hr);
  86. error:
  87. if (pszCommonName) {
  88. FreeADsMem(pszCommonName);
  89. }
  90. if (pszParent) {
  91. FreeADsMem(pszParent);
  92. }
  93. FreeObjectInfo( &ObjectInfo );
  94. RRETURN(hr);
  95. }
  96. HRESULT
  97. BuildADsParentPathFromObjectInfo(
  98. POBJECTINFO pObjectInfo,
  99. LPWSTR pszParent,
  100. LPWSTR pszCommonName
  101. )
  102. {
  103. DWORD i = 0;
  104. DWORD dwNumComponents = 0;
  105. HRESULT hr = S_OK;
  106. LPWSTR pszComponent = NULL, pszValue = NULL;
  107. dwNumComponents = pObjectInfo->NumComponents;
  108. if (!dwNumComponents && !pObjectInfo->DisplayTreeName) {
  109. //
  110. // There are no CNs in this pathname and
  111. // no tree name specified. This is the
  112. // namespace object - its parent is the
  113. // @ADs! object
  114. //
  115. wsprintf(pszParent,L"ADs:");
  116. wsprintf(pszCommonName, L"%s:", pObjectInfo->NamespaceName);
  117. hr = S_OK;
  118. } else if (!dwNumComponents && pObjectInfo->DisplayTreeName) {
  119. //
  120. // There are no CNs in this pathname and a tree
  121. // name has been specified. This is the root
  122. // object - its parent is the @NDS! object
  123. wsprintf(pszParent, L"%s:", pObjectInfo->NamespaceName);
  124. //
  125. // And the common name is the TreeName (and port)
  126. //
  127. if ( IS_EXPLICIT_PORT(pObjectInfo->PortNumber) ) {
  128. wsprintf(pszCommonName,L"%s:%d", pObjectInfo->TreeName, pObjectInfo->PortNumber);
  129. }
  130. else {
  131. wsprintf(pszCommonName,L"%s", pObjectInfo->TreeName);
  132. }
  133. hr = S_OK;
  134. }else {
  135. //
  136. // There are one or more CNs, a tree name has been
  137. // specified. In the worst case the parent is the
  138. // root object. In the best case a long CN.
  139. //
  140. switch (pObjectInfo->dwServerPresent) {
  141. case TRUE:
  142. if ( IS_EXPLICIT_PORT(pObjectInfo->PortNumber) ) {
  143. wsprintf(
  144. pszParent, L"%s://%s:%d",
  145. pObjectInfo->NamespaceName,
  146. pObjectInfo->DisplayTreeName,
  147. pObjectInfo->PortNumber
  148. );
  149. }
  150. else {
  151. wsprintf(
  152. pszParent, L"%s://%s",
  153. pObjectInfo->NamespaceName,
  154. pObjectInfo->DisplayTreeName
  155. );
  156. }
  157. break;
  158. case FALSE:
  159. wsprintf(
  160. pszParent, L"%s:",
  161. pObjectInfo->NamespaceName
  162. );
  163. break;
  164. }
  165. switch (pObjectInfo->dwPathType) {
  166. case PATHTYPE_X500:
  167. default: // where we cannot make a determination whether its X500 or Windows style
  168. if (dwNumComponents > 1) {
  169. if (pObjectInfo->dwServerPresent) {
  170. wcscat(pszParent, L"/");
  171. }else {
  172. wcscat(pszParent,L"//");
  173. }
  174. for (i = 1; i < dwNumComponents; i++) {
  175. AppendComponent(pszParent, &(pObjectInfo->DisplayComponentArray[i]));
  176. if (i < (dwNumComponents - 1)) {
  177. wcscat(pszParent, L",");
  178. }
  179. }
  180. }
  181. //
  182. // And the common name is the last component
  183. //
  184. pszComponent = pObjectInfo->DisplayComponentArray[0].szComponent;
  185. pszValue = pObjectInfo->DisplayComponentArray[0].szValue;
  186. if (pszComponent && pszValue) {
  187. wsprintf(pszCommonName, L"%s=%s",pszComponent, pszValue);
  188. }else if (pszComponent){
  189. wsprintf(pszCommonName, L"%s", pszComponent);
  190. }else {
  191. //
  192. // Error - we should never hit this case!!
  193. //
  194. }
  195. hr = S_OK;
  196. break;
  197. case PATHTYPE_WINDOWS:
  198. switch (pObjectInfo->dwServerPresent) {
  199. case FALSE:
  200. if (dwNumComponents > 1) {
  201. wcscat(pszParent,L"//");
  202. for (i = 0; i < dwNumComponents - 1; i++) {
  203. if (i ) {
  204. wcscat(pszParent, L"/");
  205. }
  206. AppendComponent(pszParent, &(pObjectInfo->DisplayComponentArray[i]));
  207. }
  208. }
  209. break;
  210. case TRUE:
  211. for (i = 0; i < dwNumComponents - 1; i++) {
  212. wcscat(pszParent, L"/");
  213. AppendComponent(pszParent, &(pObjectInfo->DisplayComponentArray[i]));
  214. }
  215. break;
  216. }
  217. //
  218. // And the common name is the last component
  219. //
  220. pszComponent = pObjectInfo->DisplayComponentArray[dwNumComponents - 1].szComponent;
  221. pszValue = pObjectInfo->DisplayComponentArray[dwNumComponents - 1].szValue;
  222. if (pszComponent && pszValue) {
  223. wsprintf(pszCommonName, L"%s=%s",pszComponent, pszValue);
  224. }else if (pszComponent){
  225. wsprintf(pszCommonName, L"%s", pszComponent);
  226. }else {
  227. //
  228. // Error - we should never hit this case!!
  229. //
  230. }
  231. break;
  232. }
  233. }
  234. RRETURN(hr);
  235. }
  236. HRESULT
  237. AppendComponent(
  238. LPWSTR pszADsPathName,
  239. PCOMPONENT pComponent
  240. )
  241. {
  242. HRESULT hr = S_OK;
  243. LPWSTR pszComponent = NULL, pszValue = NULL;
  244. pszComponent = pComponent->szComponent;
  245. pszValue = pComponent->szValue;
  246. if (pszComponent && pszValue) {
  247. wcscat(
  248. pszADsPathName,
  249. pComponent->szComponent
  250. );
  251. wcscat(pszADsPathName,L"=");
  252. wcscat(
  253. pszADsPathName,
  254. pComponent->szValue
  255. );
  256. }else if (pszComponent){
  257. wcscat(
  258. pszADsPathName,
  259. pComponent->szComponent
  260. );
  261. }else {
  262. //
  263. // Error - we should never hit this case!!
  264. //
  265. }
  266. RRETURN(S_OK);
  267. }
  268. HRESULT
  269. ComputeAllocateParentCommonNameSize(
  270. POBJECTINFO pObjectInfo,
  271. LPWSTR * ppszParent,
  272. LPWSTR * ppszCommonName
  273. )
  274. {
  275. HRESULT hr = S_OK;
  276. LPWSTR pszParent = NULL;
  277. LPWSTR pszCommonName = NULL;
  278. DWORD dwPathSz = 0;
  279. WCHAR szPort[32];
  280. DWORD i = 0;
  281. //
  282. // the ADsPath of the Parent is atleast as long as the standard
  283. // pathname
  284. //
  285. //
  286. // the CommonName is atleast as long as the parent name
  287. //
  288. dwPathSz += STRING_LENGTH(pObjectInfo->NamespaceName);
  289. dwPathSz += STRING_LENGTH(pObjectInfo->ProviderName);
  290. dwPathSz += 2;
  291. dwPathSz += STRING_LENGTH(pObjectInfo->DisplayTreeName);
  292. //
  293. // If an explicit port has been specified
  294. //
  295. if ( IS_EXPLICIT_PORT(pObjectInfo->PortNumber) ) {
  296. wsprintf(szPort, L":%d", pObjectInfo->PortNumber);
  297. dwPathSz += wcslen(szPort);
  298. }
  299. dwPathSz += 1;
  300. for (i = 0; i < pObjectInfo->NumComponents; i++) {
  301. dwPathSz += STRING_LENGTH(pObjectInfo->DisplayComponentArray[i].szComponent);
  302. dwPathSz += 1;
  303. dwPathSz += STRING_LENGTH(pObjectInfo->DisplayComponentArray[i].szValue);
  304. dwPathSz += 1;
  305. }
  306. dwPathSz += 1;
  307. pszCommonName = (LPWSTR)AllocADsMem((dwPathSz)*sizeof(WCHAR));
  308. if (!pszCommonName) {
  309. hr = E_OUTOFMEMORY;
  310. BAIL_ON_FAILURE(hr);
  311. }
  312. pszParent = (LPWSTR)AllocADsMem((dwPathSz)*sizeof(WCHAR));
  313. if (!pszParent) {
  314. hr = E_OUTOFMEMORY;
  315. BAIL_ON_FAILURE(hr);
  316. }
  317. *ppszCommonName = pszCommonName;
  318. *ppszParent = pszParent;
  319. RRETURN(hr);
  320. error:
  321. if (pszCommonName ) {
  322. FreeADsMem(pszCommonName);
  323. }
  324. if (pszParent) {
  325. FreeADsMem(pszParent);
  326. }
  327. RRETURN(hr);
  328. }
  329. HRESULT
  330. BuildADsPathFromParent(
  331. LPWSTR Parent,
  332. LPWSTR Name,
  333. LPWSTR *ppszADsPath
  334. )
  335. {
  336. OBJECTINFO ObjectInfo;
  337. POBJECTINFO pParentObjectInfo = &ObjectInfo;
  338. HRESULT hr = S_OK;
  339. LPWSTR pszCommonName = NULL;
  340. LPWSTR pszADsPath = NULL;
  341. memset(pParentObjectInfo, 0, sizeof(OBJECTINFO));
  342. hr = ADsObject(Parent, pParentObjectInfo);
  343. BAIL_ON_FAILURE(hr);
  344. // The length of the pszADsPath is the total path + name + 1;
  345. //
  346. // The length of pszParent or pszCommon is definitely less than the
  347. // length of the total buffer.
  348. //
  349. // The Name part may be expanded to include escaping characters. In
  350. // the worst case, the number of characters will double. Extra 2+1 is for
  351. // the "//" and a NULL
  352. //
  353. pszADsPath = (LPWSTR) AllocADsMem( (_tcslen(Parent) + (_tcslen(Name)*2) + 2 + 1) * sizeof(TCHAR));
  354. if (!pszADsPath) {
  355. hr = E_OUTOFMEMORY;
  356. BAIL_ON_FAILURE(hr);
  357. }
  358. hr = BuildADsPathFromParentObjectInfo(
  359. pParentObjectInfo,
  360. Name,
  361. pszADsPath
  362. );
  363. BAIL_ON_FAILURE(hr);
  364. *ppszADsPath = pszADsPath;
  365. cleanup:
  366. if (pParentObjectInfo) {
  367. FreeObjectInfo( pParentObjectInfo );
  368. }
  369. RRETURN(hr);
  370. error:
  371. if (pszADsPath) {
  372. FreeADsMem(pszADsPath);
  373. }
  374. goto cleanup;
  375. }
  376. HRESULT
  377. BuildADsPathFromParentObjectInfo(
  378. POBJECTINFO pParentObjectInfo,
  379. LPWSTR pszName,
  380. LPWSTR pszADsPath
  381. )
  382. {
  383. DWORD i = 0;
  384. DWORD dwNumComponents = 0;
  385. HRESULT hr = S_OK;
  386. LPWSTR pszDisplayName = NULL;
  387. //
  388. // Get the display name for the name; The display name will have the proper
  389. // escaping for characters that have special meaning in an ADsPath like
  390. // '/' etc.
  391. //
  392. hr = GetDisplayName(
  393. pszName,
  394. &pszDisplayName
  395. );
  396. BAIL_ON_FAILURE(hr);
  397. dwNumComponents = pParentObjectInfo->NumComponents;
  398. if (!dwNumComponents && !pParentObjectInfo->DisplayTreeName) {
  399. //
  400. // Should never happen --- ADs is the root of the tree,
  401. // and has no parent
  402. //
  403. ADsAssert(_wcsicmp(pszDisplayName, L"ADs:") != 0);
  404. if (!_wcsicmp(pParentObjectInfo->NamespaceName, L"ADs")) {
  405. //
  406. // In this one particular case we take in LDAP: as the Name
  407. // or GC: as the name
  408. //
  409. //
  410. // Do not add another : - so bogus!! Krishna
  411. //
  412. wsprintf(pszADsPath, L"%s", pszDisplayName);
  413. }else {
  414. //
  415. // There are no CNs in this pathname and
  416. // no tree name specified. This is the
  417. // namespace object
  418. //
  419. // Its pszName is a TreeName and we will concatenate
  420. // the treename with a slash slash
  421. //
  422. wsprintf(pszADsPath,
  423. L"%s://%s",
  424. pParentObjectInfo->NamespaceName,
  425. pszDisplayName
  426. );
  427. }
  428. hr = S_OK;
  429. } else if (!dwNumComponents && pParentObjectInfo->DisplayTreeName) {
  430. //
  431. // There are no CNs in this pathname and a tree
  432. // name has been specified.
  433. //
  434. if (IS_EXPLICIT_PORT(pParentObjectInfo->PortNumber) ) {
  435. wsprintf(
  436. pszADsPath,
  437. L"%s://%s:%d/%s",
  438. pParentObjectInfo->NamespaceName,
  439. pParentObjectInfo->DisplayTreeName,
  440. pParentObjectInfo->PortNumber,
  441. pszDisplayName
  442. );
  443. }
  444. else {
  445. wsprintf(
  446. pszADsPath,
  447. L"%s://%s/%s",
  448. pParentObjectInfo->NamespaceName,
  449. pParentObjectInfo->DisplayTreeName,
  450. pszDisplayName
  451. );
  452. }
  453. hr = S_OK;
  454. }else {
  455. //
  456. // There are one or more CNs, a tree name has been
  457. // specified. In the worst case the parent is the
  458. // root object. In the best case a long CN.
  459. //
  460. switch (pParentObjectInfo->dwServerPresent) {
  461. case TRUE:
  462. if ( IS_EXPLICIT_PORT(pParentObjectInfo->PortNumber) ) {
  463. wsprintf(
  464. pszADsPath, L"%s://%s:%d",
  465. pParentObjectInfo->NamespaceName,
  466. pParentObjectInfo->DisplayTreeName,
  467. pParentObjectInfo->PortNumber
  468. );
  469. }
  470. else {
  471. wsprintf(
  472. pszADsPath, L"%s://%s",
  473. pParentObjectInfo->NamespaceName,
  474. pParentObjectInfo->DisplayTreeName
  475. );
  476. }
  477. break;
  478. case FALSE:
  479. wsprintf(
  480. pszADsPath, L"%s://",
  481. pParentObjectInfo->NamespaceName
  482. );
  483. }
  484. switch (pParentObjectInfo->dwPathType) {
  485. case PATHTYPE_WINDOWS:
  486. switch (pParentObjectInfo->dwServerPresent) {
  487. case TRUE:
  488. for (i = 0; i < dwNumComponents; i++) {
  489. wcscat(pszADsPath, L"/");
  490. AppendComponent(pszADsPath, &(pParentObjectInfo->DisplayComponentArray[i]));
  491. }
  492. wcscat(pszADsPath, L"/");
  493. wcscat(pszADsPath, pszDisplayName);
  494. hr = S_OK;
  495. break;
  496. case FALSE:
  497. for (i = 0; i < dwNumComponents; i++) {
  498. if (i ) {
  499. wcscat(pszADsPath, L"/");
  500. }
  501. AppendComponent(pszADsPath, &(pParentObjectInfo->DisplayComponentArray[i]));
  502. }
  503. wcscat(pszADsPath, L"/");
  504. wcscat(pszADsPath, pszDisplayName);
  505. hr = S_OK;
  506. break;
  507. }
  508. break;
  509. case PATHTYPE_X500:
  510. default:
  511. switch (pParentObjectInfo->dwServerPresent) {
  512. case TRUE:
  513. wcscat(pszADsPath, L"/");
  514. break;
  515. case FALSE:
  516. break;
  517. }
  518. wcscat(pszADsPath, pszDisplayName);
  519. wcscat(pszADsPath, L",");
  520. for (i = 0; i < dwNumComponents; i++) {
  521. AppendComponent(pszADsPath, &(pParentObjectInfo->DisplayComponentArray[i]));
  522. if (i < (dwNumComponents - 1)) {
  523. wcscat(pszADsPath, L",");
  524. }
  525. }
  526. hr = S_OK;
  527. break;
  528. }
  529. }
  530. error:
  531. if (pszDisplayName) {
  532. FreeADsMem(pszDisplayName);
  533. }
  534. RRETURN(hr);
  535. }
  536. HRESULT
  537. BuildLDAPPathFromADsPath(
  538. LPWSTR szADsPathName,
  539. LPWSTR *pszLDAPPathName
  540. )
  541. {
  542. OBJECTINFO ObjectInfo;
  543. POBJECTINFO pObjectInfo = &ObjectInfo;
  544. DWORD i = 0;
  545. DWORD dwNumComponents = 0;
  546. HRESULT hr = S_OK;
  547. LPWSTR szLDAPPathName = NULL;
  548. *pszLDAPPathName = NULL;
  549. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  550. hr = ADsObject(szADsPathName, pObjectInfo);
  551. BAIL_ON_FAILURE(hr);
  552. dwNumComponents = pObjectInfo->NumComponents;
  553. //
  554. // Assumption LDAPPath is always less than the ADsPath
  555. //
  556. szLDAPPathName = AllocADsStr(szADsPathName);
  557. if (!szLDAPPathName) {
  558. hr = E_OUTOFMEMORY;
  559. BAIL_ON_FAILURE(hr);
  560. }
  561. if (!pObjectInfo->TreeName) {
  562. //
  563. // At the very minimum, we need a treename
  564. //
  565. hr = E_FAIL;
  566. BAIL_ON_FAILURE(hr);
  567. }else if (pObjectInfo->TreeName && !dwNumComponents){
  568. _tcscpy(szLDAPPathName, TEXT("\\\\"));
  569. _tcscat(szLDAPPathName, pObjectInfo->TreeName);
  570. }else if (pObjectInfo->TreeName && dwNumComponents){
  571. _tcscpy(szLDAPPathName, TEXT("\\\\"));
  572. _tcscat(szLDAPPathName, pObjectInfo->TreeName);
  573. _tcscat(szLDAPPathName, TEXT("\\"));
  574. switch (pObjectInfo->dwPathType) {
  575. case PATHTYPE_X500:
  576. default:
  577. for (i = 0; i < dwNumComponents; i++) {
  578. AppendComponent(
  579. szLDAPPathName,
  580. &(pObjectInfo->ComponentArray[i])
  581. );
  582. if (i < (dwNumComponents - 1)){
  583. _tcscat(szLDAPPathName, TEXT(","));
  584. }
  585. }
  586. break;
  587. case PATHTYPE_WINDOWS:
  588. for (i = dwNumComponents; i > 0; i--) {
  589. AppendComponent(
  590. szLDAPPathName,
  591. &(pObjectInfo->ComponentArray[i-1])
  592. );
  593. if ((i - 1) > 0){
  594. _tcscat(szLDAPPathName, TEXT(","));
  595. }
  596. }
  597. break;
  598. }
  599. }
  600. *pszLDAPPathName = szLDAPPathName;
  601. error:
  602. FreeObjectInfo( &ObjectInfo );
  603. RRETURN(hr);
  604. }
  605. HRESULT
  606. BuildADsPathFromLDAPPath(
  607. LPWSTR szADsPathContext,
  608. LPWSTR szTargetLdapDN,
  609. LPWSTR * ppszADsPathName
  610. )
  611. {
  612. LPWSTR pszADsPathName = NULL;
  613. PKEYDATA pKeyData = NULL;
  614. DWORD dwCount = 0, dwLen = 0;
  615. DWORD i = 0;
  616. int cHostNameLen;
  617. HRESULT hr;
  618. LPWSTR pszHostName = NULL, pszTemp = NULL;
  619. LPWSTR pszLDAPServer = NULL;
  620. LPWSTR pszLDAPDn = NULL;
  621. WCHAR szPort[32];
  622. DWORD dwPortNumber = 0;
  623. OBJECTINFO ObjectInfo, ObjectInfo2;
  624. POBJECTINFO pObjectInfo = &ObjectInfo;
  625. POBJECTINFO pObjectInfo2 = &ObjectInfo2;
  626. LPWSTR pszDisplayDN = NULL;
  627. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  628. memset(pObjectInfo2, 0, sizeof(OBJECTINFO));
  629. if (!szADsPathContext || !szTargetLdapDN) {
  630. RRETURN(E_FAIL);
  631. }
  632. hr = GetDisplayName(
  633. szTargetLdapDN,
  634. &pszDisplayDN
  635. );
  636. BAIL_ON_FAILURE(hr);
  637. if (!pszDisplayDN) {
  638. BAIL_ON_FAILURE(hr = E_FAIL);
  639. }
  640. *ppszADsPathName = NULL;
  641. hr = ADsObject(szADsPathContext, pObjectInfo);
  642. BAIL_ON_FAILURE(hr);
  643. hr = BuildLDAPPathFromADsPath2(
  644. szADsPathContext,
  645. &pszLDAPServer,
  646. &pszLDAPDn,
  647. &dwPortNumber
  648. );
  649. BAIL_ON_FAILURE(hr);
  650. dwLen = STRING_LENGTH(pObjectInfo->NamespaceName) +
  651. STRING_LENGTH(pszLDAPServer) +
  652. STRING_LENGTH(pszDisplayDN) +
  653. STRING_LENGTH(L"://") +
  654. STRING_LENGTH(L"/") +
  655. 1;
  656. if (IS_EXPLICIT_PORT(dwPortNumber) ) {
  657. wsprintf(szPort, L":%d", dwPortNumber);
  658. dwLen += wcslen(szPort);
  659. }
  660. pszADsPathName = (LPWSTR) AllocADsMem( dwLen * sizeof(WCHAR) );
  661. pszTemp = (LPWSTR) AllocADsMem( dwLen * sizeof(WCHAR) );
  662. if(!pszADsPathName) {
  663. hr = E_OUTOFMEMORY;
  664. goto error;
  665. }
  666. switch (pObjectInfo->dwPathType) {
  667. case PATHTYPE_WINDOWS:
  668. //
  669. // Simplistic way to do this is to create the X500 based name and then
  670. // reparse it to generate the Windows style name
  671. //
  672. switch (pObjectInfo->dwServerPresent) {
  673. case TRUE:
  674. wsprintf(pszADsPathName,L"%s://", pObjectInfo->NamespaceName);
  675. wcscat(pszADsPathName, pszLDAPServer);
  676. if (IS_EXPLICIT_PORT(pObjectInfo->PortNumber) ) {
  677. wsprintf(szPort, L":%d", pObjectInfo->PortNumber);
  678. wcscat(pszADsPathName, szPort);
  679. }
  680. wcscat(pszADsPathName, L"/");
  681. wcscpy(pszTemp, pszADsPathName);
  682. wcscat(pszADsPathName, pszDisplayDN);
  683. break;
  684. case FALSE:
  685. wsprintf(pszADsPathName,L"%s://", pObjectInfo->NamespaceName);
  686. wcscpy(pszTemp, pszADsPathName);
  687. wcscat(pszADsPathName, pszDisplayDN);
  688. break;
  689. }
  690. hr = ADsObject(pszADsPathName, pObjectInfo2);
  691. BAIL_ON_FAILURE(hr);
  692. wcscpy (pszADsPathName, pszTemp);
  693. for (i = pObjectInfo2->NumComponents; i > 0; i--) {
  694. AppendComponent(
  695. pszADsPathName,
  696. &(pObjectInfo2->DisplayComponentArray[i-1])
  697. );
  698. if ((i - 1) > 0){
  699. _tcscat(pszADsPathName, TEXT("/"));
  700. }
  701. }
  702. break;
  703. case PATHTYPE_X500:
  704. default:
  705. switch (pObjectInfo->dwServerPresent) {
  706. case TRUE:
  707. wsprintf(pszADsPathName,L"%s://", pObjectInfo->NamespaceName);
  708. wcscat(pszADsPathName, pszLDAPServer);
  709. if (IS_EXPLICIT_PORT(pObjectInfo->PortNumber) ) {
  710. wsprintf(szPort, L":%d", pObjectInfo->PortNumber);
  711. wcscat(pszADsPathName, szPort);
  712. }
  713. wcscat(pszADsPathName, L"/");
  714. wcscat(pszADsPathName, pszDisplayDN);
  715. break;
  716. case FALSE:
  717. wsprintf(pszADsPathName,L"%s://", pObjectInfo->NamespaceName);
  718. wcscat(pszADsPathName, pszDisplayDN);
  719. break;
  720. }
  721. break;
  722. }
  723. *ppszADsPathName = pszADsPathName;
  724. error:
  725. if (pObjectInfo) {
  726. FreeObjectInfo(pObjectInfo);
  727. }
  728. if (pObjectInfo2) {
  729. FreeObjectInfo(pObjectInfo2);
  730. }
  731. if (pszTemp) {
  732. FreeADsMem(pszTemp);
  733. }
  734. if (pszLDAPServer) {
  735. FreeADsStr(pszLDAPServer);
  736. }
  737. if (pszLDAPDn) {
  738. FreeADsStr(pszLDAPDn);
  739. }
  740. if (pszDisplayDN) {
  741. FreeADsMem(pszDisplayDN);
  742. }
  743. RRETURN(hr);
  744. }
  745. PKEYDATA
  746. CreateTokenList(
  747. LPWSTR pKeyData,
  748. WCHAR ch
  749. )
  750. {
  751. DWORD cTokens;
  752. DWORD cb;
  753. PKEYDATA pResult;
  754. LPWSTR pDest;
  755. LPWSTR psz = pKeyData;
  756. LPWSTR *ppToken;
  757. WCHAR szTokenList[MAX_PATH];
  758. if (!psz || !*psz)
  759. return NULL;
  760. _stprintf(szTokenList, TEXT("%c"), ch);
  761. cTokens=1;
  762. // Scan through the string looking for commas,
  763. // ensuring that each is followed by a non-NULL character:
  764. while ((psz = wcschr(psz, ch)) && psz[1]) {
  765. cTokens++;
  766. psz++;
  767. }
  768. cb = sizeof(KEYDATA) + (cTokens-1) * sizeof(LPWSTR) +
  769. wcslen(pKeyData)*sizeof(WCHAR) + sizeof(WCHAR);
  770. if (!(pResult = (PKEYDATA)AllocADsMem(cb)))
  771. return NULL;
  772. // Initialise pDest to point beyond the token pointers:
  773. pDest = (LPWSTR)((LPBYTE)pResult + sizeof(KEYDATA) +
  774. (cTokens-1) * sizeof(LPWSTR));
  775. // Then copy the key data buffer there:
  776. wcscpy(pDest, pKeyData);
  777. ppToken = pResult->pTokens;
  778. // Remember, wcstok has the side effect of replacing the delimiter
  779. // by NULL, which is precisely what we want:
  780. psz = wcstok (pDest, szTokenList);
  781. while (psz) {
  782. *ppToken++ = psz;
  783. psz = wcstok (NULL, szTokenList);
  784. }
  785. pResult->cTokens = cTokens;
  786. return( pResult );
  787. }
  788. HRESULT
  789. BuildLDAPPathFromADsPath2(
  790. LPWSTR szADsPathName,
  791. LPWSTR *pszLDAPServer,
  792. LPWSTR *pszLDAPDn,
  793. DWORD * pdwPort
  794. )
  795. {
  796. OBJECTINFO ObjectInfo;
  797. POBJECTINFO pObjectInfo = &ObjectInfo;
  798. DWORD i = 0;
  799. DWORD dwNumComponents = 0;
  800. HRESULT hr = S_OK;
  801. LPWSTR szLDAPServer = NULL;
  802. LPWSTR szLDAPDn = NULL;
  803. DWORD dwPortNumber = 0;
  804. *pszLDAPServer = NULL;
  805. *pszLDAPDn = NULL;
  806. *pdwPort = 0;
  807. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  808. hr = ADsObject(szADsPathName, pObjectInfo);
  809. BAIL_ON_FAILURE(hr);
  810. dwPortNumber = pObjectInfo->PortNumber;
  811. dwNumComponents = pObjectInfo->NumComponents;
  812. //
  813. // Assumption LDAPPath is always less than the ADsPath
  814. //
  815. if (!pObjectInfo->TreeName && !dwNumComponents) {
  816. //
  817. // At the very minimum, we need a treename
  818. //
  819. hr = E_FAIL;
  820. BAIL_ON_FAILURE(hr);
  821. }
  822. if (pObjectInfo->TreeName){
  823. szLDAPServer = (LPWSTR)AllocADsMem((wcslen(szADsPathName) +1)*sizeof(WCHAR));
  824. if (!szLDAPServer) {
  825. hr = E_OUTOFMEMORY;
  826. BAIL_ON_FAILURE(hr);
  827. }
  828. _tcscat(szLDAPServer, pObjectInfo->TreeName);
  829. }
  830. if (dwNumComponents){
  831. szLDAPDn = (LPWSTR)AllocADsMem((wcslen(szADsPathName) +1)*sizeof(WCHAR));
  832. if (!szLDAPDn) {
  833. hr = E_OUTOFMEMORY;
  834. BAIL_ON_FAILURE(hr);
  835. }
  836. switch (pObjectInfo->dwPathType) {
  837. case PATHTYPE_X500:
  838. default:
  839. for (i = 0; i < dwNumComponents; i++) {
  840. AppendComponent(
  841. szLDAPDn,
  842. &(pObjectInfo->ComponentArray[i])
  843. );
  844. if (i < (dwNumComponents - 1)){
  845. _tcscat(szLDAPDn, TEXT(","));
  846. }
  847. }
  848. break;
  849. case PATHTYPE_WINDOWS:
  850. for (i = dwNumComponents; i > 0; i--) {
  851. AppendComponent(
  852. szLDAPDn,
  853. &(pObjectInfo->ComponentArray[i-1])
  854. );
  855. if ((i - 1) > 0){
  856. _tcscat(szLDAPDn, TEXT(","));
  857. }
  858. }
  859. break;
  860. }
  861. }
  862. if (szLDAPServer && *szLDAPServer) {
  863. *pszLDAPServer = szLDAPServer;
  864. }
  865. if (szLDAPDn && *szLDAPDn) {
  866. *pszLDAPDn = szLDAPDn;
  867. }
  868. *pdwPort = dwPortNumber;
  869. error:
  870. if (szLDAPServer && (*szLDAPServer == NULL)) {
  871. FreeADsMem(szLDAPServer);
  872. }
  873. if (szLDAPDn && (*szLDAPDn == NULL)) {
  874. FreeADsMem(szLDAPDn);
  875. }
  876. FreeObjectInfo( &ObjectInfo );
  877. RRETURN(hr);
  878. }
  879. HRESULT
  880. BuildADsPathFromLDAPPath2(
  881. DWORD dwServerPresent,
  882. LPWSTR szADsNamespace,
  883. LPWSTR szLDAPServer,
  884. DWORD dwPort,
  885. LPWSTR szLDAPDn,
  886. LPWSTR * ppszADsPathName
  887. )
  888. {
  889. LPWSTR pszADsPathName = NULL;
  890. HRESULT hr = S_OK;
  891. DWORD dwLen;
  892. WCHAR szPort[32];
  893. LPWSTR pszDisplayDN = NULL;
  894. hr = GetDisplayName(
  895. szLDAPDn,
  896. &pszDisplayDN
  897. );
  898. BAIL_ON_FAILURE(hr);
  899. dwLen = STRING_LENGTH(szADsNamespace) +
  900. STRING_LENGTH(szLDAPServer) +
  901. STRING_LENGTH(pszDisplayDN) +
  902. STRING_LENGTH(L"//") +
  903. STRING_LENGTH(L"/") +
  904. 1;
  905. if (IS_EXPLICIT_PORT(dwPort) ) {
  906. wsprintf(szPort, L":%d", dwPort);
  907. dwLen += STRING_LENGTH(szPort);
  908. }
  909. pszADsPathName = (LPWSTR) AllocADsMem( dwLen * sizeof(WCHAR) );
  910. if(!pszADsPathName) {
  911. hr = E_OUTOFMEMORY;
  912. goto error;
  913. }
  914. wsprintf(pszADsPathName,L"%s//", szADsNamespace);
  915. if (dwServerPresent) {
  916. if (szLDAPServer && *szLDAPServer) {
  917. wcscat(pszADsPathName, szLDAPServer);
  918. if (IS_EXPLICIT_PORT(dwPort) ) {
  919. wsprintf(szPort, L":%d", dwPort);
  920. wcscat(pszADsPathName, szPort);
  921. }
  922. }
  923. if (pszDisplayDN && *pszDisplayDN) {
  924. wcscat(pszADsPathName, L"/");
  925. wcscat(pszADsPathName, pszDisplayDN);
  926. }
  927. }else {
  928. if (pszDisplayDN && *pszDisplayDN) {
  929. wcscat(pszADsPathName, pszDisplayDN);
  930. }
  931. }
  932. *ppszADsPathName = pszADsPathName;
  933. error:
  934. if (pszDisplayDN) {
  935. FreeADsMem(pszDisplayDN);
  936. }
  937. RRETURN(hr);
  938. }
  939. HRESULT
  940. GetNamespaceFromADsPath(
  941. LPWSTR szADsPath,
  942. LPWSTR pszNamespace
  943. )
  944. {
  945. LPWSTR pszTemp;
  946. // Get the namespace name
  947. pszTemp = _tcschr( szADsPath, TEXT(':'));
  948. if (!pszTemp) {
  949. RRETURN(E_FAIL);
  950. }
  951. _tcsncpy (pszNamespace, szADsPath, (int)(pszTemp - szADsPath));
  952. pszNamespace[pszTemp - szADsPath] = L'\0';
  953. RRETURN(S_OK);
  954. }
  955. //
  956. // Change the separator of a DN from '\' to '/' so that it can be used in
  957. // an ADsPath
  958. HRESULT
  959. ChangeSeparator(
  960. LPWSTR pszDN
  961. )
  962. {
  963. LPWSTR ptr;
  964. if (pszDN) {
  965. while (ptr = wcschr(pszDN, '\\')) {
  966. *ptr = '/';
  967. }
  968. }
  969. return (S_OK);
  970. }