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.

1186 lines
36 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include <windows.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <stddef.h>
  8. #include "dfsheader.h"
  9. #include "dfsmisc.h"
  10. #include <shellapi.h>
  11. #include <ole2.h>
  12. #include <activeds.h>
  13. #include <DfsServerLibrary.hxx>
  14. #include <WinLdap.h>
  15. #include <NtLdap.h>
  16. #include "dfsutil.hxx"
  17. #include "dsgetdc.h"
  18. #include <dsrole.h>
  19. #include "DfsBlobInfo.hxx"
  20. #define ADBlobAttribute L"pKT"
  21. #define ADBlobPktGuidAttribute L"pKTGuid"
  22. #define ADBlobSiteRoot L"\\siteroot"
  23. #define DFS_AD_CONFIG_DATA L"CN=Dfs-configuration, CN=System"
  24. DFSSTATUS
  25. DfsWriteBlobToFile(
  26. PBYTE pBlob,
  27. ULONG BlobSize,
  28. LPWSTR FileName);
  29. DFSSTATUS
  30. DfsCreateDN(
  31. OUT LPWSTR PathString,
  32. IN size_t CharacterCount,
  33. LPWSTR DCName,
  34. LPWSTR PathPrefix,
  35. LPWSTR *CNNames );
  36. DFSSTATUS
  37. DfsGenerateRootCN(
  38. LPWSTR RootName,
  39. LPWSTR *pRootCNName);
  40. DFSSTATUS
  41. DfsGenerateADPathString(
  42. IN LPWSTR DCName,
  43. IN LPWSTR ObjectName,
  44. IN LPWSTR PathPrefix,
  45. OUT LPOLESTR *pPathString);
  46. extern LPWSTR RootDseString;
  47. //
  48. // The prefix for AD path string. This is used to generate a path of
  49. // the form "LDAP://<dcname>/CN=,...DC=,..."
  50. //
  51. extern LPWSTR LdapPrefixString;
  52. //
  53. // The first part of this file contains the marshalling/unmarshalling
  54. // routines that are used by the old stores (registry and AD)
  55. // These routines help us read a binary blob and unravel their contents.
  56. //
  57. // the latter part defines the common store class for all our stores.
  58. //
  59. #define BYTE_0_MASK 0xFF
  60. #define BYTE_0(Value) (UCHAR)( (Value) & BYTE_0_MASK)
  61. #define BYTE_1(Value) (UCHAR)( ((Value) >> 8) & BYTE_0_MASK)
  62. #define BYTE_2(Value) (UCHAR)( ((Value) >> 16) & BYTE_0_MASK)
  63. #define BYTE_3(Value) (UCHAR)( ((Value) >> 24) & BYTE_0_MASK)
  64. #define MTYPE_BASE_TYPE (0x0000ffffL)
  65. #define MTYPE_COMPOUND (0x00000001L)
  66. #define MTYPE_GUID (0x00000002L)
  67. #define MTYPE_ULONG (0x00000003L)
  68. #define MTYPE_USHORT (0x00000004L)
  69. #define MTYPE_PWSTR (0x00000005L)
  70. #define MTYPE_UCHAR (0x00000006L)
  71. #define _MCode_Base(t,s,m,i)\
  72. {t,offsetof(s,m),0L,0L,i}
  73. #define _MCode_struct(s,m,i)\
  74. _MCode_Base(MTYPE_COMPOUND,s,m,i)
  75. #define _MCode_pwstr(s,m)\
  76. _MCode_Base(MTYPE_PWSTR,s,m,NULL)
  77. #define _MCode_ul(s,m)\
  78. _MCode_Base(MTYPE_ULONG,s,m,NULL)
  79. #define _MCode_guid(s,m)\
  80. _MCode_Base(MTYPE_GUID,s,m,NULL)
  81. #define _mkMarshalInfo(s, i)\
  82. {(ULONG)sizeof(s),(ULONG)(sizeof(i)/sizeof(MARSHAL_TYPE_INFO)),i}
  83. typedef struct _MARSHAL_TYPE_INFO
  84. {
  85. ULONG _type; // the type of item to be marshalled
  86. ULONG _off; // offset of item (in the struct)
  87. ULONG _cntsize; // size of counter for counted array
  88. ULONG _cntoff; // else, offset count item (in the struct)
  89. struct _MARSHAL_INFO * _subinfo;// if compound type, need info
  90. } MARSHAL_TYPE_INFO, *PMARSHAL_TYPE_INFO;
  91. typedef struct _MARSHAL_INFO
  92. {
  93. ULONG _size; // size of item
  94. ULONG _typecnt; // number of type infos
  95. PMARSHAL_TYPE_INFO _typeInfo; // type infos
  96. } MARSHAL_INFO, *PMARSHAL_INFO;
  97. extern MARSHAL_INFO MiFileTime;
  98. #define INIT_FILE_TIME_INFO() \
  99. static MARSHAL_TYPE_INFO _MCode_FileTime[] = { \
  100. _MCode_ul(FILETIME, dwLowDateTime), \
  101. _MCode_ul(FILETIME, dwHighDateTime), \
  102. }; \
  103. extern MARSHAL_INFO MiFileTime; // = _mkMarshalInfo(FILETIME, _MCode_FileTime);
  104. //
  105. // Marshalling info for DFS_REPLICA_INFO structure
  106. //
  107. extern MARSHAL_INFO MiDfsReplicaInfo;
  108. #define INIT_DFS_REPLICA_INFO_MARSHAL_INFO() \
  109. static MARSHAL_TYPE_INFO _MCode_DfsReplicaInfo[] = { \
  110. _MCode_struct(DFS_REPLICA_INFORMATION, ReplicaTimeStamp, &MiFileTime), \
  111. _MCode_ul(DFS_REPLICA_INFORMATION, ReplicaState), \
  112. _MCode_ul(DFS_REPLICA_INFORMATION, ReplicaType), \
  113. _MCode_pwstr(DFS_REPLICA_INFORMATION, ServerName), \
  114. _MCode_pwstr(DFS_REPLICA_INFORMATION, ShareName), \
  115. }; \
  116. extern MARSHAL_INFO MiDfsReplicaInfo;// = _mkMarshalInfo(DFS_REPLICA_INFORMATION, _MCode_DfsReplicaInfo);
  117. extern MARSHAL_INFO MiADBlobDfsIdProperty;
  118. #define INIT_ADBLOB_DFS_ID_PROPERTY_INFO() \
  119. static MARSHAL_TYPE_INFO _MCode_ADBlobDfsIdProperty[] = { \
  120. _MCode_guid(DFS_NAME_INFORMATION, VolumeId), \
  121. _MCode_pwstr(DFS_NAME_INFORMATION, Prefix), \
  122. _MCode_pwstr(DFS_NAME_INFORMATION, ShortPrefix), \
  123. _MCode_ul(DFS_NAME_INFORMATION, Type), \
  124. _MCode_ul(DFS_NAME_INFORMATION, State), \
  125. _MCode_pwstr(DFS_NAME_INFORMATION, Comment), \
  126. _MCode_struct(DFS_NAME_INFORMATION, PrefixTimeStamp, &MiFileTime), \
  127. _MCode_struct(DFS_NAME_INFORMATION, StateTimeStamp, &MiFileTime), \
  128. _MCode_struct(DFS_NAME_INFORMATION, CommentTimeStamp, &MiFileTime), \
  129. _MCode_ul(DFS_NAME_INFORMATION, Version), \
  130. }; \
  131. extern MARSHAL_INFO MiADBlobDfsIdProperty; //= _mkMarshalInfo(DFS_NAME_INFORMATION, _MCode_ADBlobDfsIdProperty);
  132. extern MARSHAL_INFO MiStdDfsIdProperty;
  133. //+-------------------------------------------------------------------------
  134. //
  135. // Function: PackSetInformation - packs information based on MARSHAL_INFO struct
  136. //
  137. // Arguments: pInfo - pointer to the info buffer to pack
  138. // ppBuffer - pointer to buffer that holds the binary stream.
  139. // pSizeRemaining - pointer to size of above buffer
  140. // pMarshalInfo - pointer to information that describes how to
  141. // pack the info into the binary stream.
  142. //
  143. // Returns: Status
  144. // ERROR_SUCCESS if we could pack the info
  145. // error status otherwise.
  146. //
  147. //
  148. // Description: This routine expects the binary stream can hold all the
  149. // information that is necessary to pack the information
  150. // described by the MARSHAL_INFO structure.
  151. //--------------------------------------------------------------------------
  152. DFSSTATUS
  153. PackSetInformation(
  154. ULONG_PTR Info,
  155. PVOID *ppBuffer,
  156. PULONG pSizeRemaining,
  157. PMARSHAL_INFO pMarshalInfo )
  158. {
  159. PMARSHAL_TYPE_INFO typeInfo;
  160. DFSSTATUS Status = ERROR_INVALID_DATA;
  161. for ( typeInfo = &pMarshalInfo->_typeInfo[0];
  162. typeInfo < &pMarshalInfo->_typeInfo[pMarshalInfo->_typecnt];
  163. typeInfo++ )
  164. {
  165. switch ( typeInfo->_type & MTYPE_BASE_TYPE )
  166. {
  167. case MTYPE_COMPOUND:
  168. Status = PackSetInformation( Info + typeInfo->_off,
  169. ppBuffer,
  170. pSizeRemaining,
  171. typeInfo->_subinfo);
  172. break;
  173. case MTYPE_ULONG:
  174. Status = PackSetULong( *(PULONG)(Info + typeInfo->_off),
  175. ppBuffer,
  176. pSizeRemaining );
  177. break;
  178. case MTYPE_PWSTR:
  179. Status = PackSetString( (PUNICODE_STRING)(Info + typeInfo->_off),
  180. ppBuffer,
  181. pSizeRemaining );
  182. break;
  183. case MTYPE_GUID:
  184. Status = PackSetGuid( (GUID *)(Info + typeInfo->_off),
  185. ppBuffer,
  186. pSizeRemaining );
  187. break;
  188. default:
  189. break;
  190. }
  191. }
  192. return Status;
  193. }
  194. DFSSTATUS
  195. DfsLdapConnect(
  196. LPWSTR DCName,
  197. LDAP **ppLdap )
  198. {
  199. LDAP *pLdap = NULL;
  200. DFSSTATUS Status = ERROR_SUCCESS;
  201. LPWSTR DCNameToUse = NULL;
  202. const TCHAR * apszSubStrings[4];
  203. DCNameToUse = DCName;
  204. apszSubStrings[0] = DCNameToUse;
  205. pLdap = ldap_initW(DCNameToUse, LDAP_PORT);
  206. if (pLdap != NULL)
  207. {
  208. Status = ldap_set_option(pLdap, LDAP_OPT_AREC_EXCLUSIVE, LDAP_OPT_ON);
  209. if (Status == LDAP_SUCCESS)
  210. {
  211. Status = ldap_bind_s(pLdap, NULL, NULL, LDAP_AUTH_SSPI);
  212. }
  213. }
  214. else
  215. {
  216. Status = LdapGetLastError();
  217. Status = LdapMapErrorToWin32(Status);
  218. }
  219. *ppLdap = pLdap;
  220. return Status;
  221. }
  222. // Initialize the common marshalling info for Registry and ADLegacy stores.
  223. //
  224. INIT_FILE_TIME_INFO();
  225. INIT_DFS_REPLICA_INFO_MARSHAL_INFO();
  226. //+-------------------------------------------------------------------------
  227. //
  228. // Function: PackGetInfo - unpacks information based on MARSHAL_INFO struct
  229. //
  230. // Arguments: pInfo - pointer to the info to fill.
  231. // ppBuffer - pointer to buffer that holds the binary stream.
  232. // pSizeRemaining - pointer to size of above buffer
  233. // pMarshalInfo - pointer to information that describes how to
  234. // interpret the binary stream.
  235. //
  236. // Returns: Status
  237. // ERROR_SUCCESS if we could unpack the name info
  238. // error status otherwise.
  239. //
  240. //
  241. // Description: This routine expects the binary stream to hold all the
  242. // information that is necessary to return the information
  243. // described by the MARSHAL_INFO structure.
  244. //--------------------------------------------------------------------------
  245. DFSSTATUS
  246. PackGetInformation(
  247. ULONG_PTR Info,
  248. PVOID *ppBuffer,
  249. PULONG pSizeRemaining,
  250. PMARSHAL_INFO pMarshalInfo )
  251. {
  252. PMARSHAL_TYPE_INFO typeInfo;
  253. DFSSTATUS Status = ERROR_INVALID_DATA;
  254. for ( typeInfo = &pMarshalInfo->_typeInfo[0];
  255. typeInfo < &pMarshalInfo->_typeInfo[pMarshalInfo->_typecnt];
  256. typeInfo++ )
  257. {
  258. switch ( typeInfo->_type & MTYPE_BASE_TYPE )
  259. {
  260. case MTYPE_COMPOUND:
  261. Status = PackGetInformation(Info + typeInfo->_off,
  262. ppBuffer,
  263. pSizeRemaining,
  264. typeInfo->_subinfo);
  265. break;
  266. case MTYPE_ULONG:
  267. Status = PackGetULong( (PULONG)(Info + typeInfo->_off),
  268. ppBuffer,
  269. pSizeRemaining );
  270. break;
  271. case MTYPE_PWSTR:
  272. Status = PackGetString( (PUNICODE_STRING)(Info + typeInfo->_off),
  273. ppBuffer,
  274. pSizeRemaining );
  275. break;
  276. case MTYPE_GUID:
  277. Status = PackGetGuid( (GUID *)(Info + typeInfo->_off),
  278. ppBuffer,
  279. pSizeRemaining );
  280. break;
  281. default:
  282. break;
  283. }
  284. }
  285. return Status;
  286. }
  287. //+-------------------------------------------------------------------------
  288. //
  289. // Function: PackSizeInformation - packs information based on MARSHAL_INFO struct
  290. //
  291. // Arguments: pInfo - pointer to the info buffer to pack
  292. // ppBuffer - pointer to buffer that holds the binary stream.
  293. // pSizeRemaining - pointer to size of above buffer
  294. // pMarshalInfo - pointer to information that describes how to
  295. // pack the info into the binary stream.
  296. //
  297. // Returns: Status
  298. // ERROR_SUCCESS if we could pack the info
  299. // error status otherwise.
  300. //
  301. //
  302. // Description: This routine expects the binary stream can hold all the
  303. // information that is necessary to pack the information
  304. // described by the MARSHAL_INFO structure.
  305. //--------------------------------------------------------------------------
  306. ULONG
  307. PackSizeInformation(
  308. ULONG_PTR Info,
  309. PMARSHAL_INFO pMarshalInfo )
  310. {
  311. PMARSHAL_TYPE_INFO typeInfo;
  312. ULONG Size = 0;
  313. for ( typeInfo = &pMarshalInfo->_typeInfo[0];
  314. typeInfo < &pMarshalInfo->_typeInfo[pMarshalInfo->_typecnt];
  315. typeInfo++ )
  316. {
  317. switch ( typeInfo->_type & MTYPE_BASE_TYPE )
  318. {
  319. case MTYPE_COMPOUND:
  320. Size += PackSizeInformation( Info + typeInfo->_off,
  321. typeInfo->_subinfo);
  322. break;
  323. case MTYPE_ULONG:
  324. Size += PackSizeULong();
  325. break;
  326. case MTYPE_PWSTR:
  327. Size += PackSizeString( (PUNICODE_STRING)(Info + typeInfo->_off) );
  328. break;
  329. case MTYPE_GUID:
  330. Size += PackSizeGuid();
  331. break;
  332. default:
  333. break;
  334. }
  335. }
  336. return Size;
  337. }
  338. INIT_ADBLOB_DFS_ID_PROPERTY_INFO();
  339. //+-------------------------------------------------------------------------
  340. //
  341. // Function: PackGetNameInformation - Unpacks the root/link name info
  342. //
  343. // Arguments: pDfsNameInfo - pointer to the info to fill.
  344. // ppBuffer - pointer to buffer that holds the binary stream.
  345. // pSizeRemaining - pointer to size of above buffer
  346. //
  347. // Returns: Status
  348. // ERROR_SUCCESS if we could unpack the name info
  349. // error status otherwise.
  350. //
  351. //
  352. // Description: This routine expects the binary stream to hold all the
  353. // information that is necessary to return a complete name
  354. // info structure (as defined by MiADBlobDfsIdProperty). If the stream
  355. // does not have the sufficient
  356. // info, ERROR_INVALID_DATA is returned back.
  357. //
  358. //--------------------------------------------------------------------------
  359. DFSSTATUS
  360. PackGetNameInformation(
  361. IN PDFS_NAME_INFORMATION pDfsNameInfo,
  362. IN OUT PVOID *ppBuffer,
  363. IN OUT PULONG pSizeRemaining)
  364. {
  365. DFSSTATUS Status = STATUS_SUCCESS;
  366. //
  367. // Get the name information from the binary stream.
  368. //
  369. Status = PackGetInformation( (ULONG_PTR)pDfsNameInfo,
  370. ppBuffer,
  371. pSizeRemaining,
  372. &MiADBlobDfsIdProperty );
  373. if (Status == ERROR_SUCCESS)
  374. {
  375. if ((pDfsNameInfo->Type & 0x80) == 0x80)
  376. {
  377. pDfsNameInfo->State |= DFS_VOLUME_FLAVOR_AD_BLOB;
  378. }
  379. }
  380. return Status;
  381. }
  382. DFSSTATUS
  383. PackGetStandaloneNameInformation(
  384. IN PDFS_NAME_INFORMATION pDfsNameInfo,
  385. IN OUT PVOID *ppBuffer,
  386. IN OUT PULONG pSizeRemaining)
  387. {
  388. DFSSTATUS Status = STATUS_SUCCESS;
  389. RtlZeroMemory(pDfsNameInfo, sizeof(DFS_NAME_INFORMATION));
  390. //
  391. // Get the name information from the binary stream.
  392. //
  393. Status = PackGetInformation( (ULONG_PTR)pDfsNameInfo,
  394. ppBuffer,
  395. pSizeRemaining,
  396. &MiStdDfsIdProperty );
  397. if (Status == ERROR_SUCCESS)
  398. {
  399. if ((pDfsNameInfo->Type & 0x80) == 0x80)
  400. {
  401. pDfsNameInfo->State |= DFS_VOLUME_FLAVOR_STANDALONE;
  402. }
  403. }
  404. return Status;
  405. }
  406. ULONG
  407. PackSizeNameInformation(
  408. IN PDFS_NAME_INFORMATION pDfsNameInfo )
  409. {
  410. ULONG Size;
  411. Size = PackSizeInformation( (ULONG_PTR)pDfsNameInfo,
  412. &MiStdDfsIdProperty );
  413. Size += PackSizeULong();
  414. return Size;
  415. }
  416. //+-------------------------------------------------------------------------
  417. //
  418. // Function: PackSetNameInformation - Packs the root/link name info
  419. //
  420. // Arguments: pDfsNameInfo - pointer to the info to pack.
  421. // ppBuffer - pointer to buffer that holds the binary stream.
  422. // pSizeRemaining - pointer to size of above buffer
  423. //
  424. // Returns: Status
  425. // ERROR_SUCCESS if we could pack the name info
  426. // error status otherwise.
  427. //
  428. //
  429. // Description: This routine takes the passedin name information and
  430. // stores it in the binary stream passed in.
  431. //
  432. //--------------------------------------------------------------------------
  433. DFSSTATUS
  434. PackSetStandaloneNameInformation(
  435. IN PDFS_NAME_INFORMATION pDfsNameInfo,
  436. IN OUT PVOID *ppBuffer,
  437. IN OUT PULONG pSizeRemaining)
  438. {
  439. DFSSTATUS Status;
  440. pDfsNameInfo->State &= ~DFS_VOLUME_FLAVORS;
  441. pDfsNameInfo->PrefixTimeStamp = pDfsNameInfo->LastModifiedTime;
  442. pDfsNameInfo->StateTimeStamp = pDfsNameInfo->LastModifiedTime;
  443. pDfsNameInfo->CommentTimeStamp = pDfsNameInfo->LastModifiedTime;
  444. //
  445. // Store the DfsNameInfo in the stream first.
  446. //
  447. Status = PackSetInformation( (ULONG_PTR)pDfsNameInfo,
  448. ppBuffer,
  449. pSizeRemaining,
  450. &MiStdDfsIdProperty );
  451. //
  452. // Follow that info with the timeout information.
  453. // xxx this is not present in win2k?
  454. /* if ( Status == ERROR_SUCCESS )
  455. {
  456. Status = PackSetULong( pDfsNameInfo->Timeout,
  457. ppBuffer,
  458. pSizeRemaining);
  459. } */
  460. return Status;
  461. }
  462. //+-------------------------------------------------------------------------
  463. //
  464. // Function: PackGetReplicaInformation - Unpacks the replica info
  465. //
  466. // Arguments: pDfsReplicaInfo - pointer to the info to fill.
  467. // ppBuffer - pointer to buffer that holds the binary stream.
  468. // pSizeRemaining - pointer to size of above buffer
  469. //
  470. // Returns: Status
  471. // ERROR_SUCCESS if we could unpack the name info
  472. // error status otherwise.
  473. //
  474. //
  475. // Description: This routine expects the binary stream to hold all the
  476. // information that is necessary to return a complete replica
  477. // info structure (as defined by MiDfsReplicaInfo). If the stream
  478. // does not have the sufficient info, ERROR_INVALID_DATA is
  479. // returned back.
  480. // This routine expects to find "replicaCount" number of individual
  481. // binary streams in passed in buffer. Each stream starts with
  482. // the size of the stream, followed by that size of data.
  483. //
  484. //--------------------------------------------------------------------------
  485. DFSSTATUS
  486. PackGetReplicaInformation(
  487. PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo,
  488. PVOID *ppBuffer,
  489. PULONG pSizeRemaining)
  490. {
  491. ULONG Count;
  492. ULONG ReplicaSizeRemaining;
  493. PVOID nextStream;
  494. DFSSTATUS Status = ERROR_SUCCESS;
  495. for ( Count = 0; Count < pReplicaListInfo->ReplicaCount; Count++ )
  496. {
  497. PDFS_REPLICA_INFORMATION pReplicaInfo;
  498. pReplicaInfo = &pReplicaListInfo->pReplicas[Count];
  499. //
  500. // We now have a binary stream in ppBuffer, the first word of which
  501. // indicates the size of this stream.
  502. //
  503. Status = PackGetULong( &pReplicaInfo->DataSize,
  504. ppBuffer,
  505. pSizeRemaining );
  506. //
  507. // ppBuffer is now pointing past the size (to the binary stream)
  508. // because UnpackUlong added size of ulong to it.
  509. // Unravel that stream into the next array element.
  510. // Note that when this unpack returns, the ppBuffer is not necessarily
  511. // pointing to the next binary stream within this blob.
  512. //
  513. if ( Status == ERROR_SUCCESS )
  514. {
  515. nextStream = *ppBuffer;
  516. ReplicaSizeRemaining = pReplicaInfo->DataSize;
  517. Status = PackGetInformation( (ULONG_PTR)pReplicaInfo,
  518. ppBuffer,
  519. &ReplicaSizeRemaining,
  520. &MiDfsReplicaInfo );
  521. //
  522. // We now point the buffer to the next sub-stream, which is the previos
  523. // stream + the size of the stream. We also set the remaining size
  524. // appropriately.
  525. //
  526. *ppBuffer = (PVOID)((ULONG_PTR)nextStream + pReplicaInfo->DataSize);
  527. *pSizeRemaining -= pReplicaInfo->DataSize;
  528. }
  529. if ( Status != ERROR_SUCCESS )
  530. {
  531. break;
  532. }
  533. }
  534. return Status;
  535. }
  536. DFSSTATUS
  537. GetSubBlob(
  538. PUNICODE_STRING pName,
  539. BYTE **ppBlobBuffer,
  540. PULONG pBlobSize,
  541. BYTE **ppBuffer,
  542. PULONG pSize )
  543. {
  544. DFSSTATUS Status = ERROR_SUCCESS;
  545. //
  546. // ppbuffer is the main blob, and it is point to a stream at this
  547. // point
  548. // the first part is the name of the sub-blob.
  549. //
  550. Status = PackGetString( pName, (PVOID *) ppBuffer, pSize );
  551. if (Status == ERROR_SUCCESS)
  552. {
  553. //
  554. // now get the size of the sub blob.
  555. //
  556. Status = PackGetULong( pBlobSize, (PVOID *) ppBuffer, pSize );
  557. if (Status == ERROR_SUCCESS)
  558. {
  559. //
  560. // At this point the main blob is point to the sub-blob itself.
  561. // So copy the pointer of the main blob so we can return it
  562. // as the sub blob.
  563. //
  564. *ppBlobBuffer = *ppBuffer;
  565. //
  566. // update the main blob pointer to point to the next stream
  567. // in the blob.
  568. *ppBuffer = (BYTE *)*ppBuffer + *pBlobSize;
  569. *pSize -= *pBlobSize;
  570. }
  571. }
  572. return Status;
  573. }
  574. VOID
  575. DumpNameInformation(
  576. PDFS_NAME_INFORMATION pNameInfo)
  577. {
  578. ShowInformation((L"Name is %wZ, State %x, Type %x, Comment \"%wZ\"\n",
  579. &pNameInfo->Prefix, pNameInfo->State, pNameInfo->Type,
  580. &pNameInfo->Comment));
  581. return;
  582. }
  583. VOID
  584. DumpReplicaInformation(
  585. PDFS_REPLICA_LIST_INFORMATION pReplicaInfo)
  586. {
  587. ULONG x;
  588. ShowInformation((L"Replica Count %d\n", pReplicaInfo->ReplicaCount));
  589. for (x = 0; x < pReplicaInfo->ReplicaCount; x++)
  590. {
  591. ShowInformation((L"Replica %x, Server %wZ Share %wZ\n",
  592. x,
  593. &pReplicaInfo->pReplicas[x].ServerName,
  594. &pReplicaInfo->pReplicas[x].ShareName ));
  595. }
  596. return;
  597. }
  598. DFSSTATUS
  599. UnpackBlob(
  600. BYTE *pBuffer,
  601. PULONG pLength,
  602. BOOLEAN Show )
  603. {
  604. ULONG Discard = 0;
  605. DFSSTATUS Status = ERROR_SUCCESS;
  606. BYTE *pUseBuffer = NULL;
  607. ULONG BufferSize = 0;
  608. ULONG ObjNdx = 0;
  609. ULONG TotalObjects = 0;
  610. ULONG BlobSize = 0;
  611. ULONG AD_BlobSize = 0;
  612. BYTE *BlobBuffer = NULL;
  613. UNICODE_STRING BlobName;
  614. UNICODE_STRING SiteRoot;
  615. pUseBuffer = pBuffer;
  616. BufferSize = *pLength;
  617. //
  618. // Note the size of the whole blob.
  619. //
  620. AD_BlobSize = BufferSize;
  621. Status = DfsRtlInitUnicodeStringEx( &SiteRoot, ADBlobSiteRoot );
  622. if (Status != ERROR_SUCCESS)
  623. {
  624. goto done;
  625. }
  626. //
  627. // dfsdev: investigate what the first ulong is and add comment
  628. // here as to why we are discarding it.
  629. //
  630. Status = PackGetULong( &Discard, (PVOID *) &pUseBuffer, &BufferSize );
  631. if (Status != ERROR_SUCCESS)
  632. {
  633. goto done;
  634. }
  635. if(BufferSize == 0)
  636. {
  637. goto done;
  638. }
  639. Status = PackGetULong(&TotalObjects, (PVOID *) &pUseBuffer, &BufferSize);
  640. if (Status != ERROR_SUCCESS)
  641. {
  642. goto done;
  643. }
  644. DebugInformation((L"The blob has %d objects, Blob Start Address 0x%x, size 0x%x (%d bytes)\n", TotalObjects,
  645. pBuffer, AD_BlobSize, AD_BlobSize));
  646. for (ObjNdx = 0; ObjNdx < TotalObjects; ObjNdx++)
  647. {
  648. BOOLEAN FoundSite = FALSE;
  649. BOOLEAN FoundRoot = FALSE;
  650. ULONG ReplicaBlobSize;
  651. DebugInformation((L"\n\nGetting blob %d: Offset 0x%x (%d)\n",
  652. ObjNdx + 1,
  653. AD_BlobSize - BufferSize,
  654. AD_BlobSize - BufferSize ));
  655. Status = GetSubBlob( &BlobName,
  656. &BlobBuffer,
  657. &BlobSize,
  658. &pUseBuffer,
  659. &BufferSize );
  660. if (Status == ERROR_SUCCESS)
  661. {
  662. DFS_NAME_INFORMATION NameInfo;
  663. DFS_REPLICA_LIST_INFORMATION ReplicaListInfo;
  664. PVOID pNestedBuffer = BlobBuffer;
  665. ULONG Size = BlobSize;
  666. DebugInformation((L"Found Blob %wZ, Size 0x%x (%d bytes), (address 0x%x)\n",
  667. &BlobName, BlobSize, BlobSize, BlobBuffer));
  668. if (RtlCompareUnicodeString( &BlobName, &SiteRoot, TRUE ) == 0)
  669. {
  670. extern DFSSTATUS DumpSiteBlob(PVOID pBuffer, ULONG Size, BOOLEAN Display);
  671. Status = DumpSiteBlob( BlobBuffer, BlobSize, FALSE);
  672. continue;
  673. }
  674. Status = PackGetNameInformation( &NameInfo,
  675. &pNestedBuffer,
  676. &Size );
  677. if (Status == ERROR_SUCCESS)
  678. {
  679. if (Show)
  680. {
  681. DumpNameInformation(&NameInfo);
  682. }
  683. Status = PackGetULong( &ReplicaBlobSize,
  684. &pNestedBuffer,
  685. &Size );
  686. if (Status == ERROR_SUCCESS)
  687. {
  688. Status = PackGetULong( &ReplicaListInfo.ReplicaCount,
  689. &pNestedBuffer,
  690. &ReplicaBlobSize );
  691. }
  692. if (Status == ERROR_SUCCESS)
  693. {
  694. ReplicaListInfo.pReplicas = new DFS_REPLICA_INFORMATION[ ReplicaListInfo.ReplicaCount ];
  695. if (ReplicaListInfo.pReplicas == NULL)
  696. {
  697. Status = ERROR_NOT_ENOUGH_MEMORY;
  698. }
  699. }
  700. if (Status == ERROR_SUCCESS)
  701. {
  702. DebugInformation((L"Reading replica information, size 0x%x\n",
  703. ReplicaBlobSize));
  704. Status = PackGetReplicaInformation( &ReplicaListInfo,
  705. &pNestedBuffer,
  706. &ReplicaBlobSize);
  707. DebugInformation((L"Read replica information 0x%x\n", Status));
  708. if (Status == ERROR_SUCCESS)
  709. {
  710. if (Show)
  711. {
  712. DumpReplicaInformation(&ReplicaListInfo);
  713. }
  714. }
  715. else
  716. {
  717. DebugInformation((L"Could not read replica information, Status 0x%x\n", Status));
  718. }
  719. delete [] ReplicaListInfo.pReplicas;
  720. }
  721. else
  722. {
  723. DebugInformation((L"Could not read replica size information, Status 0x%x\n", Status));
  724. }
  725. }
  726. else
  727. {
  728. DebugInformation((L"Could not read name information, Status 0x%x\n", Status));
  729. }
  730. }
  731. }
  732. done:
  733. return Status;
  734. }
  735. DFSSTATUS
  736. DfsGetPktBlob(
  737. LDAP *pLdap,
  738. LPWSTR ObjectDN,
  739. LPWSTR FileName )
  740. {
  741. DFSSTATUS Status = ERROR_SUCCESS;
  742. DFSSTATUS LdapStatus = ERROR_SUCCESS;
  743. PLDAPMessage pLdapSearchedObject = NULL;
  744. PLDAPMessage pLdapObject = NULL;
  745. PLDAP_BERVAL *pLdapPktAttr = NULL;
  746. LPWSTR Attributes[2];
  747. PBYTE pBlob;
  748. ULONG BlobSize;
  749. Status = ERROR_ACCESS_DENIED; // fix this after we understand
  750. // ldap error correctly. When
  751. // ldap_get_values_len returns NULL
  752. // the old code return no more mem.
  753. Attributes[0] = ADBlobAttribute;
  754. Attributes[1] = NULL;
  755. LdapStatus = ldap_search_ext_sW( pLdap,
  756. ObjectDN,
  757. LDAP_SCOPE_BASE,
  758. L"(objectClass=*)",
  759. Attributes,
  760. 0, // attributes only
  761. NULL, // server controls
  762. NULL, // client controls
  763. NULL,
  764. 0, // size limit
  765. &pLdapSearchedObject);
  766. if (LdapStatus == LDAP_SUCCESS)
  767. {
  768. pLdapObject = ldap_first_entry( pLdap,
  769. pLdapSearchedObject );
  770. if (pLdapObject != NULL)
  771. {
  772. pLdapPktAttr = ldap_get_values_len( pLdap,
  773. pLdapObject,
  774. Attributes[0] );
  775. if (pLdapPktAttr != NULL)
  776. {
  777. pBlob = (PBYTE)pLdapPktAttr[0]->bv_val;
  778. BlobSize = pLdapPktAttr[0]->bv_len;
  779. if (FileName != NULL)
  780. {
  781. Status = DfsWriteBlobToFile( pBlob, BlobSize, FileName);
  782. }
  783. else
  784. {
  785. Status = UnpackBlob( pBlob, &BlobSize, FALSE );
  786. if (Status == ERROR_SUCCESS)
  787. {
  788. ShowInformation((L"\nBlob Checked OK\n\n"));
  789. }
  790. else
  791. {
  792. ShowInformation((L"\nBlob check failed with %d\n\n", Status));
  793. }
  794. }
  795. ldap_value_free_len( pLdapPktAttr );
  796. }
  797. }
  798. }
  799. else
  800. {
  801. Status = LdapMapErrorToWin32(LdapStatus);
  802. }
  803. if (pLdapSearchedObject != NULL)
  804. {
  805. ldap_msgfree( pLdapSearchedObject );
  806. }
  807. return Status;
  808. }
  809. DFSSTATUS
  810. DfsWriteBlobToFile(
  811. PBYTE pBlob,
  812. ULONG BlobSize,
  813. LPWSTR FileName)
  814. {
  815. HANDLE FileHandle;
  816. DFSSTATUS Status = ERROR_SUCCESS;
  817. ULONG BytesWritten;
  818. FileHandle = CreateFile( FileName,
  819. GENERIC_ALL,
  820. FILE_SHARE_WRITE,
  821. NULL,
  822. CREATE_ALWAYS,
  823. FILE_ATTRIBUTE_NORMAL,
  824. 0);
  825. if (FileHandle == INVALID_HANDLE_VALUE)
  826. {
  827. Status = GetLastError();
  828. }
  829. if (Status == ERROR_SUCCESS)
  830. {
  831. if (WriteFile( FileHandle,
  832. pBlob,
  833. BlobSize,
  834. &BytesWritten,
  835. NULL) == TRUE)
  836. {
  837. if (BlobSize != BytesWritten)
  838. {
  839. DebugInformation((L"Blob Size %d, Written %d\n", BlobSize, BytesWritten));
  840. }
  841. }
  842. else
  843. {
  844. Status = GetLastError();
  845. }
  846. }
  847. return Status;
  848. }
  849. DFSSTATUS
  850. DfsReadFromFile(
  851. LPWSTR Name )
  852. {
  853. HANDLE FileHandle;
  854. ULONG Size, HighValue;
  855. BYTE *pBuffer;
  856. DFSSTATUS Status = ERROR_SUCCESS;
  857. ULONG BytesRead;
  858. FileHandle = CreateFile( Name,
  859. GENERIC_READ,
  860. FILE_SHARE_READ,
  861. NULL,
  862. OPEN_EXISTING,
  863. FILE_ATTRIBUTE_NORMAL,
  864. 0);
  865. if (FileHandle == INVALID_HANDLE_VALUE)
  866. {
  867. Status = GetLastError();
  868. }
  869. if (Status == ERROR_SUCCESS)
  870. {
  871. Size = GetFileSize( FileHandle,
  872. &HighValue );
  873. if (Size == INVALID_FILE_SIZE)
  874. {
  875. Status = GetLastError();
  876. }
  877. }
  878. if (Status == ERROR_SUCCESS)
  879. {
  880. pBuffer = new BYTE[Size];
  881. if (pBuffer == NULL)
  882. {
  883. Status = ERROR_NOT_ENOUGH_MEMORY;
  884. }
  885. }
  886. if (Status == ERROR_SUCCESS)
  887. {
  888. if (ReadFile( FileHandle,
  889. pBuffer,
  890. Size,
  891. &BytesRead,
  892. NULL ) == TRUE)
  893. {
  894. if (Size != BytesRead)
  895. {
  896. DebugInformation((L"File size %d, Read %d\n", Size, BytesRead));
  897. }
  898. Status = UnpackBlob( pBuffer,
  899. &BytesRead,
  900. TRUE );
  901. }
  902. else
  903. {
  904. Status = GetLastError();
  905. }
  906. }
  907. return Status;
  908. }
  909. DFSSTATUS
  910. DfsReadFromAD(
  911. LPWSTR DomainName,
  912. LPWSTR Name,
  913. LPWSTR FileName,
  914. LPWSTR UseDC )
  915. {
  916. PDOMAIN_CONTROLLER_INFO pDomainControllerInfo = NULL;
  917. DWORD dwErr = ERROR_SUCCESS;
  918. LDAP *pLdap;
  919. LPWSTR ObjectDN;
  920. HRESULT Hr;
  921. DFSSTATUS Status;
  922. LPWSTR ObjectName;
  923. //
  924. // We need to initialize the COM library for use by DfsUtil.exe
  925. //
  926. Hr = CoInitializeEx(NULL,COINIT_MULTITHREADED| COINIT_DISABLE_OLE1DDE);
  927. if (!SUCCEEDED(Hr))
  928. {
  929. return HRESULT_CODE(Hr);
  930. }
  931. if (UseDC == NULL)
  932. {
  933. dwErr = DsGetDcName ( NULL,
  934. DomainName,
  935. NULL,
  936. NULL,
  937. DS_DIRECTORY_SERVICE_REQUIRED |
  938. DS_PDC_REQUIRED |
  939. DS_FORCE_REDISCOVERY,
  940. &pDomainControllerInfo );
  941. if (dwErr == ERROR_SUCCESS)
  942. {
  943. UseDC = &pDomainControllerInfo->DomainControllerName[2];
  944. }
  945. else
  946. {
  947. return dwErr;
  948. }
  949. }
  950. Status = DfsLdapConnect( UseDC, &pLdap );
  951. DebugInformation((L"Ldap Connect Status %ws 0x%x\n", UseDC, Status));
  952. if (Status == ERROR_SUCCESS)
  953. {
  954. LPWSTR NameContext = NULL;
  955. extern LPWSTR DfsGetDfsAdNameContextStringForDomain(LPWSTR UseDC);
  956. NameContext = DfsGetDfsAdNameContextStringForDomain(UseDC);
  957. if (NameContext == NULL)
  958. {
  959. Status = ERROR_NOT_ENOUGH_MEMORY; // cookup an error.
  960. }
  961. if (Status == ERROR_SUCCESS)
  962. {
  963. Status = DfsGenerateRootCN( Name,
  964. &ObjectName );
  965. }
  966. if (Status == ERROR_SUCCESS) {
  967. Status = DfsGenerateADPathString( NULL,
  968. ObjectName,
  969. NULL,
  970. &ObjectDN);
  971. DebugInformation((L"Generate path Status 0x%x\n", Status));
  972. if (Status == ERROR_SUCCESS)
  973. {
  974. DebugInformation((L"Generated path %wS\n", ObjectDN));
  975. Status = DfsGetPktBlob(pLdap, ObjectDN, FileName );
  976. DebugInformation((L"Getblob Status 0x%x\n", Status));
  977. }
  978. }
  979. }
  980. CoUninitialize();
  981. return Status;
  982. }