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.

967 lines
24 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT Security
  4. // Copyright (C) Microsoft Corporation, 1997 - 1998
  5. //
  6. // File: dsctx.cpp
  7. //
  8. // Contents: Implementation of CDsObjectContext and NT Marta DS object
  9. // Functions
  10. //
  11. // History: 3-31-1999 kirtd Created
  12. //
  13. //----------------------------------------------------------------------------
  14. #include <aclpch.hxx>
  15. #pragma hdrstop
  16. #include <windows.h>
  17. #include <dsctx.h>
  18. //+---------------------------------------------------------------------------
  19. //
  20. // Member: CDsObjectContext::CDsObjectContext, public
  21. //
  22. // Synopsis: Constructor
  23. //
  24. //----------------------------------------------------------------------------
  25. CDsObjectContext::CDsObjectContext ()
  26. {
  27. m_cRefs = 1;
  28. memset( &m_LdapUrlComponents, 0, sizeof( m_LdapUrlComponents ) );
  29. m_pBinding = NULL;
  30. }
  31. //+---------------------------------------------------------------------------
  32. //
  33. // Member: CDsObjectContext::~CDsObjectContext, public
  34. //
  35. // Synopsis: Destructor
  36. //
  37. //----------------------------------------------------------------------------
  38. CDsObjectContext::~CDsObjectContext ()
  39. {
  40. LdapFreeBindings( m_pBinding );
  41. LdapFreeUrlComponents( &m_LdapUrlComponents );
  42. assert( m_cRefs == 0 );
  43. }
  44. //+---------------------------------------------------------------------------
  45. //
  46. // Member: CDsObjectContext::InitializeByName, public
  47. //
  48. // Synopsis: initialize the context given the name of the lanman share
  49. //
  50. //----------------------------------------------------------------------------
  51. DWORD
  52. CDsObjectContext::InitializeByName (LPCWSTR pObjectName, ACCESS_MASK AccessMask)
  53. {
  54. DWORD Result = ERROR_SUCCESS;
  55. LPWSTR pwszName = NULL;
  56. ULONG len = wcslen( pObjectName );
  57. ULONG i, j;
  58. if ( _wcsnicmp( pObjectName, LDAP_SCHEME_U, wcslen( LDAP_SCHEME_U ) ) != 0 )
  59. {
  60. pwszName = new WCHAR [ len + wcslen( LDAP_SCHEME_UC ) + 2 ];
  61. if ( pwszName != NULL )
  62. {
  63. wcscpy( pwszName, LDAP_SCHEME_UC );
  64. wcscat( pwszName, L"/" );
  65. wcscat( pwszName, pObjectName );
  66. }
  67. else
  68. {
  69. Result = ERROR_OUTOFMEMORY;
  70. }
  71. }
  72. else
  73. {
  74. pwszName = new WCHAR [ len + 1 ];
  75. if ( pwszName != NULL )
  76. {
  77. wcscpy( pwszName, pObjectName );
  78. }
  79. else
  80. {
  81. Result = ERROR_OUTOFMEMORY;
  82. }
  83. }
  84. if ( Result == ERROR_SUCCESS )
  85. {
  86. for (i = j = 0; i <= len; i++, j++)
  87. {
  88. if (L'\\' == pwszName[i])
  89. {
  90. if (L'/' != pwszName[i+1])
  91. {
  92. pwszName[j++] = pwszName[i++];
  93. }
  94. else
  95. {
  96. i++;
  97. }
  98. }
  99. pwszName[j] = pwszName[i];
  100. }
  101. }
  102. if ( Result == ERROR_SUCCESS )
  103. {
  104. if ( LdapCrackUrl( pwszName, &m_LdapUrlComponents ) == FALSE )
  105. {
  106. Result = GetLastError();
  107. }
  108. }
  109. if ( Result == ERROR_SUCCESS )
  110. {
  111. if ( LdapGetBindings(
  112. m_LdapUrlComponents.pwszHost,
  113. m_LdapUrlComponents.Port,
  114. 0,
  115. 0,
  116. &m_pBinding
  117. ) == FALSE )
  118. {
  119. Result = GetLastError();
  120. }
  121. }
  122. if ( pwszName != pObjectName )
  123. {
  124. delete pwszName;
  125. }
  126. return( Result );
  127. }
  128. //+---------------------------------------------------------------------------
  129. //
  130. // Member: CDsObjectContext::AddRef, public
  131. //
  132. // Synopsis: add a reference to the context
  133. //
  134. //----------------------------------------------------------------------------
  135. DWORD
  136. CDsObjectContext::AddRef ()
  137. {
  138. m_cRefs += 1;
  139. return( m_cRefs );
  140. }
  141. //+---------------------------------------------------------------------------
  142. //
  143. // Member: CDsObjectContext::Release, public
  144. //
  145. // Synopsis: release a reference to the context
  146. //
  147. //----------------------------------------------------------------------------
  148. DWORD
  149. CDsObjectContext::Release ()
  150. {
  151. m_cRefs -= 1;
  152. if ( m_cRefs == 0 )
  153. {
  154. delete this;
  155. return( 0 );
  156. }
  157. return( m_cRefs );
  158. }
  159. //+---------------------------------------------------------------------------
  160. //
  161. // Member: CDsObjectContext::GetDsObjectProperties, public
  162. //
  163. // Synopsis: get properties about the context
  164. //
  165. //----------------------------------------------------------------------------
  166. DWORD
  167. CDsObjectContext::GetDsObjectProperties (
  168. PMARTA_OBJECT_PROPERTIES pObjectProperties
  169. )
  170. {
  171. if ( pObjectProperties->cbSize < sizeof( MARTA_OBJECT_PROPERTIES ) )
  172. {
  173. return( ERROR_INVALID_PARAMETER );
  174. }
  175. assert( pObjectProperties->dwFlags == 0 );
  176. return( ERROR_SUCCESS );
  177. }
  178. //+---------------------------------------------------------------------------
  179. //
  180. // Member: CDsObjectContext::GetDsObjectRights, public
  181. //
  182. // Synopsis: get the DsObject security descriptor
  183. //
  184. //----------------------------------------------------------------------------
  185. DWORD
  186. CDsObjectContext::GetDsObjectRights (
  187. SECURITY_INFORMATION SecurityInfo,
  188. PSECURITY_DESCRIPTOR* ppSecurityDescriptor
  189. )
  190. {
  191. DWORD Result;
  192. Result = MartaReadDSObjSecDesc(
  193. m_pBinding,
  194. m_LdapUrlComponents.pwszDN,
  195. SecurityInfo,
  196. ppSecurityDescriptor
  197. );
  198. return( Result );
  199. }
  200. //+---------------------------------------------------------------------------
  201. //
  202. // Member: CDsObjectContext::SetDsObjectRights, public
  203. //
  204. // Synopsis: set the window security descriptor
  205. //
  206. //----------------------------------------------------------------------------
  207. DWORD
  208. CDsObjectContext::SetDsObjectRights (
  209. SECURITY_INFORMATION SecurityInfo,
  210. PSECURITY_DESCRIPTOR pSecurityDescriptor
  211. )
  212. {
  213. DWORD Result;
  214. PISECURITY_DESCRIPTOR pisd = NULL;
  215. DWORD cb = 0;
  216. PSECURITY_DESCRIPTOR psd = NULL;
  217. pisd = (PISECURITY_DESCRIPTOR)pSecurityDescriptor;
  218. if ( pisd->Control & SE_SELF_RELATIVE )
  219. {
  220. cb = GetSecurityDescriptorLength( pSecurityDescriptor );
  221. psd = pSecurityDescriptor;
  222. }
  223. else
  224. {
  225. if ( MakeSelfRelativeSD(
  226. pSecurityDescriptor,
  227. NULL,
  228. &cb
  229. ) == FALSE )
  230. {
  231. if ( cb > 0 )
  232. {
  233. psd = new BYTE [ cb ];
  234. if ( psd != NULL )
  235. {
  236. if ( MakeSelfRelativeSD(
  237. pSecurityDescriptor,
  238. psd,
  239. &cb
  240. ) == FALSE )
  241. {
  242. delete psd;
  243. return( GetLastError() );
  244. }
  245. }
  246. else
  247. {
  248. return( ERROR_OUTOFMEMORY );
  249. }
  250. }
  251. else
  252. {
  253. return( GetLastError() );
  254. }
  255. }
  256. else
  257. {
  258. assert( FALSE && "Should not get here!" );
  259. return( ERROR_INVALID_PARAMETER );
  260. }
  261. }
  262. assert( psd != NULL );
  263. Result = MartaStampSD(
  264. m_LdapUrlComponents.pwszDN,
  265. cb,
  266. SecurityInfo,
  267. psd,
  268. m_pBinding
  269. );
  270. if ( psd != pSecurityDescriptor )
  271. {
  272. delete psd;
  273. }
  274. return( Result );
  275. }
  276. //+---------------------------------------------------------------------------
  277. //
  278. // Member: CDsObjectContext::GetDsObjectGuid, public
  279. //
  280. // Synopsis: get the object GUID
  281. //
  282. //----------------------------------------------------------------------------
  283. DWORD
  284. CDsObjectContext::GetDsObjectGuid (GUID* pGuid)
  285. {
  286. return( ERROR_INVALID_PARAMETER );
  287. }
  288. //
  289. // Functions from Ds.h which dispatch unto the CDsObjectContext class
  290. //
  291. DWORD
  292. MartaAddRefDsObjectContext(
  293. IN MARTA_CONTEXT Context
  294. )
  295. {
  296. return( ( (CDsObjectContext *)Context )->AddRef() );
  297. }
  298. DWORD
  299. MartaCloseDsObjectContext(
  300. IN MARTA_CONTEXT Context
  301. )
  302. {
  303. return( ( (CDsObjectContext *)Context )->Release() );
  304. }
  305. DWORD
  306. MartaGetDsObjectProperties(
  307. IN MARTA_CONTEXT Context,
  308. IN OUT PMARTA_OBJECT_PROPERTIES pProperties
  309. )
  310. {
  311. return( ( (CDsObjectContext *)Context )->GetDsObjectProperties( pProperties ) );
  312. }
  313. DWORD
  314. MartaGetDsObjectTypeProperties(
  315. IN OUT PMARTA_OBJECT_TYPE_PROPERTIES pProperties
  316. )
  317. {
  318. if ( pProperties->cbSize < sizeof( MARTA_OBJECT_TYPE_PROPERTIES ) )
  319. {
  320. return( ERROR_INVALID_PARAMETER );
  321. }
  322. assert( pProperties->dwFlags == 0 );
  323. pProperties->dwFlags = MARTA_OBJECT_TYPE_INHERITANCE_MODEL_PRESENT_FLAG;
  324. return( ERROR_SUCCESS );
  325. }
  326. DWORD
  327. MartaGetDsObjectRights(
  328. IN MARTA_CONTEXT Context,
  329. IN SECURITY_INFORMATION SecurityInfo,
  330. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
  331. )
  332. {
  333. return( ( (CDsObjectContext *)Context )->GetDsObjectRights(
  334. SecurityInfo,
  335. ppSecurityDescriptor
  336. ) );
  337. }
  338. DWORD
  339. MartaOpenDsObjectNamedObject(
  340. IN LPCWSTR pObjectName,
  341. IN ACCESS_MASK AccessMask,
  342. OUT PMARTA_CONTEXT pContext
  343. )
  344. {
  345. DWORD Result;
  346. CDsObjectContext* pDsObjectContext;
  347. pDsObjectContext = new CDsObjectContext;
  348. if ( pDsObjectContext == NULL )
  349. {
  350. return( ERROR_OUTOFMEMORY );
  351. }
  352. Result = pDsObjectContext->InitializeByName( pObjectName, AccessMask );
  353. if ( Result != ERROR_SUCCESS )
  354. {
  355. pDsObjectContext->Release();
  356. return( Result );
  357. }
  358. *pContext = pDsObjectContext;
  359. return( ERROR_SUCCESS );
  360. }
  361. DWORD
  362. MartaSetDsObjectRights(
  363. IN MARTA_CONTEXT Context,
  364. IN SECURITY_INFORMATION SecurityInfo,
  365. IN PSECURITY_DESCRIPTOR pSecurityDescriptor
  366. )
  367. {
  368. return( ( (CDsObjectContext *)Context )->SetDsObjectRights(
  369. SecurityInfo,
  370. pSecurityDescriptor
  371. ) );
  372. }
  373. DWORD
  374. MartaConvertDsObjectNameToGuid(
  375. IN LPCWSTR pObjectName,
  376. OUT GUID* pGuid
  377. )
  378. {
  379. DWORD Result = ERROR_SUCCESS;
  380. LPWSTR pwszName = NULL;
  381. LDAP_URL_COMPONENTS LdapUrlComponents;
  382. DS_NAME_RESULTW* pnameresult;
  383. HANDLE hDs = NULL;
  384. WCHAR GuidString[ MAX_PATH ];
  385. memset( &LdapUrlComponents, 0, sizeof( LdapUrlComponents ) );
  386. if ( _wcsnicmp( pObjectName, LDAP_SCHEME_U, wcslen( LDAP_SCHEME_U ) ) != 0 )
  387. {
  388. pwszName = new WCHAR [ wcslen( pObjectName ) +
  389. wcslen( LDAP_SCHEME_U ) + 2 ];
  390. if ( pwszName != NULL )
  391. {
  392. wcscpy( pwszName, LDAP_SCHEME_U );
  393. wcscat( pwszName, L"/" );
  394. wcscat( pwszName, pObjectName );
  395. }
  396. else
  397. {
  398. Result = ERROR_OUTOFMEMORY;
  399. }
  400. }
  401. else
  402. {
  403. pwszName = (LPWSTR)pObjectName;
  404. }
  405. if ( Result == ERROR_SUCCESS )
  406. {
  407. if ( LdapCrackUrl( pwszName, &LdapUrlComponents ) == FALSE )
  408. {
  409. Result = GetLastError();
  410. }
  411. }
  412. if ( Result == ERROR_SUCCESS )
  413. {
  414. Result = DsBindW( LdapUrlComponents.pwszHost, NULL, &hDs );
  415. }
  416. if ( Result == ERROR_SUCCESS )
  417. {
  418. Result = DsCrackNamesW(
  419. hDs,
  420. DS_NAME_NO_FLAGS,
  421. DS_FQDN_1779_NAME,
  422. DS_UNIQUE_ID_NAME,
  423. 1,
  424. &LdapUrlComponents.pwszDN,
  425. &pnameresult
  426. );
  427. }
  428. if ( Result == ERROR_SUCCESS )
  429. {
  430. if ( ( pnameresult->cItems > 0 ) &&
  431. ( pnameresult->rItems[0].status == ERROR_SUCCESS ) )
  432. {
  433. Result = IIDFromString( pnameresult->rItems[0].pName, pGuid );
  434. }
  435. else
  436. {
  437. Result = ERROR_INVALID_PARAMETER;
  438. }
  439. DsFreeNameResultW( pnameresult );
  440. }
  441. if ( hDs != NULL )
  442. {
  443. DsUnBindW( &hDs );
  444. }
  445. LdapFreeUrlComponents( &LdapUrlComponents );
  446. if ( pwszName != pObjectName )
  447. {
  448. delete pwszName;
  449. }
  450. return( Result );
  451. }
  452. DWORD
  453. MartaConvertGuidToDsName(
  454. IN GUID Guid,
  455. OUT LPWSTR * ppObjectName
  456. )
  457. {
  458. DWORD Result;
  459. HANDLE hDs = NULL;
  460. WCHAR GuidString[ MAX_PATH ];
  461. DS_NAME_RESULTW* pnameresult = NULL;
  462. LPWSTR pObjectName = NULL;
  463. if ( StringFromGUID2( Guid, GuidString, MAX_PATH ) == 0 )
  464. {
  465. return( ERROR_INVALID_PARAMETER );
  466. }
  467. Result = DsBindW( NULL, NULL, &hDs );
  468. if ( Result == ERROR_SUCCESS )
  469. {
  470. Result = DsCrackNamesW(
  471. hDs,
  472. DS_NAME_NO_FLAGS,
  473. DS_UNIQUE_ID_NAME,
  474. DS_FQDN_1779_NAME,
  475. 1,
  476. (LPCWSTR *)&GuidString,
  477. &pnameresult
  478. );
  479. }
  480. if ( Result == ERROR_SUCCESS )
  481. {
  482. if ( ( pnameresult->cItems > 0 ) &&
  483. ( pnameresult->rItems[0].status == ERROR_SUCCESS ) )
  484. {
  485. pObjectName = (LPWSTR)LocalAlloc(
  486. LPTR,
  487. ( wcslen( pnameresult->rItems[0].pName )
  488. + 1 ) * sizeof( WCHAR )
  489. );
  490. if ( pObjectName != NULL )
  491. {
  492. wcscpy( pObjectName, pnameresult->rItems[0].pName );
  493. *ppObjectName = pObjectName;
  494. }
  495. else
  496. {
  497. Result = ERROR_OUTOFMEMORY;
  498. }
  499. }
  500. else
  501. {
  502. Result = ERROR_INVALID_PARAMETER;
  503. }
  504. DsFreeNameResultW( pnameresult );
  505. }
  506. if ( hDs != NULL )
  507. {
  508. DsUnBindW( &hDs );
  509. }
  510. return( ERROR_SUCCESS );
  511. }
  512. //+---------------------------------------------------------------------------
  513. //
  514. // Function: MartaReadDSObjSecDesc
  515. //
  516. // Synopsis: Reads the security descriptor from the specied object via
  517. // the open ldap connection
  518. //
  519. // Arguments: [IN pLDAP] -- The open LDAP connection
  520. // [IN SeInfo] -- Parts of the security descriptor to
  521. // read.
  522. // [IN pwszDSObj] -- The DSObject to get the security
  523. // descriptor for
  524. // [OUT ppSD] -- Where the security descriptor is
  525. // returned
  526. //
  527. // Returns: ERROR_SUCCESS -- The object is reachable
  528. // ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
  529. //
  530. // Notes: The returned security descriptor must be freed with LocalFree
  531. //
  532. //----------------------------------------------------------------------------
  533. DWORD
  534. MartaReadDSObjSecDesc(IN PLDAP pLDAP,
  535. IN LPWSTR pwszObject,
  536. IN SECURITY_INFORMATION SeInfo,
  537. OUT PSECURITY_DESCRIPTOR *ppSD)
  538. {
  539. DWORD dwErr = ERROR_SUCCESS;
  540. PLDAPMessage pMessage = NULL;
  541. LPWSTR rgAttribs[2];
  542. BYTE berValue[8];
  543. //
  544. // JohnsonA The BER encoding is current hardcoded. Change this to use
  545. // AndyHe's BER_printf package once it's done.
  546. //
  547. berValue[0] = 0x30;
  548. berValue[1] = 0x03;
  549. berValue[2] = 0x02;
  550. berValue[3] = 0x01;
  551. berValue[4] = (BYTE)((ULONG)SeInfo & 0xF);
  552. LDAPControlW SeInfoControl =
  553. {
  554. LDAP_SERVER_SD_FLAGS_OID_W,
  555. {
  556. 5, (PCHAR)berValue
  557. },
  558. TRUE
  559. };
  560. PLDAPControlW ServerControls[2] =
  561. {
  562. &SeInfoControl,
  563. NULL
  564. };
  565. rgAttribs[0] = SD_PROP_NAME;
  566. rgAttribs[1] = NULL;
  567. if(dwErr == ERROR_SUCCESS)
  568. {
  569. dwErr = ldap_search_ext_sW(pLDAP,
  570. pwszObject,
  571. LDAP_SCOPE_BASE,
  572. L"(objectClass=*)",
  573. rgAttribs,
  574. 0,
  575. (PLDAPControlW *)&ServerControls,
  576. NULL,
  577. NULL,
  578. 10000,
  579. &pMessage);
  580. dwErr = LdapMapErrorToWin32( dwErr );
  581. }
  582. if(dwErr == ERROR_SUCCESS)
  583. {
  584. LDAPMessage *pEntry = NULL;
  585. pEntry = ldap_first_entry(pLDAP,pMessage);
  586. if(pEntry == NULL)
  587. {
  588. dwErr = LdapMapErrorToWin32( pLDAP->ld_errno );
  589. if (ERROR_SUCCESS == dwErr)
  590. dwErr = ERROR_ACCESS_DENIED;
  591. }
  592. else
  593. {
  594. PLDAP_BERVAL *pSize = ldap_get_values_lenW(pLDAP,
  595. pMessage,
  596. rgAttribs[0]);
  597. if(pSize == NULL)
  598. {
  599. dwErr = LdapMapErrorToWin32( pLDAP->ld_errno );
  600. }
  601. else
  602. {
  603. //
  604. // Allocate the security descriptor to return
  605. //
  606. *ppSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, (*pSize)->bv_len);
  607. if(*ppSD == NULL)
  608. {
  609. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  610. }
  611. else
  612. {
  613. memcpy(*ppSD, (PBYTE)(*pSize)->bv_val, (*pSize)->bv_len);
  614. }
  615. ldap_value_free_len(pSize);
  616. }
  617. }
  618. }
  619. if ( pMessage != NULL )
  620. {
  621. ldap_msgfree(pMessage);
  622. }
  623. return(dwErr);
  624. }
  625. //+---------------------------------------------------------------------------
  626. //
  627. // Function: MartaStampSD
  628. //
  629. // Synopsis: Actually stamps the security descriptor on the object.
  630. //
  631. // Arguments: [IN pwszObject] -- The object to stamp the SD on
  632. // [IN cSDSize] -- The size of the security descriptor
  633. // [IN SeInfo] -- SecurityInformation about the security
  634. // descriptor
  635. // [IN pSD] -- The SD to stamp
  636. // [IN pLDAP] -- The LDAP connection to use
  637. //
  638. // Returns: ERROR_SUCCESS -- Success
  639. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  640. //
  641. //----------------------------------------------------------------------------
  642. DWORD
  643. MartaStampSD(IN LPWSTR pwszObject,
  644. IN ULONG cSDSize,
  645. IN SECURITY_INFORMATION SeInfo,
  646. IN PSECURITY_DESCRIPTOR pSD,
  647. IN PLDAP pLDAP)
  648. {
  649. DWORD dwErr = ERROR_SUCCESS;
  650. //
  651. // Now, we'll do the write. The security descriptor
  652. // we got passed in better not be in the old Ds format,
  653. // where the leading 4 bytes are the SECURITY_INFORMATION, which we'll skip
  654. // and replace with control information
  655. //
  656. assert(*(PULONG)pSD > 0xF );
  657. PLDAPModW rgMods[2];
  658. PLDAP_BERVAL pBVals[2];
  659. LDAPModW Mod;
  660. LDAP_BERVAL BVal;
  661. BYTE ControlBuffer[ 5 ];
  662. LDAPControlW SeInfoControl =
  663. {
  664. LDAP_SERVER_SD_FLAGS_OID_W,
  665. {
  666. 5, (PCHAR) &ControlBuffer
  667. },
  668. TRUE
  669. };
  670. //
  671. // !!! Hardcoded for now. Use Andyhe's BER_printf once it's done.
  672. //
  673. ControlBuffer[0] = 0x30;
  674. ControlBuffer[1] = 0x3;
  675. ControlBuffer[2] = 0x02; // Denotes an integer;
  676. ControlBuffer[3] = 0x01; // Size
  677. ControlBuffer[4] = (BYTE)((ULONG)SeInfo & 0xF);
  678. PLDAPControlW ServerControls[2] =
  679. {
  680. &SeInfoControl,
  681. NULL
  682. };
  683. assert(IsValidSecurityDescriptor( pSD ) );
  684. rgMods[0] = &Mod;
  685. rgMods[1] = NULL;
  686. pBVals[0] = &BVal;
  687. pBVals[1] = NULL;
  688. BVal.bv_len = cSDSize;
  689. BVal.bv_val = (PCHAR)pSD;
  690. Mod.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
  691. Mod.mod_type = SD_PROP_NAME;
  692. Mod.mod_values = (LPWSTR *)pBVals;
  693. //
  694. // Now, we'll do the write...
  695. //
  696. dwErr = ldap_modify_ext_sW(pLDAP,
  697. pwszObject,
  698. rgMods,
  699. (PLDAPControlW *)&ServerControls,
  700. NULL);
  701. dwErr = LdapMapErrorToWin32(dwErr);
  702. return(dwErr);
  703. }
  704. DWORD
  705. MartaGetDsParentName(
  706. IN LPWSTR ObjectName,
  707. OUT LPWSTR *pParentName
  708. )
  709. /*++
  710. Routine Description:
  711. Given the name of a DS object return the name of its parent. The routine
  712. allocates memory required to hold the parent name.
  713. Arguments:
  714. ObjectName - Name of the DS object.
  715. pParentName - To return the pointer to the allocated parent name.
  716. In case of the root of the tree, we return NULL parent with ERROR_SUCCESS.
  717. Return Value:
  718. ERROR_SUCCESS in case of success.
  719. ERROR_* otherwise
  720. --*/
  721. {
  722. LPCWSTR pKey = NULL;
  723. LPCWSTR pVal = NULL;
  724. DWORD ccKey = 0;
  725. DWORD ccDN = 0;
  726. DWORD ccVal = 0;
  727. DWORD Size = 0;
  728. DWORD dwErr = ERROR_SUCCESS;
  729. LPCWSTR pDN = (LPWSTR) ObjectName;
  730. ccDN = wcslen(pDN);
  731. *pParentName = NULL;
  732. //
  733. // The input is empty. There is no parent. Just return.
  734. //
  735. if (0 == ccDN)
  736. {
  737. return ERROR_SUCCESS;
  738. }
  739. //
  740. // Do the first pass to get to the next level. At the end of this call,
  741. // pDN will point to the next ','. One more call to DsGetRdnW will
  742. // return the right result in pKey.
  743. // Input:
  744. // pDN = "CN=Kedar, DC=NTDEV, DC=Microsoft, DC=com"
  745. // Output:
  746. // pDN = ", DC=NTDEV, DC=Microsoft, DC=com"
  747. //
  748. dwErr = DsGetRdnW(
  749. &pDN,
  750. &ccDN,
  751. &pKey,
  752. &ccKey,
  753. &pVal,
  754. &ccVal
  755. );
  756. if (ERROR_SUCCESS != dwErr)
  757. {
  758. return dwErr;
  759. }
  760. //
  761. // This is TRUE when the Object does not have any parent.
  762. //
  763. if (0 == ccDN)
  764. {
  765. return ERROR_SUCCESS;
  766. }
  767. //
  768. // Input:
  769. // pDN = ", DC=NTDEV, DC=Microsoft, DC=com"
  770. // Output:
  771. // pKey = "DC=NTDEV, DC=Microsoft, DC=com"
  772. //
  773. dwErr = DsGetRdnW(
  774. &pDN,
  775. &ccDN,
  776. &pKey,
  777. &ccKey,
  778. &pVal,
  779. &ccVal
  780. );
  781. if (ERROR_SUCCESS != dwErr)
  782. {
  783. return dwErr;
  784. }
  785. //
  786. // We have to distinguish between LDAP://ServerName/ObjectName and
  787. // ObjectName.
  788. //
  789. if (!_wcsnicmp(ObjectName, LDAP_SCHEME_U, wcslen(LDAP_SCHEME_U)) != 0 )
  790. {
  791. ULONG HostSize;
  792. //
  793. // Compute the size of string required to hold "LDAP//ServerName/" in
  794. // HostSize.
  795. //
  796. pDN = ObjectName + sizeof("ldap://");
  797. pDN = wcschr(pDN, L'/');
  798. if (NULL == pDN)
  799. {
  800. return ERROR_INVALID_PARAMETER;
  801. }
  802. HostSize = (ULONG) (pDN - ObjectName + 1);
  803. Size = (1 + wcslen(pKey) + HostSize) * sizeof(WCHAR);
  804. *pParentName = (LPWSTR) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, Size);
  805. if (NULL == *pParentName)
  806. {
  807. return ERROR_NOT_ENOUGH_MEMORY;
  808. }
  809. //
  810. // Copy the name of the parent into allocated memeory.
  811. //
  812. wcsncpy(*pParentName, ObjectName, HostSize);
  813. wcscpy((*pParentName) + HostSize, pKey);
  814. }
  815. else
  816. {
  817. Size = (1 + wcslen(pKey)) * sizeof(WCHAR);
  818. *pParentName = (LPWSTR) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, Size);
  819. if (NULL == *pParentName)
  820. {
  821. return ERROR_NOT_ENOUGH_MEMORY;
  822. }
  823. //
  824. // Copy the name of the parent into allocated memeory.
  825. //
  826. wcscpy(*pParentName, pKey);
  827. }
  828. return ERROR_SUCCESS;
  829. }