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.

1370 lines
31 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. if(!pszADsPathName)
  662. {
  663. hr = E_OUTOFMEMORY;
  664. goto error;
  665. }
  666. pszTemp = (LPWSTR) AllocADsMem( dwLen * sizeof(WCHAR) );
  667. if(!pszTemp) {
  668. if(pszADsPathName)
  669. {
  670. FreeADsMem(pszADsPathName);
  671. }
  672. hr = E_OUTOFMEMORY;
  673. goto error;
  674. }
  675. switch (pObjectInfo->dwPathType) {
  676. case PATHTYPE_WINDOWS:
  677. //
  678. // Simplistic way to do this is to create the X500 based name and then
  679. // reparse it to generate the Windows style name
  680. //
  681. switch (pObjectInfo->dwServerPresent) {
  682. case TRUE:
  683. wsprintf(pszADsPathName,L"%s://", pObjectInfo->NamespaceName);
  684. wcscat(pszADsPathName, pszLDAPServer);
  685. if (IS_EXPLICIT_PORT(pObjectInfo->PortNumber) ) {
  686. wsprintf(szPort, L":%d", pObjectInfo->PortNumber);
  687. wcscat(pszADsPathName, szPort);
  688. }
  689. wcscat(pszADsPathName, L"/");
  690. wcscpy(pszTemp, pszADsPathName);
  691. wcscat(pszADsPathName, pszDisplayDN);
  692. break;
  693. case FALSE:
  694. wsprintf(pszADsPathName,L"%s://", pObjectInfo->NamespaceName);
  695. wcscpy(pszTemp, pszADsPathName);
  696. wcscat(pszADsPathName, pszDisplayDN);
  697. break;
  698. }
  699. hr = ADsObject(pszADsPathName, pObjectInfo2);
  700. BAIL_ON_FAILURE(hr);
  701. wcscpy (pszADsPathName, pszTemp);
  702. for (i = pObjectInfo2->NumComponents; i > 0; i--) {
  703. AppendComponent(
  704. pszADsPathName,
  705. &(pObjectInfo2->DisplayComponentArray[i-1])
  706. );
  707. if ((i - 1) > 0){
  708. _tcscat(pszADsPathName, TEXT("/"));
  709. }
  710. }
  711. break;
  712. case PATHTYPE_X500:
  713. default:
  714. switch (pObjectInfo->dwServerPresent) {
  715. case TRUE:
  716. wsprintf(pszADsPathName,L"%s://", pObjectInfo->NamespaceName);
  717. wcscat(pszADsPathName, pszLDAPServer);
  718. if (IS_EXPLICIT_PORT(pObjectInfo->PortNumber) ) {
  719. wsprintf(szPort, L":%d", pObjectInfo->PortNumber);
  720. wcscat(pszADsPathName, szPort);
  721. }
  722. wcscat(pszADsPathName, L"/");
  723. wcscat(pszADsPathName, pszDisplayDN);
  724. break;
  725. case FALSE:
  726. wsprintf(pszADsPathName,L"%s://", pObjectInfo->NamespaceName);
  727. wcscat(pszADsPathName, pszDisplayDN);
  728. break;
  729. }
  730. break;
  731. }
  732. *ppszADsPathName = pszADsPathName;
  733. error:
  734. if (pObjectInfo) {
  735. FreeObjectInfo(pObjectInfo);
  736. }
  737. if (pObjectInfo2) {
  738. FreeObjectInfo(pObjectInfo2);
  739. }
  740. if (pszTemp) {
  741. FreeADsMem(pszTemp);
  742. }
  743. if (pszLDAPServer) {
  744. FreeADsStr(pszLDAPServer);
  745. }
  746. if (pszLDAPDn) {
  747. FreeADsStr(pszLDAPDn);
  748. }
  749. if (pszDisplayDN) {
  750. FreeADsMem(pszDisplayDN);
  751. }
  752. RRETURN(hr);
  753. }
  754. PKEYDATA
  755. CreateTokenList(
  756. LPWSTR pKeyData,
  757. WCHAR ch
  758. )
  759. {
  760. DWORD cTokens;
  761. DWORD cb;
  762. PKEYDATA pResult;
  763. LPWSTR pDest;
  764. LPWSTR psz = pKeyData;
  765. LPWSTR *ppToken;
  766. WCHAR szTokenList[MAX_PATH];
  767. if (!psz || !*psz)
  768. return NULL;
  769. _stprintf(szTokenList, TEXT("%c"), ch);
  770. cTokens=1;
  771. // Scan through the string looking for commas,
  772. // ensuring that each is followed by a non-NULL character:
  773. while ((psz = wcschr(psz, ch)) && psz[1]) {
  774. cTokens++;
  775. psz++;
  776. }
  777. cb = sizeof(KEYDATA) + (cTokens-1) * sizeof(LPWSTR) +
  778. wcslen(pKeyData)*sizeof(WCHAR) + sizeof(WCHAR);
  779. if (!(pResult = (PKEYDATA)AllocADsMem(cb)))
  780. return NULL;
  781. // Initialise pDest to point beyond the token pointers:
  782. pDest = (LPWSTR)((LPBYTE)pResult + sizeof(KEYDATA) +
  783. (cTokens-1) * sizeof(LPWSTR));
  784. // Then copy the key data buffer there:
  785. wcscpy(pDest, pKeyData);
  786. ppToken = pResult->pTokens;
  787. // Remember, wcstok has the side effect of replacing the delimiter
  788. // by NULL, which is precisely what we want:
  789. psz = wcstok (pDest, szTokenList);
  790. while (psz) {
  791. *ppToken++ = psz;
  792. psz = wcstok (NULL, szTokenList);
  793. }
  794. pResult->cTokens = cTokens;
  795. return( pResult );
  796. }
  797. HRESULT
  798. BuildLDAPPathFromADsPath2(
  799. LPWSTR szADsPathName,
  800. LPWSTR *pszLDAPServer,
  801. LPWSTR *pszLDAPDn,
  802. DWORD * pdwPort
  803. )
  804. {
  805. OBJECTINFO ObjectInfo;
  806. POBJECTINFO pObjectInfo = &ObjectInfo;
  807. DWORD i = 0;
  808. DWORD dwNumComponents = 0;
  809. HRESULT hr = S_OK;
  810. LPWSTR szLDAPServer = NULL;
  811. LPWSTR szLDAPDn = NULL;
  812. DWORD dwPortNumber = 0;
  813. *pszLDAPServer = NULL;
  814. *pszLDAPDn = NULL;
  815. *pdwPort = 0;
  816. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  817. hr = ADsObject(szADsPathName, pObjectInfo);
  818. BAIL_ON_FAILURE(hr);
  819. dwPortNumber = pObjectInfo->PortNumber;
  820. dwNumComponents = pObjectInfo->NumComponents;
  821. //
  822. // Assumption LDAPPath is always less than the ADsPath
  823. //
  824. if (!pObjectInfo->TreeName && !dwNumComponents) {
  825. //
  826. // At the very minimum, we need a treename
  827. //
  828. hr = E_FAIL;
  829. BAIL_ON_FAILURE(hr);
  830. }
  831. if (pObjectInfo->TreeName){
  832. szLDAPServer = (LPWSTR)AllocADsMem((wcslen(szADsPathName) +1)*sizeof(WCHAR));
  833. if (!szLDAPServer) {
  834. hr = E_OUTOFMEMORY;
  835. BAIL_ON_FAILURE(hr);
  836. }
  837. _tcscat(szLDAPServer, pObjectInfo->TreeName);
  838. }
  839. if (dwNumComponents){
  840. szLDAPDn = (LPWSTR)AllocADsMem((wcslen(szADsPathName) +1)*sizeof(WCHAR));
  841. if (!szLDAPDn) {
  842. hr = E_OUTOFMEMORY;
  843. BAIL_ON_FAILURE(hr);
  844. }
  845. switch (pObjectInfo->dwPathType) {
  846. case PATHTYPE_X500:
  847. default:
  848. for (i = 0; i < dwNumComponents; i++) {
  849. AppendComponent(
  850. szLDAPDn,
  851. &(pObjectInfo->ComponentArray[i])
  852. );
  853. if (i < (dwNumComponents - 1)){
  854. _tcscat(szLDAPDn, TEXT(","));
  855. }
  856. }
  857. break;
  858. case PATHTYPE_WINDOWS:
  859. for (i = dwNumComponents; i > 0; i--) {
  860. AppendComponent(
  861. szLDAPDn,
  862. &(pObjectInfo->ComponentArray[i-1])
  863. );
  864. if ((i - 1) > 0){
  865. _tcscat(szLDAPDn, TEXT(","));
  866. }
  867. }
  868. break;
  869. }
  870. }
  871. if (szLDAPServer && *szLDAPServer) {
  872. *pszLDAPServer = szLDAPServer;
  873. }
  874. if (szLDAPDn && *szLDAPDn) {
  875. *pszLDAPDn = szLDAPDn;
  876. }
  877. *pdwPort = dwPortNumber;
  878. error:
  879. if (szLDAPServer && (*szLDAPServer == NULL)) {
  880. FreeADsMem(szLDAPServer);
  881. }
  882. if (szLDAPDn && (*szLDAPDn == NULL)) {
  883. FreeADsMem(szLDAPDn);
  884. }
  885. FreeObjectInfo( &ObjectInfo );
  886. RRETURN(hr);
  887. }
  888. HRESULT
  889. BuildADsPathFromLDAPPath2(
  890. DWORD dwServerPresent,
  891. LPWSTR szADsNamespace,
  892. LPWSTR szLDAPServer,
  893. DWORD dwPort,
  894. LPWSTR szLDAPDn,
  895. LPWSTR * ppszADsPathName
  896. )
  897. {
  898. LPWSTR pszADsPathName = NULL;
  899. HRESULT hr = S_OK;
  900. DWORD dwLen;
  901. WCHAR szPort[32];
  902. LPWSTR pszDisplayDN = NULL;
  903. hr = GetDisplayName(
  904. szLDAPDn,
  905. &pszDisplayDN
  906. );
  907. BAIL_ON_FAILURE(hr);
  908. dwLen = STRING_LENGTH(szADsNamespace) +
  909. STRING_LENGTH(szLDAPServer) +
  910. STRING_LENGTH(pszDisplayDN) +
  911. STRING_LENGTH(L"//") +
  912. STRING_LENGTH(L"/") +
  913. 1;
  914. if (IS_EXPLICIT_PORT(dwPort) ) {
  915. wsprintf(szPort, L":%d", dwPort);
  916. dwLen += STRING_LENGTH(szPort);
  917. }
  918. pszADsPathName = (LPWSTR) AllocADsMem( dwLen * sizeof(WCHAR) );
  919. if(!pszADsPathName) {
  920. hr = E_OUTOFMEMORY;
  921. goto error;
  922. }
  923. wsprintf(pszADsPathName,L"%s//", szADsNamespace);
  924. if (dwServerPresent) {
  925. if (szLDAPServer && *szLDAPServer) {
  926. wcscat(pszADsPathName, szLDAPServer);
  927. if (IS_EXPLICIT_PORT(dwPort) ) {
  928. wsprintf(szPort, L":%d", dwPort);
  929. wcscat(pszADsPathName, szPort);
  930. }
  931. }
  932. if (pszDisplayDN && *pszDisplayDN) {
  933. wcscat(pszADsPathName, L"/");
  934. wcscat(pszADsPathName, pszDisplayDN);
  935. }
  936. }else {
  937. if (pszDisplayDN && *pszDisplayDN) {
  938. wcscat(pszADsPathName, pszDisplayDN);
  939. }
  940. }
  941. *ppszADsPathName = pszADsPathName;
  942. error:
  943. if (pszDisplayDN) {
  944. FreeADsMem(pszDisplayDN);
  945. }
  946. RRETURN(hr);
  947. }
  948. HRESULT
  949. GetNamespaceFromADsPath(
  950. LPWSTR szADsPath,
  951. LPWSTR pszNamespace
  952. )
  953. {
  954. LPWSTR pszTemp;
  955. // Get the namespace name
  956. pszTemp = _tcschr( szADsPath, TEXT(':'));
  957. if (!pszTemp) {
  958. RRETURN(E_FAIL);
  959. }
  960. _tcsncpy (pszNamespace, szADsPath, (int)(pszTemp - szADsPath));
  961. pszNamespace[pszTemp - szADsPath] = L'\0';
  962. RRETURN(S_OK);
  963. }
  964. //
  965. // Change the separator of a DN from '\' to '/' so that it can be used in
  966. // an ADsPath
  967. HRESULT
  968. ChangeSeparator(
  969. LPWSTR pszDN
  970. )
  971. {
  972. LPWSTR ptr;
  973. if (pszDN) {
  974. while (ptr = wcschr(pszDN, '\\')) {
  975. *ptr = '/';
  976. }
  977. }
  978. return (S_OK);
  979. }