Source code of Windows XP (NT5)
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.

508 lines
12 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1996.
  5. //
  6. // File: cmd.cxx
  7. //
  8. // Contents: Command-line operations
  9. //
  10. // History: 7-May-96 BruceFo Created
  11. //
  12. //--------------------------------------------------------------------------
  13. #include "headers.hxx"
  14. #pragma hdrstop
  15. #include <shlobj.h>
  16. #include "cmd.hxx"
  17. #include "myutil.hxx"
  18. ULONG
  19. DfscmdPrintf(
  20. PWCHAR format,
  21. ...);
  22. //
  23. // -- create intermediate directories
  24. // -- don't remove if it's the last one
  25. // --
  26. // This function determines where the server and share name are in a UNC path,
  27. // and sets them to the output parameters. Note that the input parameter is
  28. // munged in the process. E.g.:
  29. // input: \\brucefo4\root\hello
  30. // output: \\brucefo4\0root\hello
  31. // ^server ^share
  32. //
  33. // FALSE is returned if it doesn't appear to be a UNC path. TRUE is returned
  34. // if everything seems ok.
  35. BOOL
  36. GetServerShare(
  37. IN OUT PWSTR pszUncPath,
  38. OUT PWSTR* ppszServer,
  39. OUT PWSTR* ppszShare
  40. )
  41. {
  42. appAssert(NULL != pszUncPath);
  43. //
  44. // Do a quick check that this is a UNC path
  45. //
  46. PWSTR pT;
  47. if ( L'\\' != pszUncPath[0]
  48. || L'\\' != pszUncPath[1]
  49. || L'\\' == pszUncPath[2] || L'\0' == pszUncPath[2]
  50. || (NULL == (pT = wcschr(&pszUncPath[3], L'\\')))
  51. )
  52. {
  53. return FALSE;
  54. }
  55. *ppszServer = &pszUncPath[2];
  56. *pT++ = L'\0';
  57. *ppszShare = pT;
  58. appDebugOut((DEB_TRACE,
  59. "GetServerShare: Server: %ws, share: %ws\n",
  60. *ppszServer, *ppszShare));
  61. return TRUE;
  62. }
  63. // This function determines the appropriate Dfs name to pass to the NetDfs
  64. // APIs. The input buffer is modified. E.g.:
  65. // input: \\dfsname\dfsshare
  66. // output: \\dfsname\0dfsshare
  67. // ^dfs
  68. //
  69. // FALSE is returned if it doesn't appear to be a dfs name. TRUE is returned
  70. // if everything seems ok.
  71. BOOL
  72. GetDfs(
  73. IN OUT PWSTR pszDfsName,
  74. OUT PWSTR* ppszDfs
  75. )
  76. {
  77. appAssert(NULL != pszDfsName);
  78. //
  79. // Do a quick check that this is a Dfs name
  80. //
  81. PWSTR pT;
  82. if ( L'\\' != pszDfsName[0]
  83. || L'\\' != pszDfsName[1]
  84. || L'\\' == pszDfsName[2] || L'\0' == pszDfsName[2]
  85. || (NULL == (pT = wcschr(&pszDfsName[3], L'\\')))
  86. )
  87. {
  88. return FALSE;
  89. }
  90. *ppszDfs = &pszDfsName[2];
  91. //
  92. // Go to next slash or end
  93. //
  94. pT++;
  95. while (*pT != L'\\' && *pT != L'\0')
  96. pT++;
  97. *pT = L'\0';
  98. appDebugOut((DEB_TRACE,
  99. "GetDfs: Dfs: %ws\n",
  100. *ppszDfs));
  101. return TRUE;
  102. }
  103. VOID
  104. CmdMap(
  105. IN PWSTR pszDfsPath,
  106. IN PWSTR pszUncPath,
  107. IN PWSTR pszComment,
  108. IN BOOLEAN fRestore
  109. )
  110. {
  111. appDebugOut((DEB_TRACE,"CmdMap(%ws, %ws, %ws)\n",
  112. pszDfsPath, pszUncPath, pszComment));
  113. PWSTR pszServer, pszShare;
  114. if (!GetServerShare(pszUncPath, &pszServer, &pszShare))
  115. {
  116. Usage();
  117. }
  118. NET_API_STATUS status = NetDfsAdd(
  119. pszDfsPath,
  120. pszServer,
  121. pszShare,
  122. pszComment,
  123. (fRestore == FALSE) ?
  124. DFS_ADD_VOLUME : DFS_ADD_VOLUME | DFS_RESTORE_VOLUME);
  125. if (status == NERR_Success)
  126. {
  127. // Notify shell of change.
  128. appDebugOut((DEB_TRACE,
  129. "Notify shell about new path %ws\n",
  130. pszDfsPath));
  131. SHChangeNotify(SHCNE_MKDIR, SHCNF_PATH, pszDfsPath, NULL);
  132. }
  133. else
  134. {
  135. DfsErrorMessage(status);
  136. }
  137. }
  138. VOID
  139. CmdUnmap(
  140. IN PWSTR pszDfsPath
  141. )
  142. {
  143. appDebugOut((DEB_TRACE,"CmdUnmap(%ws)\n",
  144. pszDfsPath));
  145. //
  146. // Delete all the replicas, and hence the volume
  147. //
  148. HRESULT hr = S_OK;
  149. PDFS_INFO_3 pVolumeInfo = NULL;
  150. NET_API_STATUS status = NetDfsGetInfo(
  151. pszDfsPath,
  152. NULL,
  153. NULL,
  154. 3,
  155. (LPBYTE*)&pVolumeInfo);
  156. CHECK_NET_API_STATUS(status);
  157. if (NERR_Success == status)
  158. {
  159. // now, we have pVolumeInfo memory to delete
  160. for (ULONG i = 0; i < pVolumeInfo->NumberOfStorages; i++)
  161. {
  162. appDebugOut((DEB_TRACE,
  163. "Deleting replica %d of %d\n",
  164. i + 1, pVolumeInfo->NumberOfStorages));
  165. PDFS_STORAGE_INFO pDfsStorageInfo = &pVolumeInfo->Storage[i];
  166. status = NetDfsRemove(
  167. pszDfsPath,
  168. pDfsStorageInfo->ServerName,
  169. pDfsStorageInfo->ShareName);
  170. if (status != NERR_Success)
  171. {
  172. DfsErrorMessage(status);
  173. }
  174. }
  175. NetApiBufferFree(pVolumeInfo);
  176. }
  177. else
  178. {
  179. DfsErrorMessage(status);
  180. }
  181. // Notify shell of change.
  182. appDebugOut((DEB_TRACE,
  183. "Notify shell about deleted path %ws\n",
  184. pszDfsPath));
  185. SHChangeNotify(SHCNE_RMDIR, SHCNF_PATH, pszDfsPath, NULL);
  186. }
  187. VOID
  188. CmdAdd(
  189. IN PWSTR pszDfsPath,
  190. IN PWSTR pszUncPath,
  191. IN BOOLEAN fRestore
  192. )
  193. {
  194. appDebugOut((DEB_TRACE,"CmdAdd(%ws, %ws)\n",
  195. pszDfsPath, pszUncPath));
  196. PWSTR pszServer, pszShare;
  197. if (!GetServerShare(pszUncPath, &pszServer, &pszShare))
  198. {
  199. Usage();
  200. }
  201. NET_API_STATUS status = NetDfsAdd(
  202. pszDfsPath,
  203. pszServer,
  204. pszShare,
  205. NULL,
  206. (fRestore == FALSE) ? 0 : DFS_RESTORE_VOLUME);
  207. if (status != NERR_Success)
  208. {
  209. DfsErrorMessage(status);
  210. }
  211. }
  212. VOID
  213. CmdRemove(
  214. IN PWSTR pszDfsPath,
  215. IN PWSTR pszUncPath
  216. )
  217. {
  218. appDebugOut((DEB_TRACE,"CmdRemove(%ws, %ws)\n",
  219. pszDfsPath, pszUncPath));
  220. PWSTR pszServer, pszShare;
  221. if (!GetServerShare(pszUncPath, &pszServer, &pszShare))
  222. {
  223. Usage();
  224. }
  225. NET_API_STATUS status = NetDfsRemove(
  226. pszDfsPath,
  227. pszServer,
  228. pszShare);
  229. if (status != NERR_Success)
  230. {
  231. DfsErrorMessage(status);
  232. }
  233. }
  234. VOID
  235. CmdView(
  236. IN PWSTR pszDfsName, // of form \\dfsname\dfsshare
  237. IN DWORD level,
  238. IN BOOLEAN fBatch,
  239. IN BOOLEAN fRestore
  240. )
  241. {
  242. appDebugOut((DEB_TRACE,"CmdView(%ws, %d)\n",
  243. pszDfsName, level));
  244. PWSTR pszDfs; // of form 'dfsname'
  245. if (!GetDfs(pszDfsName, &pszDfs))
  246. {
  247. Usage();
  248. }
  249. DWORD entriesread;
  250. LPBYTE buffer;
  251. DWORD resumeHandle = 0;
  252. NET_API_STATUS status = NetDfsEnum(
  253. pszDfs,
  254. level,
  255. 0xffffffff,
  256. (LPBYTE*)&buffer,
  257. &entriesread,
  258. &resumeHandle);
  259. if (status == NERR_Success)
  260. {
  261. PDFS_INFO_3 pDfsInfo = (PDFS_INFO_3)buffer;
  262. DWORD i, j;
  263. LPDFS_STORAGE_INFO pStorage;
  264. #if DBG == 1
  265. appDebugOut((DEB_TRACE,"NetDfsEnum returned %d entries\n", entriesread));
  266. for (i = 0; i < entriesread; i++)
  267. {
  268. if (level == 1)
  269. {
  270. pDfsInfo = (PDFS_INFO_3)(&(((PDFS_INFO_1)buffer)[i]));
  271. }
  272. else if (level == 2)
  273. {
  274. pDfsInfo = (PDFS_INFO_3)(&(((PDFS_INFO_2)buffer)[i]));
  275. }
  276. else if (level == 3)
  277. {
  278. pDfsInfo = &(((PDFS_INFO_3)buffer)[i]);
  279. }
  280. else
  281. {
  282. // bug!
  283. break;
  284. }
  285. appDebugOut((DEB_TRACE,"\t%ws\n", pDfsInfo->EntryPath));
  286. }
  287. pDfsInfo = (PDFS_INFO_3)buffer;
  288. #endif // DBG == 1
  289. if (fBatch == FALSE)
  290. {
  291. for (i = 0; i < entriesread; i++)
  292. {
  293. DfscmdPrintf(L"%ws", pDfsInfo->EntryPath);
  294. if (level == 1)
  295. {
  296. DfscmdPrintf(L"\r\n");
  297. pDfsInfo = (LPDFS_INFO_3)
  298. ((LPBYTE) pDfsInfo + sizeof(DFS_INFO_1));
  299. continue;
  300. }
  301. if (L'\0' != *pDfsInfo->Comment)
  302. {
  303. // Print the comment at column 60.
  304. int len = wcslen(pDfsInfo->EntryPath);
  305. while (len++ < 58)
  306. {
  307. DfscmdPrintf(L" "); // putchar?
  308. }
  309. DfscmdPrintf(L" %ws\r\n", pDfsInfo->Comment);
  310. }
  311. else
  312. {
  313. DfscmdPrintf(L"\r\n");
  314. }
  315. if (level == 2)
  316. {
  317. pDfsInfo = (LPDFS_INFO_3)
  318. ((LPBYTE) pDfsInfo + sizeof(DFS_INFO_2));
  319. continue;
  320. }
  321. pStorage = pDfsInfo->Storage;
  322. for (j = 0; j < pDfsInfo->NumberOfStorages; j++)
  323. {
  324. DfscmdPrintf(L"\t\\\\%ws\\%ws\r\n",
  325. pStorage[j].ServerName,
  326. pStorage[j].ShareName);
  327. }
  328. pDfsInfo = (LPDFS_INFO_3)
  329. ((LPBYTE) pDfsInfo + sizeof(DFS_INFO_3));
  330. }
  331. }
  332. else
  333. {
  334. DfscmdPrintf(L"REM BATCH RESTORE SCRIPT\r\n\r\n");
  335. for (i = 0; i < entriesread; i++)
  336. {
  337. pStorage = pDfsInfo->Storage;
  338. for (j = 0; j < pDfsInfo->NumberOfStorages; j++)
  339. {
  340. if (pDfsInfo->Comment == NULL
  341. ||
  342. j > 0
  343. ||
  344. (wcslen(pDfsInfo->Comment) == 1 && pDfsInfo->Comment[0] == L' ')
  345. ) {
  346. DfscmdPrintf(L"%wsdfscmd /%ws \"%ws\" \"\\\\%ws\\%ws\"%ws\r\n",
  347. (i == 0) ? L"REM " : L"",
  348. (j == 0) ? L"map" : L"add",
  349. pDfsInfo->EntryPath,
  350. pStorage[j].ServerName,
  351. pStorage[j].ShareName,
  352. (fRestore == TRUE) ? L" /restore" : L"");
  353. } else {
  354. DfscmdPrintf(L"%wsdfscmd /%ws \"%ws\" \"\\\\%ws\\%ws\" \"%ws\"%ws\r\n",
  355. (i == 0) ? L"REM " : L"",
  356. (j == 0) ? L"map" : L"add",
  357. pDfsInfo->EntryPath,
  358. pStorage[j].ServerName,
  359. pStorage[j].ShareName,
  360. pDfsInfo->Comment,
  361. (fRestore == TRUE) ? L" /restore" : L"");
  362. }
  363. }
  364. DfscmdPrintf(L"\r\n");
  365. pDfsInfo = (LPDFS_INFO_3) ((LPBYTE) pDfsInfo + sizeof(DFS_INFO_3));
  366. }
  367. }
  368. NetApiBufferFree( buffer );
  369. }
  370. else
  371. {
  372. DfsErrorMessage(status);
  373. }
  374. }
  375. //
  376. // The following is copied from dfsutil code, which allows redirection of
  377. // output to a file.
  378. //
  379. #define MAX_MESSAGE_BUF 4096
  380. #define MAX_ANSI_MESSAGE_BUF (MAX_MESSAGE_BUF * 3)
  381. WCHAR MsgBuf[MAX_MESSAGE_BUF];
  382. CHAR AnsiBuf[MAX_ANSI_MESSAGE_BUF];
  383. ULONG
  384. DfscmdPrintf(
  385. PWCHAR format,
  386. ...)
  387. {
  388. DWORD written;
  389. va_list va;
  390. va_start(va, format);
  391. wvsprintf(MsgBuf, format, va);
  392. written = WideCharToMultiByte(CP_OEMCP, 0,
  393. MsgBuf, wcslen(MsgBuf),
  394. AnsiBuf, MAX_ANSI_MESSAGE_BUF,
  395. NULL, NULL);
  396. WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), AnsiBuf, written, &written, NULL);
  397. va_end(va);
  398. return written;
  399. }
  400. #ifdef MOVERENAME
  401. VOID
  402. CmdMove(
  403. IN PWSTR pszDfsPath1,
  404. IN PWSTR pszDfsPath2
  405. )
  406. {
  407. appDebugOut((DEB_TRACE,"CmdMove(%ws, %ws)\n",
  408. pszDfsPath1, pszDfsPath2));
  409. NET_API_STATUS status = NetDfsMove(
  410. pszDfsPath1,
  411. pszDfsPath2);
  412. if (status != NERR_Success)
  413. {
  414. DfsErrorMessage(status);
  415. }
  416. }
  417. VOID
  418. CmdRename(
  419. IN PWSTR pszPath,
  420. IN PWSTR pszNewPath
  421. )
  422. {
  423. appDebugOut((DEB_TRACE,"CmdRename(%ws, %ws)\n",
  424. pszPath, pszNewPath));
  425. NET_API_STATUS status = NetDfsRename(
  426. pszPath,
  427. pszNewPath);
  428. if (status != NERR_Success)
  429. {
  430. DfsErrorMessage(status);
  431. }
  432. }
  433. #endif