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.

546 lines
13 KiB

  1. //--------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1999, Microsoft Corporation
  4. //
  5. // File: dfslink.hxx
  6. //
  7. //--------------------------------------------------------------------------
  8. #ifndef __DFS_UTIL_LINK__
  9. #define __DFS_UTIL_LINK__
  10. #include "DfsTarget.hxx"
  11. #include "Dfsheader.h"
  12. #include "dfsStrings.hxx"
  13. #include "dfsutil.hxx"
  14. #define LINK_NAME_ADDED 1
  15. #define STATE_INITIALIZED 0x10
  16. #define COMMENT_INITIALIZED 0x20
  17. #define TIMEOUT_INITIALIZED 0x40
  18. #define MARK_LINK_DELETE 0x0010
  19. #define MARK_LINK_ADD 0x0020
  20. #define UPDATE_LINK_STATE 0x0040
  21. #define UPDATE_LINK_TIMEOUT 0x0080
  22. #define UPDATE_LINK_COMMENT 0x0100
  23. class DfsLink
  24. {
  25. protected:
  26. ULONG _Flags;
  27. ULONG _ChangeStatus;
  28. DfsString _Name;
  29. DfsString _Comment;
  30. ULONG _Timeout;
  31. ULONG _State;
  32. ULONG _TargetCount;
  33. DfsLink *_pNextLink;
  34. DfsTarget *_pTargets;
  35. DfsTarget *_pLastTarget;
  36. public:
  37. DfsLink( )
  38. {
  39. _Flags = 0;
  40. _Timeout = 300;
  41. _State = DFS_VOLUME_STATE_OK;
  42. _pNextLink = NULL;
  43. _pTargets = NULL;
  44. _pLastTarget = NULL;
  45. _ChangeStatus = 0;
  46. _TargetCount = 0;
  47. }
  48. ~DfsLink( )
  49. {
  50. //
  51. // take care to free up all
  52. // resources here.
  53. //
  54. }
  55. VOID
  56. ResetChangeStatus()
  57. {
  58. _ChangeStatus = 0;
  59. }
  60. VOID
  61. SetChangeStatus( ULONG State)
  62. {
  63. _ChangeStatus |= State;
  64. }
  65. DFSSTATUS
  66. ValidateLinkName( PUNICODE_STRING pLinkName)
  67. {
  68. pLinkName;
  69. return ERROR_SUCCESS;
  70. }
  71. DFSSTATUS
  72. SetLinkName (PUNICODE_STRING pLinkName )
  73. {
  74. DFSSTATUS Status = ERROR_SUCCESS;
  75. if (_Flags & LINK_NAME_ADDED)
  76. {
  77. Status = ERROR_INVALID_PARAMETER;
  78. }
  79. if (Status == ERROR_SUCCESS)
  80. {
  81. Status = ValidateLinkName( pLinkName);
  82. if (Status == ERROR_SUCCESS)
  83. {
  84. Status = _Name.CreateString(pLinkName);
  85. if (Status == ERROR_SUCCESS)
  86. {
  87. _Flags |= LINK_NAME_ADDED;
  88. }
  89. }
  90. }
  91. return Status;
  92. }
  93. DFSSTATUS
  94. SetLinkName (LPWSTR LinkNameString )
  95. {
  96. UNICODE_STRING LinkName;
  97. RtlInitUnicodeString(&LinkName, LinkNameString);
  98. return SetLinkName(&LinkName);
  99. }
  100. BOOLEAN
  101. IsValidLink()
  102. {
  103. return ((_Flags & LINK_NAME_ADDED) == LINK_NAME_ADDED);
  104. }
  105. BOOLEAN
  106. IsMatchingState( ULONG State)
  107. {
  108. return (_State == State);
  109. }
  110. BOOLEAN
  111. IsMatchingTimeout( ULONG Timeout)
  112. {
  113. return (_Timeout == Timeout);
  114. }
  115. BOOLEAN
  116. IsMatchingComment(PUNICODE_STRING pComment)
  117. {
  118. return (_Comment == pComment);
  119. }
  120. VOID
  121. SetLinkState( ULONG State)
  122. {
  123. _Flags |= STATE_INITIALIZED;
  124. _State = State;
  125. }
  126. DFSSTATUS
  127. SetLinkComment( PUNICODE_STRING pComment )
  128. {
  129. _Flags |= COMMENT_INITIALIZED;
  130. return _Comment.CreateString(pComment);
  131. }
  132. DFSSTATUS
  133. SetLinkComment( LPWSTR Comment )
  134. {
  135. UNICODE_STRING CommentString;
  136. RtlInitUnicodeString(&CommentString, Comment);
  137. return SetLinkComment(&CommentString);
  138. }
  139. VOID
  140. SetLinkTimeout( ULONG Timeout)
  141. {
  142. _Flags |= TIMEOUT_INITIALIZED;
  143. _Timeout = Timeout;
  144. }
  145. DFSSTATUS
  146. AddTargets(DfsTarget *pTarget,
  147. ULONG Count)
  148. {
  149. DfsTarget *pLastTarget;
  150. ULONG Target;
  151. if (_pLastTarget != NULL)
  152. {
  153. _pLastTarget->AddNextTarget(pTarget);
  154. }
  155. else
  156. {
  157. _pTargets = pTarget;
  158. }
  159. _TargetCount += Count;
  160. for (Target = 0, pLastTarget = pTarget;
  161. Target < Count;
  162. Target++, pLastTarget = pLastTarget->GetNextTarget())
  163. {
  164. _pLastTarget = pLastTarget;
  165. }
  166. return ERROR_SUCCESS;
  167. }
  168. DFSSTATUS
  169. AddTarget( DfsTarget *pTarget )
  170. {
  171. if (_pLastTarget != NULL)
  172. {
  173. _pLastTarget->AddNextTarget(pTarget);
  174. }
  175. else
  176. {
  177. _pTargets = pTarget;
  178. }
  179. _TargetCount++;
  180. _pLastTarget = pTarget;
  181. return ERROR_SUCCESS;
  182. }
  183. VOID
  184. AddNextLink( DfsLink *pLink )
  185. {
  186. _pNextLink = pLink;
  187. }
  188. PUNICODE_STRING
  189. GetLinkNameCountedString()
  190. {
  191. return _Name.GetCountedString();
  192. }
  193. PUNICODE_STRING
  194. GetLinkCommentCountedString()
  195. {
  196. return _Comment.GetCountedString();
  197. }
  198. LPWSTR
  199. GetLinkNameString()
  200. {
  201. return _Name.GetString();
  202. }
  203. LPWSTR
  204. GetLinkCommentString()
  205. {
  206. return _Comment.GetString();
  207. }
  208. DfsString *
  209. GetLinkName()
  210. {
  211. return &_Name;
  212. }
  213. DfsString *
  214. GetLinkComment()
  215. {
  216. return &_Comment;
  217. }
  218. DWORD
  219. GetLinkState()
  220. {
  221. return _State;
  222. }
  223. DWORD
  224. GetLinkTimeout()
  225. {
  226. return _Timeout;
  227. }
  228. DfsTarget *
  229. GetFirstTarget()
  230. {
  231. return _pTargets;
  232. }
  233. DfsLink *
  234. GetNextLink()
  235. {
  236. return _pNextLink;
  237. }
  238. BOOLEAN
  239. MarkedForDelete()
  240. {
  241. return ((_ChangeStatus & MARK_LINK_DELETE) == MARK_LINK_DELETE);
  242. }
  243. BOOLEAN
  244. MarkedForAddition()
  245. {
  246. return ((_ChangeStatus & MARK_LINK_ADD) == MARK_LINK_ADD);
  247. }
  248. BOOLEAN
  249. MarkedForStateUpdate()
  250. {
  251. return ((_ChangeStatus & UPDATE_LINK_STATE) == UPDATE_LINK_STATE);
  252. }
  253. BOOLEAN
  254. MarkedForTimeoutUpdate()
  255. {
  256. return ((_ChangeStatus & UPDATE_LINK_TIMEOUT) == UPDATE_LINK_TIMEOUT);
  257. }
  258. BOOLEAN
  259. MarkedForCommentUpdate()
  260. {
  261. return ((_ChangeStatus & UPDATE_LINK_COMMENT) == UPDATE_LINK_COMMENT);
  262. }
  263. DFSSTATUS
  264. ApplyApiChanges( LPWSTR RootName,
  265. DFS_API_MODE Mode,
  266. ULONG Version,
  267. PDFS_UPDATE_STATISTICS pStatistics )
  268. {
  269. DFS_API_INFO ApiInfo, *pApiInfo;
  270. DFSSTATUS Status = ERROR_SUCCESS;
  271. UNICODE_STRING LinkName;
  272. DfsString *pUseComment = NULL;
  273. ULONG Flags = 0;
  274. BOOLEAN TargetAdded = FALSE;
  275. RtlInitUnicodeString(&LinkName, NULL);
  276. Status = DfsCreateUnicodePathString (&LinkName,
  277. 0,
  278. RootName,
  279. _Name.GetString());
  280. if (Status != ERROR_SUCCESS)
  281. {
  282. return Status;
  283. }
  284. if (MarkedForDelete())
  285. {
  286. if (Version >= 4)
  287. {
  288. Status = DfsApiRemove(Mode, LinkName.Buffer, NULL, NULL);
  289. if (Status != ERROR_SUCCESS)
  290. {
  291. ShowInformation((L"DfsRemove failed for %wS, Status %x\n",
  292. LinkName.Buffer, Status));
  293. }
  294. pStatistics->LinkDeleted++;
  295. pStatistics->TargetDeleted += _TargetCount;
  296. pStatistics->ApiCount++;
  297. return Status;
  298. }
  299. }
  300. if (MarkedForAddition())
  301. {
  302. pUseComment = &_Comment;
  303. Flags = DFS_ADD_VOLUME | DFS_RESTORE_VOLUME;
  304. _ChangeStatus &= ~UPDATE_LINK_COMMENT;
  305. pStatistics->LinkAdded++;
  306. }
  307. if (Status == ERROR_SUCCESS)
  308. {
  309. DfsTarget *pTarget;
  310. for (pTarget = _pTargets;
  311. ((pTarget != NULL) && (Status == ERROR_SUCCESS));
  312. pTarget = pTarget->GetNextTarget())
  313. {
  314. Status = pTarget->ApplyApiChanges(Mode,
  315. &LinkName,
  316. pUseComment,
  317. Flags,
  318. pStatistics);
  319. if (Status != ERROR_SUCCESS) {
  320. break;
  321. }
  322. TargetAdded = TRUE;
  323. pUseComment = NULL;
  324. Flags &= ~DFS_ADD_VOLUME;
  325. }
  326. }
  327. if (Status == ERROR_SUCCESS)
  328. {
  329. if (MarkedForStateUpdate())
  330. {
  331. ApiInfo.Info101.State = GetLinkState();
  332. pApiInfo = &ApiInfo;
  333. Status = DfsApiSetInfo( Mode, LinkName.Buffer, NULL, NULL, 101, &pApiInfo);
  334. if (Status != ERROR_SUCCESS)
  335. {
  336. ShowInformation((L"DfsSetInfo State %d failed for %wS, Status %x\n",
  337. ApiInfo.Info101.State,
  338. LinkName.Buffer,
  339. Status));
  340. }
  341. pStatistics->LinkModified++;
  342. pStatistics->ApiCount++;
  343. }
  344. else
  345. {
  346. //
  347. // if this is not a new link, update timestamp
  348. // on link so target changes are picked up.
  349. // this is a workaround so that we dont need to make
  350. // these changes in dfssvc itself.
  351. //
  352. if (!MarkedForAddition() && TargetAdded && (Mode == MODE_DIRECT))
  353. {
  354. ApiInfo.Info101.State = GetLinkState();
  355. pApiInfo = &ApiInfo;
  356. Status = DfsApiSetInfo( Mode, LinkName.Buffer, NULL, NULL, 101, &pApiInfo);
  357. }
  358. }
  359. }
  360. if (Status == ERROR_SUCCESS)
  361. {
  362. if (MarkedForCommentUpdate())
  363. {
  364. ApiInfo.Info100.Comment = GetLinkCommentString();
  365. pApiInfo = &ApiInfo;
  366. Status = DfsApiSetInfo( Mode, LinkName.Buffer, NULL, NULL, 100, &pApiInfo);
  367. if (Status != ERROR_SUCCESS)
  368. {
  369. ShowInformation((L"DfsSetInfo Comment %wS failed for %wS, Status %x\n",
  370. ApiInfo.Info100.Comment,
  371. LinkName.Buffer,
  372. Status));
  373. }
  374. pStatistics->LinkModified++;
  375. pStatistics->ApiCount++;
  376. }
  377. }
  378. if (Status == ERROR_SUCCESS)
  379. {
  380. if (MarkedForTimeoutUpdate())
  381. {
  382. ApiInfo.Info102.Timeout = GetLinkTimeout();
  383. pApiInfo = &ApiInfo;
  384. Status = DfsApiSetInfo( Mode, LinkName.Buffer, NULL, NULL, 102, &pApiInfo);
  385. if (Status != ERROR_SUCCESS)
  386. {
  387. ShowInformation((L"DfsSetInfo Timeout %d failed for %wS, Status %x\n",
  388. ApiInfo.Info102.Timeout,
  389. LinkName.Buffer,
  390. Status));
  391. }
  392. pStatistics->LinkModified++;
  393. pStatistics->ApiCount++;
  394. }
  395. }
  396. DfsFreeUnicodeString(&LinkName);
  397. return Status;
  398. }
  399. VOID
  400. MarkForDelete()
  401. {
  402. DfsTarget *pTarget;
  403. _ChangeStatus = MARK_LINK_DELETE;
  404. for (pTarget = _pTargets;
  405. (pTarget != NULL);
  406. pTarget = pTarget->GetNextTarget())
  407. {
  408. pTarget->MarkForDelete();
  409. }
  410. }
  411. VOID
  412. MarkForAddition()
  413. {
  414. DfsTarget *pTarget;
  415. _ChangeStatus = MARK_LINK_ADD;
  416. for (pTarget = _pTargets;
  417. (pTarget != NULL);
  418. pTarget = pTarget->GetNextTarget())
  419. {
  420. pTarget->MarkForAddition();
  421. }
  422. }
  423. DFSSTATUS
  424. FindMatchingTarget( DfsString *pServer,
  425. DfsString *pFolder,
  426. DfsTarget **ppTarget )
  427. {
  428. DfsTarget *pTarget;
  429. DFSSTATUS Status = ERROR_NOT_FOUND;
  430. for (pTarget = _pTargets;
  431. (pTarget != NULL);
  432. pTarget = pTarget->GetNextTarget())
  433. {
  434. if (pTarget->IsMatchingName(pServer, pFolder))
  435. {
  436. *ppTarget = pTarget;
  437. Status = ERROR_SUCCESS;
  438. }
  439. }
  440. return Status;
  441. }
  442. };
  443. #endif // __DFS_UTIL_LINK__