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.

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