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.

2030 lines
56 KiB

  1. //
  2. // Copyright (C) 2000, Microsoft Corporation
  3. //
  4. // File: DfsADBlobCache.cxx
  5. //
  6. // Contents: the ADBlob DFS Store class, this contains the
  7. // old AD blob store specific functionality.
  8. //
  9. // Classes: DfsADBlobCache.
  10. //
  11. // History: Dec. 8 2000, Author: udayh
  12. // April 9 2001 Rohanp - Added AD specific code.
  13. //
  14. //-----------------------------------------------------------------------------
  15. #include <DfsAdBlobCache.hxx>
  16. #include <dfsrootfolder.hxx>
  17. #include <dfserror.hxx>
  18. #include "dfsadsiapi.hxx"
  19. #include <sddl.h>
  20. #include <dfssecurity.h>
  21. #include <ntdsapi.h>
  22. #include "dfsAdBlobCache.tmh"
  23. DfsADBlobCache::DfsADBlobCache(
  24. DFSSTATUS *pStatus,
  25. PUNICODE_STRING pShareName,
  26. DfsRootFolder * pRootFolder) : DfsGeneric(DFS_OBJECT_TYPE_ADBLOB_CACHE)
  27. {
  28. SHASH_FUNCTABLE FunctionTable;
  29. NTSTATUS NtStatus = STATUS_SUCCESS;
  30. DFSSTATUS Status = ERROR_SUCCESS;
  31. *pStatus = ERROR_SUCCESS;
  32. do {
  33. m_pBlob = NULL;
  34. m_pRootBlob = NULL;
  35. m_pTable = NULL;
  36. m_pAdHandle = NULL;
  37. m_AdReferenceCount = 0;
  38. m_RefreshCount = 0;
  39. m_ErrorOccured = DFS_DS_NOERROR;
  40. m_pRootFolder = pRootFolder;
  41. RtlInitUnicodeString(&m_LogicalShare, NULL);
  42. RtlInitUnicodeString(&m_ObjectDN, NULL);
  43. ZeroMemory(&FunctionTable, sizeof(FunctionTable));
  44. FunctionTable.AllocFunc = AllocateShashData;
  45. FunctionTable.FreeFunc = DeallocateShashData;
  46. ZeroMemory(&m_BlobAttributePktGuid, sizeof(GUID));
  47. m_fCritInit = InitializeCriticalSectionAndSpinCount( &m_Lock, DFS_CRIT_SPIN_COUNT);
  48. if(!m_fCritInit)
  49. {
  50. Status = GetLastError();
  51. break;
  52. }
  53. Status = DfsCreateUnicodeString(&m_LogicalShare, pShareName);
  54. if (Status != ERROR_SUCCESS)
  55. {
  56. break;
  57. }
  58. Status = SetupObjectDN();
  59. if(Status != ERROR_SUCCESS)
  60. {
  61. if(DfsServerGlobalData.bDfsAdAlive)
  62. {
  63. DfsServerGlobalData.bDfsAdAlive = FALSE;
  64. DfsLogDfsEvent(DFS_ERROR_ACTIVEDIRECTORY_OFFLINE, 0, NULL, 0);
  65. }
  66. break;
  67. }
  68. if(DfsServerGlobalData.bDfsAdAlive == FALSE)
  69. {
  70. DfsServerGlobalData.bDfsAdAlive = TRUE;
  71. DfsLogDfsEvent(DFS_INFO_ACTIVEDIRECTORY_ONLINE, 0, NULL, 0);
  72. }
  73. NtStatus = ShashInitHashTable(&m_pTable, &FunctionTable);
  74. if (NtStatus != STATUS_SUCCESS)
  75. {
  76. Status = RtlNtStatusToDosError(NtStatus);
  77. break;
  78. }
  79. } while (FALSE);
  80. *pStatus = Status;
  81. return;
  82. }
  83. DfsADBlobCache::~DfsADBlobCache()
  84. {
  85. if(m_pBlob)
  86. {
  87. DeallocateShashData(m_pBlob);
  88. m_pBlob = NULL;
  89. }
  90. if(m_pRootBlob)
  91. {
  92. DeallocateShashData(m_pRootBlob);
  93. m_pRootBlob = NULL;
  94. }
  95. if (m_pTable != NULL)
  96. {
  97. InvalidateCache();
  98. ShashTerminateHashTable(m_pTable);
  99. m_pTable = NULL;
  100. }
  101. if (m_LogicalShare.Buffer != NULL)
  102. {
  103. delete [] m_LogicalShare.Buffer;
  104. m_LogicalShare.Buffer = NULL;
  105. }
  106. if (m_ObjectDN.Buffer != NULL)
  107. {
  108. delete [] m_ObjectDN.Buffer;
  109. m_ObjectDN.Buffer = NULL;
  110. }
  111. if(m_fCritInit)
  112. {
  113. DeleteCriticalSection(&m_Lock);
  114. m_fCritInit = FALSE;
  115. }
  116. }
  117. #ifndef DFS_USE_LDAP
  118. DFSSTATUS
  119. DfsADBlobCache::UpdateCacheWithDSBlob(
  120. PVOID pHandle )
  121. {
  122. HRESULT hr = S_OK;
  123. DFSSTATUS Status = ERROR_SUCCESS;
  124. BYTE *pBuffer = NULL;
  125. ULONG Length = 0;
  126. VARIANT BinaryBlob;
  127. IADs *pADs = (IADs *)pHandle;
  128. DFS_TRACE_LOW( ADBLOB, "Cache %p: updating cache with blob \n", this);
  129. VariantInit(&BinaryBlob);
  130. hr = pADs->Get(ADBlobAttribute, &BinaryBlob);
  131. if ( SUCCEEDED(hr) )
  132. {
  133. Status = GetBinaryFromVariant( &BinaryBlob, &pBuffer, &Length );
  134. if (Status == ERROR_SUCCESS)
  135. {
  136. Status = UnpackBlob( pBuffer, &Length, NULL );
  137. DFS_TRACE_ERROR_LOW( Status, REFERRAL_SERVER, "Unpack blob done with status %x\n", Status);
  138. delete [] pBuffer;
  139. }
  140. }
  141. else
  142. {
  143. Status = DfsGetErrorFromHr(hr);
  144. }
  145. VariantClear(&BinaryBlob);
  146. DFS_TRACE_ERROR_LOW( Status, ADBLOB, "cache %p: Updated cache (length %x) status %x\n",
  147. this, Length, Status);
  148. return Status;
  149. }
  150. DFSSTATUS
  151. DfsADBlobCache::GetObjectPktGuid(
  152. PVOID pHandle,
  153. GUID *pGuid )
  154. {
  155. HRESULT hr = S_OK;
  156. DFSSTATUS Status = ERROR_SUCCESS;
  157. BYTE *pBuffer = NULL;
  158. ULONG Length = 0;
  159. VARIANT BinaryBlob;
  160. IADs *pADs = (IADs *)pHandle;
  161. DFS_TRACE_LOW( ADBLOB, "Cache %p: getting pkt guid\n", this);
  162. VariantInit(&BinaryBlob);
  163. hr = pADs->Get(ADBlobPktGuidAttribute, &BinaryBlob);
  164. if ( SUCCEEDED(hr) )
  165. {
  166. Status = GetBinaryFromVariant( &BinaryBlob, &pBuffer, &Length );
  167. if (Status == ERROR_SUCCESS)
  168. {
  169. if (Length > sizeof(GUID)) Length = sizeof(GUID);
  170. RtlCopyMemory( pGuid, pBuffer, Length);
  171. delete [] pBuffer;
  172. }
  173. }
  174. VariantClear(&BinaryBlob);
  175. Status = DfsGetErrorFromHr(hr);
  176. DFS_TRACE_ERROR_LOW( Status, ADBLOB, "cache %p: got pkt guid, Status %x\n",
  177. this, Status );
  178. return Status;
  179. }
  180. DFSSTATUS
  181. DfsADBlobCache::UpdateDSBlobFromCache(
  182. PVOID pHandle,
  183. GUID *pGuid )
  184. {
  185. HRESULT HResult = S_OK;
  186. DFSSTATUS Status = ERROR_SUCCESS;
  187. BYTE *pBuffer = NULL;
  188. ULONG Length;
  189. ULONG UseLength;
  190. ULONG TotalBlobBytes = 0;
  191. VARIANT BinaryBlob;
  192. IADs *pObject = (IADs *)pHandle;
  193. VariantInit(&BinaryBlob);
  194. DFS_TRACE_LOW( ADBLOB, "Cache %p: updating ds with cache \n", this);
  195. UseLength = ADBlobDefaultBlobPackSize;
  196. retry:
  197. Length = UseLength;
  198. pBuffer = (BYTE *) HeapAlloc(GetProcessHeap(), 0,
  199. Length );
  200. if(pBuffer != NULL)
  201. {
  202. Status = PackBlob(pBuffer, &Length, &TotalBlobBytes);
  203. if(Status == STATUS_SUCCESS)
  204. {
  205. Status = PutBinaryIntoVariant(&BinaryBlob, pBuffer, TotalBlobBytes);
  206. if(Status == STATUS_SUCCESS)
  207. {
  208. HResult = pObject->Put(ADBlobAttribute, BinaryBlob);
  209. if (SUCCEEDED(HResult) )
  210. {
  211. HResult = pObject->SetInfo();
  212. }
  213. Status = DfsGetErrorFromHr(HResult);
  214. if (Status == ERROR_SUCCESS)
  215. {
  216. Status = SetObjectPktGuid( pObject, pGuid );
  217. }
  218. }
  219. }
  220. DFS_TRACE_ERROR_LOW(Status, ADBLOB, "Cache %p: update ds (Buffer Len %x, Length %x) Status %x\n",
  221. this, UseLength, Length, Status);
  222. HeapFree(GetProcessHeap(), 0, pBuffer);
  223. if (Status == ERROR_BUFFER_OVERFLOW)
  224. {
  225. if (UseLength < ADBlobMaximumBlobPackSize)
  226. {
  227. UseLength *= 2;
  228. }
  229. //
  230. // If we are still within the maximum bounds, retry.
  231. //
  232. if (UseLength <= ADBlobMaximumBlobPackSize)
  233. {
  234. goto retry;
  235. }
  236. }
  237. }
  238. else
  239. {
  240. Status = ERROR_NOT_ENOUGH_MEMORY;
  241. }
  242. VariantClear(&BinaryBlob);
  243. DFS_TRACE_ERROR_LOW(Status, ADBLOB, "Cache %p: update ds done (Buffer Length %x, Length %x) Status %x\n",
  244. this, UseLength, Length, Status);
  245. return Status;
  246. }
  247. DFSSTATUS
  248. DfsADBlobCache::SetObjectPktGuid(
  249. IADs *pObject,
  250. GUID *pGuid )
  251. {
  252. HRESULT HResult = S_OK;
  253. DFSSTATUS Status = ERROR_SUCCESS;
  254. VARIANT BinaryBlob;
  255. DFS_TRACE_LOW( ADBLOB, "Cache %p: setting pkt guid\n", this);
  256. VariantInit(&BinaryBlob);
  257. Status = PutBinaryIntoVariant( &BinaryBlob, (PBYTE)pGuid, sizeof(GUID));
  258. if (Status == ERROR_SUCCESS)
  259. {
  260. HResult = pObject->Put(ADBlobPktGuidAttribute, BinaryBlob);
  261. if (SUCCEEDED(HResult) )
  262. {
  263. HResult = pObject->SetInfo();
  264. }
  265. Status = DfsGetErrorFromHr(HResult);
  266. }
  267. VariantClear(&BinaryBlob);
  268. DFS_TRACE_ERROR_LOW( Status, ADBLOB, "cache %p: set pkt guid, Status %x\n",
  269. this, Status );
  270. return Status;
  271. }
  272. #else
  273. DFSSTATUS
  274. DfsADBlobCache::DfsLdapConnect(
  275. LPWSTR DCName,
  276. LDAP **ppLdap )
  277. {
  278. LDAP *pLdap = NULL;
  279. LPWSTR ActualDC = NULL;
  280. DFSSTATUS Status = ERROR_SUCCESS;
  281. DFSSTATUS LocalStatus = ERROR_SUCCESS;
  282. LONG PreviousState = DFS_DS_ACTIVE;
  283. const TCHAR * apszSubStrings[4];
  284. apszSubStrings[0] = DCName;
  285. ActualDC = DCName;
  286. pLdap = ldap_initW(DCName, LDAP_PORT);
  287. if (pLdap != NULL)
  288. {
  289. Status = ldap_set_option(pLdap, LDAP_OPT_AREC_EXCLUSIVE, LDAP_OPT_ON);
  290. if (Status == LDAP_SUCCESS)
  291. {
  292. UNICODE_STRING DnsDomain;
  293. if (DfsGetDnsDomainName( &DnsDomain) == ERROR_SUCCESS)
  294. {
  295. Status = ldap_set_option(pLdap, LDAP_OPT_DNSDOMAIN_NAME, &DnsDomain.Buffer);
  296. DfsReleaseDomainName(&DnsDomain);
  297. }
  298. }
  299. if (Status == LDAP_SUCCESS)
  300. {
  301. DFS_TRACE_LOW(ADBLOB,
  302. "Ldap Connect, calling LDAP Bind DC: %ws, init ldap status %x\n",
  303. DCName, Status);
  304. Status = ldap_bind_s(pLdap, NULL, NULL, LDAP_AUTH_NEGOTIATE);
  305. DFS_TRACE_LOW(ADBLOB,
  306. "Ldap Connect, returning from LDAP Bind DC: %ws, init ldap status %x\n",
  307. DCName, Status);
  308. }
  309. }
  310. else
  311. {
  312. Status = LdapGetLastError();
  313. DFS_TRACE_ERROR_HIGH(Status, ADBLOB,
  314. "Ldap Connect, DC: %ws, init ldap status %x\n",
  315. DCName, Status);
  316. }
  317. if (Status == LDAP_SUCCESS)
  318. {
  319. *ppLdap = pLdap;
  320. if(DCName == NULL)
  321. {
  322. //Get the actual host name that we connected to. We don't have to free
  323. //this name since it will get freed when ldap_unbind is called.
  324. LocalStatus = ldap_get_optionW(pLdap, LDAP_OPT_HOST_NAME , (void *) &ActualDC);
  325. apszSubStrings[0] = ActualDC;
  326. }
  327. DFS_TRACE_HIGH(ADBLOB, "ADBLOBConnected to actual DC: %ws, ldap status %x\n",
  328. ActualDC, Status);
  329. PreviousState = InterlockedCompareExchange(&DfsServerGlobalData.FirstContact, DFS_DS_ACTIVE, DFS_DS_NOTACTIVE);
  330. if(PreviousState == DFS_DS_NOTACTIVE)
  331. {
  332. DfsLogDfsEvent(DFS_INFO_DS_RECONNECTED, 1, apszSubStrings, Status);
  333. }
  334. }
  335. else
  336. {
  337. PreviousState = InterlockedCompareExchange(&DfsServerGlobalData.FirstContact, DFS_DS_NOTACTIVE, DFS_DS_ACTIVE);
  338. if(PreviousState == DFS_DS_ACTIVE)
  339. {
  340. DfsLogDfsEvent(DFS_ERROR_DSCONNECT_FAILED, 1, apszSubStrings, Status);
  341. }
  342. DFS_TRACE_ERROR_HIGH(Status, ADBLOB,
  343. "Ldap Connect, DC: %ws, ldap status %x\n",
  344. DCName, Status);
  345. Status = LdapMapErrorToWin32(Status);
  346. }
  347. if (Status != ERROR_SUCCESS)
  348. {
  349. if (pLdap != NULL)
  350. {
  351. //
  352. // 565302
  353. // we need to call ldap_unbind if we have a valid connection!
  354. // Note that this is true even if ldap_bind failed or we never
  355. // even called ldap_bind.
  356. //
  357. ldap_unbind(pLdap);
  358. }
  359. }
  360. return Status;
  361. }
  362. VOID
  363. DfsADBlobCache::DfsLdapDisconnect(
  364. LDAP *pLdap )
  365. {
  366. ldap_unbind(pLdap);
  367. }
  368. DFSSTATUS
  369. DfsADBlobCache::DfsGetPktBlob(
  370. LDAP *pLdap,
  371. LPWSTR ObjectDN,
  372. PVOID *ppBlob,
  373. PULONG pBlobSize,
  374. PVOID *ppHandle,
  375. PVOID *ppHandle1 )
  376. {
  377. DFSSTATUS Status = ERROR_SUCCESS;
  378. DFSSTATUS LdapStatus = ERROR_SUCCESS;
  379. PLDAPMessage pLdapSearchedObject = NULL;
  380. PLDAPMessage pLdapObject = NULL;
  381. PLDAP_BERVAL *pLdapPktAttr = NULL;
  382. LPWSTR Attributes[2];
  383. struct l_timeval Timeout;
  384. Status = ERROR_ACCESS_DENIED; // fix this after we understand
  385. // ldap error correctly. When
  386. // ldap_get_values_len returns NULL
  387. // the old code return no more mem.
  388. Attributes[0] = ADBlobAttribute;
  389. Attributes[1] = NULL;
  390. Timeout.tv_sec = DfsServerGlobalData.LdapTimeOut;
  391. DFS_TRACE_LOW(ADBLOB,
  392. "DfsGetPktBlob, calling LDAP Search ObjectDN: %ws, init ldap status %x\n",
  393. ObjectDN, Status);
  394. LdapStatus = ldap_search_ext_sW( pLdap,
  395. ObjectDN,
  396. LDAP_SCOPE_BASE,
  397. L"(objectClass=*)",
  398. Attributes,
  399. 0, // attributes only
  400. NULL, // server controls
  401. NULL, // client controls
  402. &Timeout,
  403. 0, // size limit
  404. &pLdapSearchedObject);
  405. DFS_TRACE_LOW(ADBLOB,
  406. "DfsGetPktBlob, returning from LDAP Search ObjectDN: %ws, init ldap status %x\n",
  407. ObjectDN, Status);
  408. if (LdapStatus == LDAP_SUCCESS)
  409. {
  410. pLdapObject = ldap_first_entry( pLdap,
  411. pLdapSearchedObject );
  412. if (pLdapObject != NULL)
  413. {
  414. pLdapPktAttr = ldap_get_values_len( pLdap,
  415. pLdapObject,
  416. Attributes[0] );
  417. if (pLdapPktAttr != NULL)
  418. {
  419. *ppBlob = pLdapPktAttr[0]->bv_val;
  420. *pBlobSize = pLdapPktAttr[0]->bv_len;
  421. *ppHandle = (PVOID)pLdapPktAttr;
  422. *ppHandle1 = (PVOID)pLdapSearchedObject;
  423. pLdapSearchedObject = NULL;
  424. Status = ERROR_SUCCESS;
  425. }
  426. else
  427. {
  428. if(pLdap->ld_errno == LDAP_NO_SUCH_ATTRIBUTE)
  429. {
  430. Status = ERROR_ACCESS_DENIED;
  431. }
  432. else
  433. {
  434. Status = LdapMapErrorToWin32( pLdap->ld_errno );
  435. }
  436. DFS_TRACE_ERROR_HIGH( Status, ADBLOB, "DfsADBlobCache::DfsGetPktBlob1 (ldap error %x) status %x\n",
  437. pLdap->ld_errno, Status);
  438. }
  439. }
  440. }
  441. else
  442. {
  443. Status = LdapMapErrorToWin32(LdapStatus);
  444. DFS_TRACE_ERROR_HIGH( Status, ADBLOB, "DfsADBlobCache::DfsGetPktBlob2 (ldap error %x) status %x\n",
  445. LdapStatus, Status);
  446. }
  447. if (pLdapSearchedObject != NULL)
  448. {
  449. ldap_msgfree( pLdapSearchedObject );
  450. }
  451. return Status;
  452. }
  453. VOID
  454. DfsADBlobCache::DfsReleasePktBlob(
  455. PVOID pHandle,
  456. PVOID pHandle1 )
  457. {
  458. PLDAP_BERVAL *pLdapPktAttr = (PLDAP_BERVAL *)pHandle;
  459. PLDAPMessage pLdapSearchedObject = (PLDAPMessage)pHandle1;
  460. ldap_value_free_len( pLdapPktAttr );
  461. ldap_msgfree( pLdapSearchedObject );
  462. }
  463. DFSSTATUS
  464. DfsADBlobCache::UpdateCacheWithDSBlob(
  465. PVOID pHandle )
  466. {
  467. DFSSTATUS Status = ERROR_SUCCESS;
  468. BYTE *pBuffer = NULL;
  469. ULONG Length = 0;
  470. PVOID pHandle1, pHandle2;
  471. LDAP *pLdap = (LDAP *)pHandle;
  472. UNICODE_STRING ObjectDN;
  473. DFS_TRACE_LOW( ADBLOB, "Cache %p: updating cache with blob \n", this);
  474. Status = GetObjectDN(&ObjectDN);
  475. if (Status == ERROR_SUCCESS)
  476. {
  477. Status = DfsGetPktBlob( pLdap,
  478. ObjectDN.Buffer,
  479. (PVOID *)&pBuffer,
  480. &Length,
  481. &pHandle1,
  482. &pHandle2);
  483. }
  484. if ( Status == ERROR_SUCCESS)
  485. {
  486. Status = UnpackBlob( pBuffer, &Length, NULL );
  487. DFS_TRACE_ERROR_LOW( Status, REFERRAL_SERVER, "Unpack blob done with status %x\n", Status);
  488. DfsReleasePktBlob( pHandle1, pHandle2);
  489. }
  490. DFS_TRACE_ERROR_LOW( Status, ADBLOB, "cache %p: Updated cache (length %x) status %x\n",
  491. this, Length, Status);
  492. return Status;
  493. }
  494. DFSSTATUS
  495. DfsADBlobCache::GetObjectPktGuid(
  496. PVOID pHandle,
  497. GUID *pGuid )
  498. {
  499. DFSSTATUS Status = ERROR_SUCCESS;
  500. DFSSTATUS LdapStatus = ERROR_SUCCESS;
  501. PLDAPMessage pLdapSearchedObject = NULL;
  502. PLDAPMessage pLdapObject = NULL;
  503. PLDAP_BERVAL *pLdapGuidAttr = NULL;
  504. ULONG CopySize = 0;
  505. LDAP *pLdap = (LDAP *)pHandle;
  506. UNICODE_STRING ObjectDN;
  507. struct l_timeval Timeout;
  508. LPWSTR Attributes[2];
  509. Status = GetObjectDN(&ObjectDN);
  510. if (Status != ERROR_SUCCESS)
  511. {
  512. return Status;
  513. }
  514. Status = ERROR_ACCESS_DENIED; // fix this after we understand
  515. // ldap error correctly. When
  516. // ldap_get_values_len returns NULL
  517. // the old code return no more mem.
  518. Attributes[0] = ADBlobPktGuidAttribute;
  519. Attributes[1] = NULL;
  520. Timeout.tv_sec = DfsServerGlobalData.LdapTimeOut;
  521. DFS_TRACE_LOW(ADBLOB,
  522. "DfsGetPktGuid, calling LDAP Search - ldap status %x\n",
  523. Status);
  524. LdapStatus = ldap_search_ext_sW( pLdap,
  525. ObjectDN.Buffer,
  526. LDAP_SCOPE_BASE,
  527. L"(objectClass=*)",
  528. Attributes,
  529. 0, // attributes only
  530. NULL, // server controls
  531. NULL, // client controls
  532. &Timeout,
  533. 0, // size limit
  534. &pLdapSearchedObject);
  535. DFS_TRACE_LOW(ADBLOB,
  536. "DfsGetPktGuid, returning from LDAP Search - ldap status %x\n",
  537. Status);
  538. if (LdapStatus == LDAP_SUCCESS)
  539. {
  540. pLdapObject = ldap_first_entry( pLdap,
  541. pLdapSearchedObject );
  542. if (pLdapObject != NULL)
  543. {
  544. pLdapGuidAttr = ldap_get_values_len( pLdap,
  545. pLdapObject,
  546. Attributes[0] );
  547. if (pLdapGuidAttr != NULL)
  548. {
  549. CopySize = min( pLdapGuidAttr[0]->bv_len, sizeof(GUID));
  550. RtlCopyMemory( pGuid, pLdapGuidAttr[0]->bv_val, CopySize );
  551. ldap_value_free_len( pLdapGuidAttr );
  552. Status = ERROR_SUCCESS;
  553. }
  554. else
  555. {
  556. if(pLdap->ld_errno == LDAP_NO_SUCH_ATTRIBUTE)
  557. {
  558. Status = ERROR_ACCESS_DENIED;
  559. }
  560. else
  561. {
  562. Status = LdapMapErrorToWin32( pLdap->ld_errno );
  563. }
  564. DFS_TRACE_ERROR_HIGH( Status, ADBLOB, "DfsADBlobCache::GetObjectPktGuid1 (ldap error %x) status %x\n",
  565. LdapStatus, Status);
  566. }
  567. }
  568. }
  569. else
  570. {
  571. Status = LdapMapErrorToWin32(LdapStatus);
  572. DFS_TRACE_ERROR_HIGH( Status, ADBLOB, "DfsADBlobCache::GetObjectPktGuid2 (ldap error %x) status %x\n",
  573. pLdap->ld_errno, Status);
  574. }
  575. if (pLdapSearchedObject != NULL)
  576. {
  577. ldap_msgfree( pLdapSearchedObject );
  578. }
  579. return Status;
  580. }
  581. DFSSTATUS
  582. DfsADBlobCache::DfsSetPktBlobAndPktGuid (
  583. LDAP *pLdap,
  584. LPWSTR ObjectDN,
  585. PVOID pBlob,
  586. ULONG BlobSize,
  587. GUID *pGuid )
  588. {
  589. LDAP_BERVAL LdapPkt, LdapPktGuid;
  590. PLDAP_BERVAL pLdapPktValues[2], pLdapPktGuidValues[2];
  591. LDAPModW LdapPktMod, LdapPktGuidMod;
  592. PLDAPModW pLdapDfsMod[3];
  593. DFSSTATUS Status = ERROR_SUCCESS;
  594. DFSSTATUS LdapStatus;
  595. LDAPControlW LazyCommitControl =
  596. {
  597. LDAP_SERVER_LAZY_COMMIT_OID_W, // the control
  598. { 0, NULL}, // no associated data
  599. FALSE // control isn't mandatory
  600. };
  601. PLDAPControlW ServerControls[2] =
  602. {
  603. &LazyCommitControl,
  604. NULL
  605. };
  606. LdapPkt.bv_len = BlobSize;
  607. LdapPkt.bv_val = (PCHAR)pBlob;
  608. pLdapPktValues[0] = &LdapPkt;
  609. pLdapPktValues[1] = NULL;
  610. LdapPktMod.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
  611. LdapPktMod.mod_type = ADBlobAttribute;
  612. LdapPktMod.mod_vals.modv_bvals = pLdapPktValues;
  613. LdapPktGuid.bv_len = sizeof(GUID);
  614. LdapPktGuid.bv_val = (PCHAR)pGuid;
  615. pLdapPktGuidValues[0] = &LdapPktGuid;
  616. pLdapPktGuidValues[1] = NULL;
  617. LdapPktGuidMod.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
  618. LdapPktGuidMod.mod_type = ADBlobPktGuidAttribute;
  619. LdapPktGuidMod.mod_vals.modv_bvals = pLdapPktGuidValues;
  620. pLdapDfsMod[0] = &LdapPktMod;
  621. pLdapDfsMod[1] = &LdapPktGuidMod;
  622. pLdapDfsMod[2] = NULL;
  623. DFS_TRACE_LOW(ADBLOB,
  624. "DfsSetPktBlobAndPktGuid, calling LDAP ldap_modify_ext_sW ObjectDN: %ws, init ldap status %x\n",
  625. ObjectDN, Status);
  626. LdapStatus = ldap_modify_ext_sW( pLdap,
  627. ObjectDN,
  628. pLdapDfsMod,
  629. (PLDAPControlW *)ServerControls,
  630. NULL );
  631. DFS_TRACE_LOW(ADBLOB,
  632. "DfsSetPktBlobAndPktGuid, returning from LDAP ldap_modify_ext_sW ObjectDN: %ws, init ldap status %x\n",
  633. ObjectDN, Status);
  634. if (LdapStatus != LDAP_SUCCESS)
  635. {
  636. Status = LdapMapErrorToWin32(LdapStatus);
  637. }
  638. DFS_TRACE_ERROR_LOW( Status, ADBLOB, "DfsADBlobCache::DfsSetPktBlobAndPktGuid cache %p: LDAP Status %x, Win32 status %x\n",
  639. this, LdapStatus, Status);
  640. return Status;
  641. }
  642. DFSSTATUS
  643. DfsADBlobCache::UpdateDSBlobFromCache(
  644. PVOID pHandle,
  645. GUID *pGuid )
  646. {
  647. LDAP *pLdap = (LDAP *)pHandle;
  648. UNICODE_STRING ObjectDN;
  649. BYTE *pBuffer = NULL;
  650. ULONG Length = 0;
  651. ULONG UseLength = 0;
  652. ULONG TotalBlobBytes = 0;
  653. DFSSTATUS Status = ERROR_SUCCESS;
  654. Status = GetObjectDN(&ObjectDN);
  655. if (Status != ERROR_SUCCESS)
  656. {
  657. DFS_TRACE_ERROR_LOW( Status, ADBLOB, "DfsADBlobCache::UpdateDSBlobFromCache cache %p: GetObjectDN failed status %x\n",
  658. this, Status);
  659. return Status;
  660. }
  661. UseLength = ADBlobDefaultBlobPackSize;
  662. retry:
  663. Length = UseLength;
  664. pBuffer = (BYTE *) HeapAlloc(GetProcessHeap(), 0, Length );
  665. if(pBuffer != NULL)
  666. {
  667. Status = PackBlob(pBuffer, &Length, &TotalBlobBytes);
  668. if (Status != ERROR_SUCCESS)
  669. {
  670. HeapFree(GetProcessHeap(), 0, pBuffer);
  671. if (Status == ERROR_BUFFER_OVERFLOW)
  672. {
  673. if (UseLength < ADBlobMaximumBlobPackSize)
  674. {
  675. UseLength *= 2;
  676. }
  677. goto retry;
  678. }
  679. }
  680. if(Status == STATUS_SUCCESS)
  681. {
  682. Status = DfsSetPktBlobAndPktGuid( pLdap,
  683. ObjectDN.Buffer,
  684. pBuffer,
  685. TotalBlobBytes,
  686. pGuid );
  687. DFS_TRACE_ERROR_LOW(Status, ADBLOB, "Cache %p: DfsADBlobCache::UpdateDSBlobFromCache (Buffer Len %x, Length %x) Status %x\n",
  688. this, UseLength, Length, Status);
  689. HeapFree(GetProcessHeap(), 0, pBuffer);
  690. }
  691. }
  692. else
  693. {
  694. Status = ERROR_NOT_ENOUGH_MEMORY;
  695. }
  696. return Status;
  697. }
  698. #endif
  699. DFSSTATUS
  700. DfsADBlobCache::CacheRefresh(BOOLEAN fForceSync,
  701. BOOLEAN fFromPDC)
  702. {
  703. PVOID pHandle = NULL;
  704. DFSSTATUS Status = ERROR_SUCCESS;
  705. LONG PreviousState = DFS_DS_NOERROR;
  706. LONG RefreshCount = 0;
  707. PUNICODE_STRING pUseShare = NULL;
  708. GUID CurrentGuid;
  709. const TCHAR * apszSubStrings[4];
  710. LPWSTR UseDC = NULL;
  711. DfsString *pPDC = NULL;
  712. DFSSTATUS PDCStatus = ERROR_SUCCESS;
  713. DFS_TRACE_LOW( ADBLOB, "Cache %p: from pdc? %d cache refresh\n", this, fFromPDC);
  714. if (fFromPDC == TRUE)
  715. {
  716. PDCStatus = DfsGetBlobPDCName( &pPDC, 0 );
  717. //
  718. // Ignore the status here. If this call fails, we dont care
  719. // since we will just use a non-pdc dc. All callers who
  720. // *really* care have already got the object with the right dc.
  721. // see apiprologue for more details.
  722. //
  723. if (PDCStatus == ERROR_SUCCESS)
  724. {
  725. UseDC = pPDC->GetString();
  726. }
  727. }
  728. DFS_TRACE_LOW(ADBLOB, "Cache refresh using dc %ws\n", UseDC);
  729. Status = GetADObject( &pHandle, UseDC);
  730. if ((Status != ERROR_SUCCESS) &&
  731. (UseDC != NULL))
  732. {
  733. //
  734. // hmmm. failed here going to pdc. Just get the object without bothering
  735. // about the PDC.
  736. //
  737. Status = GetADObject(&pHandle, NULL);
  738. }
  739. if (Status == ERROR_SUCCESS)
  740. {
  741. // fFromPDC == FALSE means root scalability mode..every so often, get a new
  742. // Blob and guid
  743. if(fFromPDC == FALSE)
  744. {
  745. RefreshCount = InterlockedIncrement(&m_RefreshCount);
  746. if(RefreshCount >= DFS_ROOTSCALABILTY_FORCED_REFRESH_INTERVAL)
  747. {
  748. fForceSync = TRUE;
  749. InterlockedExchange((LPLONG volatile ) &m_RefreshCount, 0);
  750. }
  751. }
  752. Status = GetObjectPktGuid( pHandle, &CurrentGuid );
  753. if(Status == ERROR_SUCCESS)
  754. {
  755. if(!fForceSync)
  756. {
  757. //
  758. // here we pass the 2 guids by reference...
  759. //
  760. if (IsEqualGUID( CurrentGuid, m_BlobAttributePktGuid) == FALSE)
  761. {
  762. Status = UpdateCacheWithDSBlob( pHandle );
  763. if (Status == ERROR_SUCCESS)
  764. {
  765. m_BlobAttributePktGuid = CurrentGuid;
  766. }
  767. }
  768. }
  769. else
  770. {
  771. Status = UpdateCacheWithDSBlob( pHandle );
  772. if (Status == ERROR_SUCCESS)
  773. {
  774. m_BlobAttributePktGuid = CurrentGuid;
  775. }
  776. }
  777. }
  778. ReleaseADObject( pHandle );
  779. }
  780. DfsReleaseBlobPDCName( pPDC );
  781. if(Status != ERROR_SUCCESS)
  782. {
  783. PreviousState = InterlockedCompareExchange(&m_ErrorOccured, DFS_DS_ERROR, DFS_DS_NOERROR);
  784. if(PreviousState == DFS_DS_NOERROR)
  785. {
  786. pUseShare = m_pRootFolder->GetRootPhysicalShareName();
  787. apszSubStrings[0] = pUseShare->Buffer;
  788. DfsLogDfsEvent(DFS_ERROR_NO_DFS_DATA, 1, apszSubStrings, Status);
  789. }
  790. }
  791. else
  792. {
  793. PreviousState = InterlockedCompareExchange(&m_ErrorOccured, DFS_DS_NOERROR, DFS_DS_ERROR);
  794. if(PreviousState == DFS_DS_ERROR)
  795. {
  796. pUseShare = m_pRootFolder->GetRootPhysicalShareName();
  797. apszSubStrings[0] = pUseShare->Buffer;
  798. DfsLogDfsEvent(DFS_INFO_RECONNECT_DATA, 1, apszSubStrings, Status);
  799. }
  800. }
  801. DFS_TRACE_ERROR_LOW( Status, ADBLOB, "Cache %p: CacheRefresh status 0x%x\n", this, Status);
  802. return Status;
  803. }
  804. void
  805. DfsADBlobCache::InvalidateCache()
  806. {
  807. PDFSBLOB_DATA pBlobData;
  808. DFSBOB_ITER Iter;
  809. DFS_TRACE_LOW( ADBLOB, "Cache %p: invalidate cache\n", this);
  810. pBlobData = FindFirstBlob(&Iter);
  811. while (pBlobData != NULL)
  812. {
  813. DFSSTATUS RemoveStatus;
  814. RemoveStatus = RemoveNamedBlob(&pBlobData->BlobName);
  815. DFS_TRACE_ERROR_LOW( RemoveStatus, REFERRAL_SERVER, "BlobCache %p, invalidate cache, remove blob status %x\n",
  816. this, RemoveStatus);
  817. pBlobData = FindNextBlob(&Iter);
  818. }
  819. FindCloseBlob(&Iter);
  820. DFS_TRACE_LOW( ADBLOB, "Cache %p: invalidate cache done\n", this);
  821. }
  822. DFSSTATUS
  823. DfsADBlobCache::PutBinaryIntoVariant(VARIANT * ovData, BYTE * pBuf,
  824. unsigned long cBufLen)
  825. {
  826. DFSSTATUS Status = ERROR_INVALID_PARAMETER;
  827. void * pArrayData = NULL;
  828. VARIANT var;
  829. SAFEARRAYBOUND rgsabound[1];
  830. VariantInit(&var); //Initialize our variant
  831. var.vt = VT_ARRAY | VT_UI1;
  832. rgsabound[0].cElements = cBufLen;
  833. rgsabound[0].lLbound = 0;
  834. var.parray = SafeArrayCreate(VT_UI1,1,rgsabound);
  835. if(var.parray != NULL)
  836. {
  837. //Get a safe pointer to the array
  838. SafeArrayAccessData(var.parray,&pArrayData);
  839. //Copy bitmap to it
  840. memcpy(pArrayData, pBuf, cBufLen);
  841. //Unlock the variant data
  842. SafeArrayUnaccessData(var.parray);
  843. *ovData = var;
  844. Status = STATUS_SUCCESS;
  845. }
  846. else
  847. {
  848. Status = ERROR_NOT_ENOUGH_MEMORY;
  849. DFS_TRACE_HIGH( REFERRAL_SERVER, "PutBinaryIntoVariant failed error %d\n", Status);
  850. }
  851. return Status;
  852. }
  853. DFSSTATUS
  854. DfsADBlobCache::GetBinaryFromVariant(VARIANT *ovData, BYTE ** ppBuf,
  855. unsigned long * pcBufLen)
  856. {
  857. DFSSTATUS Status = ERROR_INVALID_PARAMETER;
  858. void * pArrayData = NULL;
  859. //Binary data is stored in the variant as an array of unsigned char
  860. if(ovData->vt == (VT_ARRAY|VT_UI1))
  861. {
  862. //Retrieve size of array
  863. *pcBufLen = ovData->parray->rgsabound[0].cElements;
  864. *ppBuf = new BYTE[*pcBufLen]; //Allocate a buffer to store the data
  865. if(*ppBuf != NULL)
  866. {
  867. //Obtain safe pointer to the array
  868. SafeArrayAccessData(ovData->parray,&pArrayData);
  869. //Copy the bitmap into our buffer
  870. memcpy(*ppBuf, pArrayData, *pcBufLen);
  871. //Unlock the variant data
  872. SafeArrayUnaccessData(ovData->parray);
  873. Status = ERROR_SUCCESS;
  874. }
  875. else
  876. {
  877. Status = ERROR_NOT_ENOUGH_MEMORY;
  878. }
  879. }
  880. return Status;
  881. }
  882. DFSSTATUS
  883. DfsADBlobCache::CacheFlush(
  884. PVOID pHandle )
  885. {
  886. DFSSTATUS Status = ERROR_SUCCESS;
  887. GUID NewGuid;
  888. IADs *pObject = (IADs *)pHandle;
  889. DFS_TRACE_LOW( ADBLOB, "Cache %p: cache flush\n", this);
  890. Status = UuidCreate(&NewGuid);
  891. if (Status == ERROR_SUCCESS)
  892. {
  893. m_BlobAttributePktGuid = NewGuid;
  894. Status = UpdateDSBlobFromCache( pObject,
  895. &NewGuid );
  896. }
  897. DFS_TRACE_ERROR_LOW( Status, ADBLOB, "Cache %p: cache flush, Status %x\n", this, Status);
  898. return Status;
  899. }
  900. DFSSTATUS
  901. DfsADBlobCache::UnpackBlob(
  902. BYTE *pBuffer,
  903. PULONG pLength,
  904. PDFSBLOB_DATA * pRetBlob )
  905. {
  906. ULONG Discard = 0;
  907. DFSSTATUS Status = ERROR_SUCCESS;
  908. BYTE *pUseBuffer = NULL;
  909. ULONG BufferSize = 0;
  910. ULONG ObjNdx = 0;
  911. ULONG TotalObjects = 0;
  912. ULONG BlobSize = 0;
  913. BYTE *BlobBuffer = NULL;
  914. PDFSBLOB_DATA pLocalBlob = NULL;
  915. UNICODE_STRING BlobName;
  916. UNICODE_STRING SiteRoot;
  917. UNICODE_STRING BlobRoot;
  918. pUseBuffer = pBuffer;
  919. BufferSize = *pLength;
  920. DFS_TRACE_LOW( ADBLOB, "BlobCache %p, UnPackBlob \n", this);
  921. UNREFERENCED_PARAMETER(pRetBlob);
  922. Status = DfsRtlInitUnicodeStringEx( &SiteRoot, ADBlobSiteRoot );
  923. if (Status != ERROR_SUCCESS)
  924. {
  925. goto done;
  926. }
  927. Status = DfsRtlInitUnicodeStringEx( &BlobRoot, ADBlobMetaDataNamePrefix);
  928. if (Status != ERROR_SUCCESS)
  929. {
  930. goto done;
  931. }
  932. //
  933. // Note the size of the whole blob.
  934. //
  935. m_BlobSize = BufferSize;
  936. //
  937. // dfsdev: we should not need an interlocked here: this code
  938. // is already mutex'd by the caller.
  939. //
  940. InterlockedIncrement( &m_CurrentSequenceNumber );
  941. //
  942. // dfsdev: investigate what the first ulong is and add comment
  943. // here as to why we are discarding it.
  944. //
  945. Status = PackGetULong( &Discard, (PVOID *) &pUseBuffer, &BufferSize );
  946. if (Status != ERROR_SUCCESS)
  947. {
  948. goto done;
  949. }
  950. if(BufferSize == 0)
  951. {
  952. goto done;
  953. }
  954. Status = PackGetULong(&TotalObjects, (PVOID *) &pUseBuffer, &BufferSize);
  955. if (Status != ERROR_SUCCESS)
  956. {
  957. goto done;
  958. }
  959. for (ObjNdx = 0; ObjNdx < TotalObjects; ObjNdx++)
  960. {
  961. BOOLEAN FoundSite = FALSE;
  962. BOOLEAN FoundRoot = FALSE;
  963. Status = GetSubBlob( &BlobName,
  964. &BlobBuffer,
  965. &BlobSize,
  966. &pUseBuffer,
  967. &BufferSize );
  968. if (Status == ERROR_SUCCESS)
  969. {
  970. if (!FoundSite &&
  971. (RtlCompareUnicodeString( &BlobName, &SiteRoot, TRUE ) == 0))
  972. {
  973. FoundSite = TRUE;
  974. Status = CreateBlob(&BlobName,
  975. BlobBuffer,
  976. BlobSize,
  977. &pLocalBlob
  978. );
  979. if(Status == STATUS_SUCCESS)
  980. {
  981. DeallocateShashData(m_pBlob);
  982. m_pBlob = pLocalBlob;
  983. }
  984. continue;
  985. }
  986. if (!FoundRoot &&
  987. (RtlCompareUnicodeString( &BlobName, &BlobRoot, TRUE ) == 0))
  988. {
  989. FoundRoot = TRUE;
  990. UNICODE_STRING RootName;
  991. RtlInitUnicodeString(&RootName, NULL);
  992. Status = CreateBlob(&RootName,
  993. BlobBuffer,
  994. BlobSize,
  995. &pLocalBlob
  996. );
  997. if(Status == STATUS_SUCCESS)
  998. {
  999. DeallocateShashData(m_pRootBlob);
  1000. m_pRootBlob = pLocalBlob;
  1001. }
  1002. continue;
  1003. }
  1004. Status = StoreBlobInCache( &BlobName, BlobBuffer, BlobSize);
  1005. if (Status != ERROR_SUCCESS)
  1006. {
  1007. break;
  1008. }
  1009. }
  1010. }
  1011. done:
  1012. DFS_TRACE_ERROR_LOW( Status, ADBLOB, "BlobCache %p: UnPackBlob status %x\n", this, Status);
  1013. return Status;
  1014. }
  1015. DFSSTATUS
  1016. DfsADBlobCache::CreateBlob(PUNICODE_STRING BlobName,
  1017. PBYTE pBlobBuffer,
  1018. ULONG BlobSize,
  1019. PDFSBLOB_DATA *pNewBlob )
  1020. {
  1021. PDFSBLOB_DATA BlobStructure = NULL;
  1022. DFSSTATUS Status = ERROR_SUCCESS;
  1023. PBYTE NextBufOffset;
  1024. ULONG TotalSize = sizeof(DFSBLOB_DATA) +
  1025. BlobName->Length + sizeof(WCHAR) +
  1026. BlobSize;
  1027. BlobStructure = (PDFSBLOB_DATA) AllocateShashData( TotalSize );
  1028. if (BlobStructure != NULL)
  1029. {
  1030. RtlZeroMemory(BlobStructure, sizeof(DFSBLOB_DATA));
  1031. NextBufOffset = (PBYTE)(BlobStructure + 1);
  1032. BlobStructure->Header.RefCount = 1;
  1033. BlobStructure->Header.pvKey = &BlobStructure->BlobName;
  1034. BlobStructure->Header.pData = (PVOID)BlobStructure;
  1035. BlobStructure->SequenceNumber = m_CurrentSequenceNumber;
  1036. BlobStructure->BlobName.Length = BlobName->Length;
  1037. BlobStructure->BlobName.MaximumLength = BlobName->Length + sizeof(WCHAR);
  1038. BlobStructure->BlobName.Buffer = (WCHAR *) (NextBufOffset);
  1039. NextBufOffset = (PBYTE)((ULONG_PTR)(NextBufOffset) +
  1040. BlobName->Length +
  1041. sizeof(WCHAR));
  1042. if (BlobName->Length != 0)
  1043. {
  1044. RtlCopyMemory(BlobStructure->BlobName.Buffer,
  1045. BlobName->Buffer,
  1046. BlobName->Length);
  1047. }
  1048. BlobStructure->BlobName.Buffer[BlobName->Length/sizeof(WCHAR)] = UNICODE_NULL;
  1049. BlobStructure->Size = BlobSize;
  1050. BlobStructure->pBlob = (PBYTE)(NextBufOffset);
  1051. if(pBlobBuffer && BlobSize)
  1052. {
  1053. RtlCopyMemory(BlobStructure->pBlob, pBlobBuffer, BlobSize);
  1054. }
  1055. }
  1056. else
  1057. {
  1058. Status = ERROR_NOT_ENOUGH_MEMORY;
  1059. }
  1060. *pNewBlob = BlobStructure;
  1061. return Status;
  1062. }
  1063. DFSSTATUS
  1064. DfsADBlobCache::CreateSiteBlobIfNecessary(void)
  1065. {
  1066. DFSSTATUS Status = ERROR_SUCCESS;
  1067. PDFSBLOB_DATA pSiteBlob = NULL;
  1068. PBYTE pBuffer = NULL;
  1069. PVOID pUseBuffer = NULL;
  1070. ULONG SiteBlobSize = 0;
  1071. ULONG SizeRemaining = 0;
  1072. GUID NewGuid;
  1073. UNICODE_STRING SiteMetadataName;
  1074. if(m_pBlob == NULL)
  1075. {
  1076. do
  1077. {
  1078. Status = UuidCreate(&NewGuid);
  1079. if (Status != ERROR_SUCCESS)
  1080. {
  1081. break;
  1082. }
  1083. Status = DfsRtlInitUnicodeStringEx(&SiteMetadataName, ADBlobSiteRoot);
  1084. if(Status != ERROR_SUCCESS)
  1085. {
  1086. break;
  1087. }
  1088. SiteBlobSize = sizeof(ULONG) + sizeof(GUID);
  1089. pBuffer = (PBYTE) AllocateShashData (SiteBlobSize);
  1090. if (pBuffer == NULL)
  1091. {
  1092. Status = ERROR_NOT_ENOUGH_MEMORY;
  1093. break;
  1094. }
  1095. pUseBuffer = pBuffer;
  1096. SizeRemaining = SiteBlobSize;
  1097. Status = PackSetGuid( &NewGuid, &pUseBuffer, &SizeRemaining);
  1098. if (Status != ERROR_SUCCESS)
  1099. {
  1100. break;
  1101. }
  1102. Status = PackSetULong( 0, &pUseBuffer, &SizeRemaining );
  1103. if (Status != ERROR_SUCCESS)
  1104. {
  1105. break;
  1106. }
  1107. Status = CreateBlob(&SiteMetadataName,
  1108. pBuffer,
  1109. SiteBlobSize,
  1110. &pSiteBlob);
  1111. if(Status != ERROR_SUCCESS)
  1112. {
  1113. break;
  1114. }
  1115. m_pBlob = pSiteBlob;
  1116. }while(0);
  1117. }
  1118. if (pBuffer)
  1119. {
  1120. DeallocateShashData(pBuffer);
  1121. }
  1122. return Status;
  1123. }
  1124. //
  1125. // UpdateSiteBlob: This routine takes a binary stream and stuffs that
  1126. // as the site information. It gets rid of the old site information.
  1127. // No update is done here, the caller has to call us back to say
  1128. // that data needs to be written out.
  1129. //
  1130. //
  1131. DFSSTATUS
  1132. DfsADBlobCache::UpdateSiteBlob(PVOID pBuffer, ULONG Size)
  1133. {
  1134. DFSSTATUS Status = ERROR_SUCCESS;
  1135. PDFSBLOB_DATA pSiteBlob = NULL;
  1136. UNICODE_STRING SiteMetadataName;
  1137. Status = DfsRtlInitUnicodeStringEx(&SiteMetadataName, ADBlobSiteRoot);
  1138. if(Status == ERROR_SUCCESS)
  1139. {
  1140. Status = CreateBlob(&SiteMetadataName,
  1141. (PBYTE)pBuffer,
  1142. Size,
  1143. &pSiteBlob);
  1144. if(Status == ERROR_SUCCESS)
  1145. {
  1146. if (m_pBlob != NULL)
  1147. {
  1148. DeallocateShashData(m_pBlob);
  1149. }
  1150. m_pBlob = pSiteBlob;
  1151. }
  1152. }
  1153. return Status;
  1154. }
  1155. DFSSTATUS
  1156. DfsADBlobCache::StoreBlobInCache(PUNICODE_STRING BlobName,
  1157. PBYTE pBlobBuffer,
  1158. ULONG BlobSize)
  1159. {
  1160. PDFSBLOB_DATA BlobStructure = NULL;
  1161. NTSTATUS NtStatus = STATUS_SUCCESS;
  1162. DFSSTATUS Status = ERROR_SUCCESS;
  1163. DFS_TRACE_LOW( ADBLOB, "cache %p: Storing Blob %wZ in cache, size %x\n",
  1164. this, BlobName, BlobSize );
  1165. Status = CreateBlob( BlobName,
  1166. pBlobBuffer,
  1167. BlobSize,
  1168. &BlobStructure );
  1169. if (Status == ERROR_SUCCESS)
  1170. {
  1171. if (IsEmptyString(BlobStructure->BlobName.Buffer))
  1172. {
  1173. ReleaseRootBlob();
  1174. m_pRootBlob = BlobStructure;
  1175. }
  1176. else
  1177. {
  1178. NtStatus = SHashInsertKey(m_pTable,
  1179. BlobStructure,
  1180. &BlobStructure->BlobName,
  1181. SHASH_REPLACE_IFFOUND);
  1182. if(NtStatus == STATUS_SUCCESS)
  1183. {
  1184. InterlockedDecrement(&BlobStructure->Header.RefCount);
  1185. }
  1186. else
  1187. {
  1188. DeallocateShashData( BlobStructure );
  1189. Status = RtlNtStatusToDosError(NtStatus);
  1190. }
  1191. }
  1192. }
  1193. DFS_TRACE_LOW( ADBLOB, "cache %p: storing Blob %wZ done, status %x\n",
  1194. this, BlobName, Status);
  1195. return Status;
  1196. }
  1197. DFSSTATUS
  1198. DfsADBlobCache::WriteBlobToAd(
  1199. BOOLEAN ForceFlush)
  1200. {
  1201. DFSSTATUS Status = STATUS_SUCCESS;
  1202. PVOID pHandle = NULL;
  1203. DFS_TRACE_LOW(ADBLOB, "cache %p: writing blob to ad\n", this);
  1204. //
  1205. // ForceFlush flag is currently implemented as a DirectMode
  1206. // specific functionality. Essentially all normal flushes that happen
  1207. // during direct-mode operations are no-ops unless the ForceFlush
  1208. // flag is specified. All regular mode operations are left unaffected.
  1209. //
  1210. if (DfsCheckDirectMode() && !ForceFlush)
  1211. {
  1212. DFS_TRACE_LOW(ADBLOB, "cache %p: WriteBlobToAd is a NOOP\n", this);
  1213. return Status;
  1214. }
  1215. Status = GetCachedADObject ( &pHandle );
  1216. if(Status == ERROR_SUCCESS)
  1217. {
  1218. Status = CacheFlush(pHandle);
  1219. ReleaseADObject( pHandle );
  1220. }
  1221. DFS_TRACE_ERROR_LOW(Status, ADBLOB, "cache %p: writing blob to ad, status %x\n",
  1222. this, Status);
  1223. return Status;
  1224. }
  1225. //+-------------------------------------------------------------------------
  1226. //
  1227. // Function: GetSubBlob
  1228. //
  1229. // Arguments:
  1230. //
  1231. // PUNICODE_STRING pBlobName (name of the sub blob)
  1232. // BYTE **ppBlobBuffer - holds pointer to sub blob buffer
  1233. // PULONG pBlobSize - holds the blob size
  1234. // BYTE **ppBuffer - holds the pointer to the main blob buffer
  1235. // PULONG pSize - holds size of the main blob stream.
  1236. //
  1237. // Returns: Status: Success or Error status code
  1238. //
  1239. // Description: This routine reads the next stream in the main blob, and
  1240. // returns all the information necessary to unravel the
  1241. // sub blob held within the main blob,
  1242. // It adjusts the main blob buffer and size appropriately
  1243. // to point to the next stream or sub-blob within the main
  1244. // blob.
  1245. //
  1246. //--------------------------------------------------------------------------
  1247. DFSSTATUS
  1248. DfsADBlobCache::GetSubBlob(
  1249. PUNICODE_STRING pName,
  1250. BYTE **ppBlobBuffer,
  1251. PULONG pBlobSize,
  1252. BYTE **ppBuffer,
  1253. PULONG pSize )
  1254. {
  1255. DFSSTATUS Status = ERROR_SUCCESS;
  1256. //
  1257. // ppbuffer is the main blob, and it is point to a stream at this
  1258. // point
  1259. // the first part is the name of the sub-blob.
  1260. //
  1261. Status = PackGetString( pName, (PVOID *) ppBuffer, pSize );
  1262. if (Status == ERROR_SUCCESS)
  1263. {
  1264. //
  1265. // now get the size of the sub blob.
  1266. //
  1267. Status = PackGetULong( pBlobSize, (PVOID *) ppBuffer, pSize );
  1268. if (Status == ERROR_SUCCESS)
  1269. {
  1270. if(*pBlobSize > *pSize)
  1271. {
  1272. Status = ERROR_INVALID_DATA ;
  1273. }
  1274. else
  1275. {
  1276. //
  1277. // At this point the main blob is point to the sub-blob itself.
  1278. // So copy the pointer of the main blob so we can return it
  1279. // as the sub blob.
  1280. //
  1281. *ppBlobBuffer = *ppBuffer;
  1282. //
  1283. // update the main blob pointer to point to the next stream
  1284. // in the blob.
  1285. *ppBuffer = (BYTE *)*ppBuffer + *pBlobSize;
  1286. *pSize -= *pBlobSize;
  1287. }
  1288. }
  1289. }
  1290. return Status;
  1291. }
  1292. DFSSTATUS
  1293. DfsADBlobCache::GetNamedBlob(PUNICODE_STRING pBlobName,
  1294. PDFSBLOB_DATA *pBlobStructure)
  1295. {
  1296. DFSSTATUS Status = ERROR_SUCCESS;
  1297. NTSTATUS NtStatus = STATUS_SUCCESS;
  1298. if (IsEmptyString(pBlobName->Buffer))
  1299. {
  1300. *pBlobStructure = AcquireRootBlob();
  1301. if (*pBlobStructure == NULL)
  1302. {
  1303. Status = ERROR_NOT_FOUND;
  1304. }
  1305. }
  1306. else
  1307. {
  1308. NtStatus = SHashGetDataFromTable(m_pTable,
  1309. (void *)pBlobName,
  1310. (void **) pBlobStructure);
  1311. Status = RtlNtStatusToDosError(NtStatus);
  1312. }
  1313. return Status;
  1314. }
  1315. DFSSTATUS
  1316. DfsADBlobCache::SetNamedBlob(PDFSBLOB_DATA pBlobStructure)
  1317. {
  1318. NTSTATUS NtStatus = STATUS_SUCCESS;
  1319. DFSSTATUS Status = ERROR_SUCCESS;
  1320. if (IsEmptyString(pBlobStructure->BlobName.Buffer))
  1321. {
  1322. ReleaseRootBlob();
  1323. m_pRootBlob = pBlobStructure;
  1324. AcquireRootBlob();
  1325. }
  1326. else
  1327. {
  1328. NtStatus = SHashInsertKey(m_pTable,
  1329. pBlobStructure,
  1330. &pBlobStructure->BlobName,
  1331. SHASH_REPLACE_IFFOUND);
  1332. Status = RtlNtStatusToDosError(NtStatus);
  1333. }
  1334. return Status;
  1335. }
  1336. DFSSTATUS
  1337. DfsADBlobCache::RemoveNamedBlob(PUNICODE_STRING pBlobName )
  1338. {
  1339. NTSTATUS NtStatus;
  1340. DFSSTATUS Status = ERROR_SUCCESS;
  1341. if (IsEmptyString(pBlobName->Buffer))
  1342. {
  1343. if (m_pRootBlob == NULL)
  1344. {
  1345. Status = ERROR_NOT_FOUND;
  1346. }
  1347. ReleaseRootBlob();
  1348. }
  1349. else
  1350. {
  1351. NtStatus = SHashRemoveKey(m_pTable,
  1352. pBlobName,
  1353. NULL );
  1354. Status = RtlNtStatusToDosError(NtStatus);
  1355. }
  1356. return Status;
  1357. }
  1358. DWORD
  1359. PackBlobEnumerator( PSHASH_HEADER pEntry,
  1360. void* pContext )
  1361. {
  1362. NTSTATUS Status = STATUS_SUCCESS;
  1363. PUNICODE_STRING pBlobName = (PUNICODE_STRING) pEntry->pvKey;
  1364. PDFSBLOB_DATA pBlobStructure = (PDFSBLOB_DATA) pEntry;
  1365. PPACKBLOB_ENUMCTX pEnumCtx = (PPACKBLOB_ENUMCTX) pContext;
  1366. if (pBlobStructure->SequenceNumber == pEnumCtx->SequenceNumber)
  1367. {
  1368. Status = AddStreamToBlob( pBlobName,
  1369. pBlobStructure->pBlob,
  1370. pBlobStructure->Size,
  1371. &pEnumCtx->pBuffer,
  1372. &pEnumCtx->Size );
  1373. pEnumCtx->NumItems++;
  1374. pEnumCtx->CurrentSize += (pBlobName->Length +
  1375. sizeof(USHORT) +
  1376. sizeof(ULONG) +
  1377. pBlobStructure->Size);
  1378. }
  1379. return Status;
  1380. }
  1381. //
  1382. // skeleton of pack blob.
  1383. // The buffer is passed in. The length is passed in.
  1384. // If the information does not fit the buffer, return required length.
  1385. // Required for API implementation.
  1386. //
  1387. //
  1388. DFSSTATUS
  1389. DfsADBlobCache::PackBlob(
  1390. BYTE *pBuffer,
  1391. PULONG pLength,
  1392. PULONG TotalBlobBytes )
  1393. {
  1394. ULONG Discard = 0;
  1395. DFSSTATUS Status = ERROR_SUCCESS;
  1396. NTSTATUS NtStatus = STATUS_SUCCESS;
  1397. BYTE *pUseBuffer = NULL;
  1398. BYTE *pSavedBuffer = NULL;
  1399. ULONG SavedBufferSize = 0;
  1400. ULONG BufferSize = 0;
  1401. PACKBLOB_ENUMCTX EnumCtx;
  1402. pUseBuffer = pBuffer;
  1403. BufferSize = *pLength;
  1404. DFS_TRACE_LOW(ADBLOB, "BlobCache %p: packing blob\n", this);
  1405. //
  1406. // dfsdev: investigate what the first ulong is and add comment
  1407. // here as to why we are setting it to 0.
  1408. //
  1409. Status = PackSetULong( 0, (PVOID *) &pUseBuffer, &BufferSize );
  1410. if (Status == ERROR_SUCCESS)
  1411. {
  1412. //save the place where we should write back the number of objects
  1413. pSavedBuffer = pUseBuffer;
  1414. SavedBufferSize = BufferSize;
  1415. //
  1416. // the next argument is the number of objects in the blob.
  1417. // set 0 until we find how many blobs there are
  1418. //
  1419. Status = PackSetULong(0, (PVOID *) &pUseBuffer, &BufferSize);
  1420. }
  1421. if (Status == ERROR_SUCCESS)
  1422. {
  1423. EnumCtx.pBuffer = pUseBuffer;
  1424. EnumCtx.Size = BufferSize;
  1425. EnumCtx.NumItems = 0;
  1426. EnumCtx.SequenceNumber = m_CurrentSequenceNumber;
  1427. EnumCtx.CurrentSize = sizeof(ULONG);
  1428. }
  1429. if (Status == ERROR_SUCCESS)
  1430. {
  1431. if (m_pRootBlob != NULL)
  1432. {
  1433. PDFSBLOB_DATA pRootBlob;
  1434. UNICODE_STRING RootMetadataName;
  1435. Status = DfsRtlInitUnicodeStringEx(&RootMetadataName, ADBlobMetaDataNamePrefix);
  1436. if(Status == ERROR_SUCCESS)
  1437. {
  1438. Status = CreateBlob( &RootMetadataName,
  1439. m_pRootBlob->pBlob,
  1440. m_pRootBlob->Size,
  1441. &pRootBlob);
  1442. if (Status == ERROR_SUCCESS)
  1443. {
  1444. Status = PackBlobEnumerator( (SHASH_HEADER *)pRootBlob, (PVOID) &EnumCtx);
  1445. DeallocateShashData(pRootBlob);
  1446. }
  1447. }
  1448. }
  1449. }
  1450. if (Status == ERROR_SUCCESS)
  1451. {
  1452. NtStatus = ShashEnumerateItems(m_pTable,
  1453. PackBlobEnumerator,
  1454. &EnumCtx);
  1455. //dfsdev: make sure that shash enumerate retuns NTSTATUS.
  1456. // it does not appear to do so... I think it is the packblobenumerator
  1457. // that is returning a non-ntstatus. Till we fix it dont convert err
  1458. // Status = RtlNtStatusToDosError(NtStatus);
  1459. Status = NtStatus;
  1460. }
  1461. //
  1462. // Now add the site blob as the LAST blob. It appears that old
  1463. // downlevel dfs may rely on this.
  1464. //
  1465. if (Status == ERROR_SUCCESS)
  1466. {
  1467. CreateSiteBlobIfNecessary();
  1468. if (m_pBlob != NULL)
  1469. {
  1470. Status = PackBlobEnumerator( (SHASH_HEADER *) m_pBlob, (PVOID) &EnumCtx);
  1471. }
  1472. }
  1473. if (Status == ERROR_SUCCESS)
  1474. {
  1475. if (EnumCtx.NumItems > 0)
  1476. {
  1477. Status = PackSetULong(EnumCtx.NumItems,
  1478. (PVOID *) &pSavedBuffer,
  1479. &SavedBufferSize);
  1480. EnumCtx.CurrentSize += sizeof(ULONG);
  1481. }
  1482. *TotalBlobBytes = EnumCtx.CurrentSize;
  1483. }
  1484. m_BlobSize = *TotalBlobBytes;
  1485. //*TotalBlobBytes = (ULONG) (EnumCtx.pBuffer - pBuffer);
  1486. DFS_TRACE_ERROR_LOW( Status, ADBLOB, "BlobCache %p, PackBlob status %x\n",
  1487. this, Status);
  1488. return Status;
  1489. }
  1490. ULONG
  1491. DfsADBlobCache::GetBlobSize()
  1492. {
  1493. return m_BlobSize;
  1494. }
  1495. PDFSBLOB_DATA
  1496. DfsADBlobCache::FindFirstBlob(PDFSBLOB_ITER pIter)
  1497. {
  1498. PDFSBLOB_DATA pBlob = NULL;
  1499. pIter->RootReferenced = AcquireRootBlob();
  1500. if (pIter->RootReferenced != NULL)
  1501. {
  1502. pIter->Started = FALSE;
  1503. pBlob = pIter->RootReferenced;
  1504. }
  1505. else
  1506. {
  1507. pIter->Started = TRUE;
  1508. pBlob = (PDFSBLOB_DATA) SHashStartEnumerate(&pIter->Iter, m_pTable);
  1509. }
  1510. return pBlob;
  1511. }
  1512. PDFSBLOB_DATA
  1513. DfsADBlobCache::FindNextBlob(PDFSBLOB_ITER pIter)
  1514. {
  1515. PDFSBLOB_DATA pBlob = NULL;
  1516. if (pIter->Started == FALSE)
  1517. {
  1518. pIter->Started = TRUE;
  1519. pBlob = (PDFSBLOB_DATA) SHashStartEnumerate(&pIter->Iter, m_pTable);
  1520. }
  1521. else
  1522. {
  1523. pBlob = (PDFSBLOB_DATA) SHashNextEnumerate(&pIter->Iter, m_pTable);
  1524. }
  1525. return pBlob;
  1526. }
  1527. void
  1528. DfsADBlobCache::FindCloseBlob(PDFSBLOB_ITER pIter)
  1529. {
  1530. if (pIter->RootReferenced)
  1531. {
  1532. ReleaseBlobReference(pIter->RootReferenced);
  1533. pIter->RootReferenced = NULL;
  1534. }
  1535. if (pIter->Started)
  1536. {
  1537. SHashFinishEnumerate(&pIter->Iter, m_pTable);
  1538. pIter->Started = FALSE;
  1539. }
  1540. }
  1541. DFSSTATUS
  1542. AddStreamToBlob(PUNICODE_STRING BlobName,
  1543. BYTE *pBlobBuffer,
  1544. ULONG BlobSize,
  1545. BYTE ** pUseBuffer,
  1546. ULONG *BufferSize )
  1547. {
  1548. DFSSTATUS Status = ERROR_SUCCESS;
  1549. Status = PackSetString(BlobName, (PVOID *) pUseBuffer, BufferSize);
  1550. if(Status == ERROR_SUCCESS)
  1551. {
  1552. Status = PackSetULong(BlobSize, (PVOID *) pUseBuffer, BufferSize);
  1553. if(Status == ERROR_SUCCESS)
  1554. {
  1555. if ( *BufferSize >= BlobSize )
  1556. {
  1557. RtlCopyMemory((*pUseBuffer), pBlobBuffer, BlobSize);
  1558. *pUseBuffer = (BYTE *)((ULONG_PTR)*pUseBuffer + BlobSize);
  1559. *BufferSize -= BlobSize;
  1560. }
  1561. else
  1562. {
  1563. Status = ERROR_BUFFER_OVERFLOW;
  1564. }
  1565. }
  1566. }
  1567. if (Status == ERROR_INVALID_DATA)
  1568. {
  1569. Status = ERROR_BUFFER_OVERFLOW;
  1570. }
  1571. return Status;
  1572. }
  1573. PVOID
  1574. AllocateShashData(ULONG Size )
  1575. {
  1576. PVOID RetValue = NULL;
  1577. if (Size)
  1578. {
  1579. RetValue = (PVOID) new BYTE[Size];
  1580. }
  1581. return RetValue;
  1582. }
  1583. VOID
  1584. DeallocateShashData(PVOID pPointer )
  1585. {
  1586. if(pPointer)
  1587. {
  1588. delete [] (PBYTE)pPointer;
  1589. }
  1590. }
  1591. DFSSTATUS
  1592. DfsADBlobCache::DfsDoesUserHaveAccess(DWORD DesiredAccess)
  1593. {
  1594. DFSSTATUS Status = ERROR_SUCCESS;
  1595. PSECURITY_DESCRIPTOR pSD = NULL;
  1596. PVOID pHandle = NULL;
  1597. UNICODE_STRING ObjectDN;
  1598. DFS_TRACE_LOW(ADBLOB, "BlobCache %p: DfsADBlobCache::DfsDoesUserHaveAccess\n", this);
  1599. do
  1600. {
  1601. Status = GetCachedADObject ( &pHandle );
  1602. if(Status != ERROR_SUCCESS)
  1603. {
  1604. DFS_TRACE_ERROR_HIGH( Status, ADBLOB, "DfsADBlobCache::DfsDoesUserHaveAccess: GetCachedADObject failed status %x\n",
  1605. Status);
  1606. break;
  1607. }
  1608. Status = GetObjectDN(&ObjectDN);
  1609. if(Status != ERROR_SUCCESS)
  1610. {
  1611. DFS_TRACE_ERROR_HIGH( Status, ADBLOB, "DfsADBlobCache::DfsDoesUserHaveAccess: GetObjectDN failed status %x\n",
  1612. Status);
  1613. break;
  1614. }
  1615. Status = DfsGetObjSecurity((LDAP *) pHandle,
  1616. ObjectDN.Buffer,
  1617. &pSD);
  1618. if(Status != ERROR_SUCCESS)
  1619. {
  1620. DFS_TRACE_ERROR_HIGH( Status, ADBLOB, "DfsADBlobCache::DfsDoesUserHaveAccess: DfsGetObjectSecurity failed status %x\n",
  1621. Status);
  1622. break;
  1623. }
  1624. Status = DfsDoesUserHaveDesiredAccessToAd(DesiredAccess,
  1625. pSD);
  1626. if(Status != ERROR_SUCCESS)
  1627. {
  1628. DFS_TRACE_ERROR_HIGH( Status, ADBLOB, "DfsADBlobCache::DfsDoesUserHaveAccess: DfsDoesUserHaveDesiredAccessToAd failed status %x\n",
  1629. Status);
  1630. break;
  1631. }
  1632. }while (0);
  1633. if(pHandle != NULL)
  1634. {
  1635. ReleaseADObject( pHandle );
  1636. }
  1637. if(pSD)
  1638. {
  1639. DfsDeallocateSecurityData (pSD);
  1640. }
  1641. return Status;
  1642. }