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.

667 lines
16 KiB

  1. //--------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1999, Microsoft Corporation
  4. //
  5. // File: misc.cxx
  6. //
  7. //--------------------------------------------------------------------------
  8. #define UNICODE 1
  9. extern "C" {
  10. #include <nt.h>
  11. #include <ntrtl.h>
  12. #include <nturtl.h>
  13. #include <windows.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <stddef.h>
  17. #include <shellapi.h>
  18. #include <dfsprefix.h>
  19. #include <winldap.h>
  20. #include <dsgetdc.h>
  21. #include <lm.h>
  22. #include <lmdfs.h>
  23. #include <dfsfsctl.h>
  24. }
  25. #include <DfsServerLibrary.hxx>
  26. #include "struct.hxx"
  27. #include "flush.hxx"
  28. #include "misc.hxx"
  29. #include "messages.h"
  30. #include <strsafe.h>
  31. #include <dfsutil.hxx>
  32. #include "dfspathname.hxx"
  33. #include "resapi.h"
  34. #define MAX_BUF_SIZE 10000
  35. WCHAR MsgBuf[MAX_BUF_SIZE];
  36. CHAR AnsiBuf[MAX_BUF_SIZE*3];
  37. WCHAR wszRootShare[MAX_PATH+1] = { 0 };
  38. #define WINLOGON_FOLDER L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"
  39. #define SFCVALUE L"SFCDisable"
  40. #define ARRAYLEN(x) (sizeof(x) / sizeof((x)[0]))
  41. DWORD
  42. DfspGetLinkName(
  43. LPWSTR pwszDfsRoot,
  44. LPWSTR *ppwszLinkName);
  45. DWORD
  46. AtoHex(
  47. LPWSTR pwszHexValue,
  48. PDWORD pdwErr)
  49. {
  50. DWORD dwHexValue = 0;
  51. DWORD DiscardResult;
  52. // if (fSwDebug == TRUE)
  53. // MyPrintf(L"AtoHex(%ws)\r\n", pwszHexValue);
  54. if (pwszHexValue == NULL) {
  55. *pdwErr = ERROR_INVALID_PARAMETER;
  56. goto AllDone;
  57. }
  58. if (pwszHexValue[0] == L'0' && (pwszHexValue[1] == L'x' || pwszHexValue[1] == L'X'))
  59. pwszHexValue = &pwszHexValue[2];
  60. DiscardResult = swscanf(pwszHexValue, L"%x", &dwHexValue);
  61. AllDone:
  62. // if (fSwDebug == TRUE)
  63. // MyPrintf(L"AtoHex returning 0x%x (dwErr=0x%x)\r\n", dwHexValue, *pdwErr);
  64. return dwHexValue;
  65. }
  66. DWORD
  67. AtoDec(
  68. LPWSTR pwszDecValue,
  69. PDWORD pdwErr)
  70. {
  71. DWORD dwDecValue = 0;
  72. DWORD DiscardResult;
  73. // if (fSwDebug == TRUE)
  74. // MyPrintf(L"AtoDec(%ws)\r\n", pwszDecValue);
  75. if (pwszDecValue == NULL) {
  76. *pdwErr = ERROR_INVALID_PARAMETER;
  77. goto AllDone;
  78. }
  79. DiscardResult = swscanf(pwszDecValue, L"%d", &dwDecValue);
  80. AllDone:
  81. // if (fSwDebug == TRUE)
  82. // MyPrintf(L"AtoDec returning 0x%x (dwErr=0x%x)\r\n", dwDecValue, *pdwErr);
  83. return dwDecValue;
  84. }
  85. DFSSTATUS
  86. IsClusterNode(
  87. LPWSTR pNodeName,
  88. PBOOLEAN pIsCluster )
  89. {
  90. DFSSTATUS Status = ERROR_SUCCESS;
  91. DWORD ClusterState;
  92. *pIsCluster = FALSE;
  93. Status = GetNodeClusterState( pNodeName,
  94. &ClusterState );
  95. if (Status == ERROR_SUCCESS)
  96. {
  97. if ( (ClusterStateRunning == ClusterState) ||
  98. (ClusterStateNotRunning == ClusterState) )
  99. {
  100. *pIsCluster = TRUE;
  101. }
  102. }
  103. return Status;
  104. }
  105. #if 0
  106. // We might enable this code in a more cluster friendly
  107. // dfsutil version.
  108. //
  109. typedef struct _DFSUTIL_CLUSTER_CONTEXT {
  110. PUNICODE_STRING pShareName;
  111. BOOLEAN bIsClustered;
  112. } DFSUTIL_CLUSTER_CONTEXT;
  113. DWORD
  114. DfsUtilClusterCallBackFunction(
  115. HRESOURCE hSelf,
  116. HRESOURCE hResource,
  117. PVOID Context)
  118. {
  119. UNREFERENCED_PARAMETER( hSelf );
  120. HKEY HKey = NULL;
  121. HKEY HParamKey = NULL;
  122. DFSUTIL_CLUSTER_CONTEXT *pContext = (DFSUTIL_CLUSTER_CONTEXT *)Context;
  123. DWORD Status = ERROR_SUCCESS;
  124. DWORD Value = 0;
  125. pContext->bIsClustered = FALSE;
  126. HKey = GetClusterResourceKey(hResource, KEY_READ);
  127. if (HKey != NULL) {
  128. Status = ClusterRegOpenKey( HKey,
  129. L"Parameters",
  130. KEY_READ,
  131. &HParamKey );
  132. ClusterRegCloseKey( HKey );
  133. if (ERROR_SUCCESS == Status)
  134. {
  135. LPWSTR ResShareName = NULL;
  136. UNICODE_STRING VsName;
  137. ResShareName = ResUtilGetSzValue( HParamKey,
  138. L"ShareName" );
  139. Status = DfsRtlInitUnicodeStringEx(&VsName, ResShareName);
  140. if(Status == ERROR_SUCCESS)
  141. {
  142. if (pContext->pShareName->Length == VsName.Length)
  143. {
  144. Status = ResUtilGetDwordValue(HParamKey, L"IsDfsRoot", &Value, 0);
  145. if ((ERROR_SUCCESS == Status) &&
  146. (Value == 1))
  147. {
  148. if (_wcsnicmp(pContext->pShareName->Buffer,
  149. VsName.Buffer,
  150. VsName.Length) == 0)
  151. {
  152. pContext->bIsClustered = TRUE;
  153. }
  154. }
  155. }
  156. }
  157. ClusterRegCloseKey( HParamKey );
  158. }
  159. }
  160. return Status;
  161. }
  162. DWORD
  163. IsClusterRoot(
  164. LPWSTR pNodeName,
  165. PUNICODE_STRING pShareName,
  166. PBOOLEAN pIsClustered )
  167. {
  168. DWORD Status;
  169. DFSUTIL_CLUSTER_CONTEXT Context;
  170. UNREFERENCED_PARAMETER(pNodeName);
  171. Context.pShareName = pShareName;
  172. Context.bIsClustered = FALSE;
  173. Status = ResUtilEnumResources(NULL,
  174. L"File Share",
  175. DfsUtilClusterCallBackFunction,
  176. (PVOID)&Context );
  177. if (Status == ERROR_SUCCESS)
  178. {
  179. *pIsClustered = Context.bIsClustered;
  180. }
  181. return Status;
  182. }
  183. #endif
  184. DWORD
  185. CmdAddRoot(
  186. BOOLEAN DomainDfs,
  187. LPWSTR pwszServerName,
  188. LPWSTR pwszShareName,
  189. LPWSTR pwszRootName,
  190. LPWSTR pwszComment)
  191. {
  192. DWORD dwErr = ERROR_SUCCESS;
  193. BOOLEAN bIsClustered = FALSE;
  194. DebugInformation((L"CmdAddRoot (%ws,%ws)\r\n", pwszServerName, pwszShareName));
  195. if (DomainDfs == FALSE)
  196. {
  197. // see if the server is a clustered node.
  198. dwErr = IsClusterNode( pwszServerName, &bIsClustered );
  199. if (dwErr == ERROR_SUCCESS && bIsClustered)
  200. {
  201. DebugInformation((L"Node %ws is in a cluster\r\n", pwszServerName));
  202. }
  203. if (!bIsClustered)
  204. {
  205. DebugInformation((L"<%ws, %ws> is not clustered. Calling NetDfsAddStdRoot\r\n",
  206. pwszServerName, pwszShareName));
  207. dwErr = NetDfsAddStdRoot(
  208. pwszServerName,
  209. pwszShareName,
  210. pwszComment,
  211. 0);;
  212. }
  213. else
  214. {
  215. MyPrintf(L"Node %ws belongs to a cluster environment. This command is not supported.\r\n", pwszServerName);
  216. dwErr = ERROR_NOT_SUPPORTED;
  217. }
  218. } else {
  219. dwErr = NetDfsAddFtRoot(
  220. pwszServerName,
  221. pwszShareName,
  222. pwszRootName,
  223. pwszComment,
  224. 0);
  225. }
  226. DebugInformation((L"CmdAddRoot returning %d\r\n", dwErr));
  227. if (dwErr == ERROR_SUCCESS)
  228. CommandSucceeded = TRUE;
  229. return dwErr;
  230. }
  231. DWORD
  232. CmdRemRoot(
  233. BOOLEAN DomDfs,
  234. LPWSTR pwszServerName,
  235. LPWSTR pwszShareName,
  236. LPWSTR pwszRootName)
  237. {
  238. DWORD dwErr = ERROR_SUCCESS;
  239. BOOLEAN bIsClustered = FALSE;
  240. DebugInformation((L"CmdRemRoot: Server %ws, Physical Share %ws, Logical Share %ws)\r\n",
  241. pwszServerName, pwszShareName, pwszRootName));
  242. if (DomDfs == FALSE)
  243. {
  244. // see if the server is a clustered node.
  245. dwErr = IsClusterNode( pwszServerName, &bIsClustered );
  246. if (dwErr == ERROR_SUCCESS && bIsClustered)
  247. {
  248. DebugInformation((L"Node %ws is in a cluster.\r\n", pwszServerName));
  249. }
  250. if (!bIsClustered)
  251. {
  252. DebugInformation((L"<%ws, %ws> is not clustered. Calling NetDfsRemoveStdRoot\r\n",
  253. pwszServerName, pwszShareName));
  254. dwErr = NetDfsRemoveStdRoot(
  255. pwszServerName,
  256. pwszShareName,
  257. 0);
  258. }
  259. else
  260. {
  261. MyPrintf(L"Node %ws belongs to a cluster environment. This command is not supported.\r\n",pwszServerName);
  262. dwErr = ERROR_NOT_SUPPORTED;
  263. }
  264. }
  265. else {
  266. dwErr = NetDfsRemoveFtRoot(
  267. pwszServerName,
  268. pwszShareName,
  269. pwszRootName,
  270. 0);
  271. }
  272. DebugInformation((L"CmdRemRoot returning %d\r\n", dwErr));
  273. if (dwErr == ERROR_SUCCESS)
  274. CommandSucceeded = TRUE;
  275. return dwErr;
  276. }
  277. VOID
  278. MyFormatMessageText(
  279. HRESULT dwMsgId,
  280. PWSTR pszBuffer,
  281. DWORD dwBufferSize,
  282. va_list *parglist)
  283. {
  284. DWORD dwReturn = FormatMessage(
  285. (dwMsgId >= MSG_FIRST_MESSAGE)
  286. ? FORMAT_MESSAGE_FROM_HMODULE
  287. : FORMAT_MESSAGE_FROM_SYSTEM,
  288. NULL,
  289. dwMsgId,
  290. LANG_USER_DEFAULT,
  291. pszBuffer,
  292. dwBufferSize,
  293. parglist);
  294. if (dwReturn == 0 && fSwDebug)
  295. MyPrintf(L"Formatmessage failed 0x%x\r\n", GetLastError());
  296. }
  297. VOID
  298. ErrorMessage(
  299. IN HRESULT hr,
  300. ...)
  301. {
  302. ULONG cch;
  303. va_list arglist;
  304. HRESULT HResult;
  305. size_t CharacterCount;
  306. va_start(arglist, hr);
  307. MyFormatMessageText(hr, MsgBuf, ARRAYLEN(MsgBuf), &arglist);
  308. HResult = StringCchLength( MsgBuf,
  309. MAX_BUF_SIZE,
  310. &CharacterCount );
  311. if (SUCCEEDED(HResult))
  312. {
  313. cch = WideCharToMultiByte(CP_OEMCP, 0,
  314. MsgBuf, CharacterCount,
  315. AnsiBuf, MAX_BUF_SIZE*3,
  316. NULL, NULL);
  317. WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), AnsiBuf, cch, &cch, NULL);
  318. }
  319. va_end(arglist);
  320. }
  321. VOID
  322. DfsVPrintToFile(
  323. HANDLE FileHandle,
  324. PWCHAR format,
  325. va_list va)
  326. {
  327. ULONG cch;
  328. HRESULT HResult;
  329. size_t CharacterCount;
  330. HResult = StringCchVPrintf( MsgBuf,
  331. MAX_BUF_SIZE,
  332. format,
  333. va );
  334. if (SUCCEEDED(HResult))
  335. {
  336. HResult = StringCchLength( MsgBuf,
  337. MAX_BUF_SIZE,
  338. &CharacterCount );
  339. }
  340. if (SUCCEEDED(HResult))
  341. {
  342. cch = WideCharToMultiByte(CP_OEMCP, 0,
  343. MsgBuf, CharacterCount,
  344. AnsiBuf, MAX_BUF_SIZE*3,
  345. NULL, NULL);
  346. WriteFile(FileHandle, AnsiBuf, cch, &cch, NULL);
  347. }
  348. return;
  349. }
  350. VOID
  351. DfsVPrintWideToFile(
  352. HANDLE FileHandle,
  353. PWCHAR format,
  354. va_list va)
  355. {
  356. ULONG cch;
  357. HRESULT HResult;
  358. size_t CharacterCount;
  359. HResult = StringCchVPrintf( MsgBuf,
  360. MAX_BUF_SIZE,
  361. format,
  362. va );
  363. if (SUCCEEDED(HResult))
  364. {
  365. HResult = StringCchLength( MsgBuf,
  366. MAX_BUF_SIZE,
  367. &CharacterCount );
  368. }
  369. if (SUCCEEDED(HResult))
  370. {
  371. //cch = WideCharToMultiByte(CP_OEMCP, 0,
  372. // MsgBuf, CharacterCount,
  373. // AnsiBuf, MAX_BUF_SIZE*3,
  374. // NULL, NULL);
  375. // WriteFile(FileHandle, AnsiBuf, cch, &cch, NULL);
  376. WriteFile(FileHandle, MsgBuf, CharacterCount*sizeof(WCHAR), &cch, NULL);
  377. }
  378. return;
  379. }
  380. VOID
  381. DfsPrintToFile(
  382. HANDLE FileHandle,
  383. BOOLEAN ScriptOut,
  384. PWCHAR format,
  385. ...)
  386. {
  387. va_list va;
  388. va_start(va, format);
  389. if (ScriptOut)
  390. {
  391. DfsVPrintWideToFile( FileHandle, format, va);
  392. }
  393. else
  394. {
  395. DfsVPrintToFile( FileHandle, format, va);
  396. }
  397. va_end(va);
  398. return;
  399. }
  400. VOID
  401. MyPrintf(
  402. PWCHAR format,
  403. ...)
  404. {
  405. va_list va;
  406. va_start(va, format);
  407. DfsVPrintToFile( GetStdHandle(STD_OUTPUT_HANDLE), format, va);
  408. va_end(va);
  409. return;
  410. }
  411. VOID
  412. ShowVerboseInformation(
  413. PWCHAR format,
  414. ...)
  415. {
  416. va_list va;
  417. extern HANDLE ShowHandle;
  418. va_start(va, format);
  419. DfsVPrintToFile( ShowHandle, format, va);
  420. va_end(va);
  421. return;
  422. }
  423. VOID
  424. ShowDebugInformation(
  425. PWCHAR format,
  426. ...)
  427. {
  428. va_list va;
  429. extern HANDLE DebugHandle;
  430. va_start(va, format);
  431. DfsVPrintToFile( DebugHandle, format, va);
  432. va_end(va);
  433. return;
  434. }
  435. DFSSTATUS
  436. SetInfoReSynchronize(
  437. LPWSTR ServerName,
  438. LPWSTR ShareName)
  439. {
  440. DfsPathName RootTarget;
  441. DFS_INFO_101 Info101;
  442. DFSSTATUS Status;
  443. //
  444. // First create a UNC path name to the root target.
  445. //
  446. Status = RootTarget.SetPathName( ServerName, ShareName );
  447. if (Status != ERROR_SUCCESS)
  448. {
  449. DebugInformation((L"DfsUtil: Error 0x%x in creating RootTarget<%wS, %wS>\n",
  450. Status, ServerName, ShareName));
  451. ErrorMessage(Status);
  452. return Status;
  453. }
  454. DebugInformation((L"DfsUtil: ReSynchronize notification to root target %wS\n", RootTarget.GetPathString()));
  455. //
  456. // Ask the dfs service to synchronize. It is important that we don't
  457. // use direct mode operations (ie. DFS_SET_INFO macro) here. These are the root targets.
  458. //
  459. Info101.State = DFS_VOLUME_STATE_RESYNCHRONIZE;
  460. Status = NetDfsSetInfo( RootTarget.GetPathString(), NULL, NULL, 101, (LPBYTE)&Info101 );
  461. //
  462. // It is entirely fine to get an error from W2K servers. Still, we'll defer that decision to the
  463. // to the caller and return the real error.
  464. //
  465. if (Status != ERROR_SUCCESS)
  466. {
  467. DebugInformation((L"DfsUtil: Error 0x%x hit in attempting to contact root target %wS\n",
  468. Status, RootTarget.GetPathString()));
  469. }
  470. return Status;
  471. }
  472. //
  473. // Just take out the <target,share> tuple from the replicalist
  474. // in the AD directly. This doesn't involve any attempts to
  475. // contact that replica server other than a feeble attempt to
  476. // send a RESYNCHRONIZE message to it. We fully expect that
  477. // the typically scenario will be one of a dead replica server.
  478. //
  479. DWORD
  480. CmdUnmapRootReplica(
  481. LPWSTR DomainDfsPath,
  482. LPWSTR ReplicaServerName,
  483. LPWSTR ReplicaShareName )
  484. {
  485. DfsPathName DfsPathName;
  486. DFSSTATUS Status;
  487. Status = DfsPathName.CreatePathName( DomainDfsPath );
  488. if (Status == ERROR_SUCCESS)
  489. {
  490. PUNICODE_STRING pRemaining = DfsPathName.GetRemainingCountedString();
  491. if (pRemaining->Length != 0)
  492. {
  493. Status = ERROR_INVALID_PARAMETER;
  494. }
  495. if (Status == ERROR_SUCCESS)
  496. {
  497. Status = NetDfsRemoveFtRootForced( DfsPathName.GetServerString(),
  498. ReplicaServerName,
  499. ReplicaShareName,
  500. DfsPathName.GetShareString(),
  501. 0 );
  502. }
  503. }
  504. return Status;
  505. }
  506. DWORD
  507. CmdClean(
  508. LPWSTR HostServerName,
  509. LPWSTR RootShareName )
  510. {
  511. DWORD Status;
  512. DebugInformation((L"DfsUtil: Contacting registry of %wS to remove %wS\n",
  513. HostServerName, RootShareName));
  514. Status = DfsClean( HostServerName, RootShareName );
  515. if (Status != ERROR_SUCCESS) {
  516. DebugInformation((L"DfsUtil: Specified registry entry was not found.\n"));
  517. }
  518. return Status;
  519. }
  520. DWORD
  521. CreateDfsFile( LPWSTR pFileString,
  522. PHANDLE pFileHandle )
  523. {
  524. HANDLE FileHandle;
  525. DWORD Status = ERROR_SUCCESS;
  526. FileHandle = CreateFile( pFileString,
  527. GENERIC_ALL,
  528. FILE_SHARE_READ|FILE_SHARE_DELETE,
  529. NULL,
  530. CREATE_ALWAYS,
  531. FILE_ATTRIBUTE_NORMAL,
  532. NULL );
  533. if (FileHandle == INVALID_HANDLE_VALUE)
  534. {
  535. Status = GetLastError();
  536. }
  537. else
  538. {
  539. *pFileHandle = FileHandle;
  540. }
  541. return Status;
  542. }