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.

2421 lines
67 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. cliparse.cpp
  5. Abstract:
  6. Implements CLI parsing engine
  7. Author:
  8. Ravisankar Pudipeddi [ravisp] 3-March-2000
  9. Revision History:
  10. --*/
  11. //
  12. // Throughout this parse module, we return E_NOINTERFACE
  13. // to indicate invalid command line syntax/parameters.
  14. // This is to explicitly distinguish from E_INVALIDARG that may
  15. // be returned by the CLI dll: we wish to distinguish a syntax error
  16. // detected by the parser from a syntax error detected by the CLI dll
  17. // because in the latter case we do not print the usage for the interface.
  18. // Whereas for errors detected by the parser, we *do* print the usage.
  19. // This rule needs to be strictly adhered to
  20. //
  21. #include "stdafx.h"
  22. #include "stdlib.h"
  23. #include "cliparse.h"
  24. #include "string.h"
  25. #include "locale.h"
  26. #include "winnlsp.h"
  27. #pragma warning( disable : 4100 )
  28. CComModule _Module;
  29. CComPtr<IWsbTrace> g_pTrace;
  30. #define MAX_ARGS 40
  31. #define MAX_SWITCHES 20
  32. //
  33. // List of all CLI keywords
  34. // TBD: Sort them!
  35. //
  36. RSS_KEYWORD RssInterfaceStrings[] = {
  37. {L"ADMIN", L"AD", ADMIN_IF},
  38. {L"VOLUME", L"VL", VOLUME_IF},
  39. {L"MEDIA", L"MD", MEDIA_IF},
  40. {L"FILE", L"FL", FILE_IF},
  41. {L"SHOW", L"SH", SHOW_IF},
  42. {L"SET", L"ST", SET_IF},
  43. {L"MANAGE", L"MG", MANAGE_IF},
  44. {L"UNMANAGE", L"UM", UNMANAGE_IF},
  45. {L"DELETE", L"DL", DELETE_IF},
  46. {L"JOB", L"JB", JOB_IF},
  47. {L"RECALL", L"RC", RECALL_IF},
  48. {L"SYNCHRONIZE", L"SN", SYNCHRONIZE_IF},
  49. {L"RECREATEMASTER", L"RM", RECREATEMASTER_IF},
  50. {L"HELP", L"/?", HELP_IF},
  51. //
  52. // Duplicate entry for HELP to recognize -? also as a help
  53. // interface
  54. //
  55. {L"HELP", L"-?", HELP_IF},
  56. {NULL, NULL, UNKNOWN_IF}
  57. };
  58. //
  59. // Rss option strings - listed here without the preceding
  60. // '/' or '-' (or whatever that distinguishes a switch from
  61. // an argument)
  62. // TBD: Sort them!
  63. //
  64. RSS_SWITCH_DEFINITION RssSwitchStrings[] = {
  65. {L"RECALLLIMIT", L"LM", RECALLLIMIT_SW, RSS_ARG_DWORD},
  66. {L"MEDIACOPIES", L"MC", MEDIACOPIES_SW, RSS_ARG_DWORD},
  67. {L"SCHEDULE", L"SC", SCHEDULE_SW, RSS_ARG_STRING},
  68. {L"CONCURRENCY", L"CN", CONCURRENCY_SW, RSS_ARG_DWORD},
  69. {L"ADMINEXEMPT", L"AE", ADMINEXEMPT_SW, RSS_ARG_DWORD},
  70. {L"GENERAL", L"GN", GENERAL_SW, RSS_NO_ARG},
  71. {L"MANAGEABLES", L"MS", MANAGEABLES_SW, RSS_NO_ARG},
  72. {L"MANAGED", L"MN", MANAGED_SW, RSS_NO_ARG},
  73. {L"MEDIA", L"MD", MEDIA_SW, RSS_NO_ARG},
  74. {L"DFS", L"DF", DFS_SW, RSS_ARG_DWORD},
  75. {L"SIZE", L"SZ", SIZE_SW, RSS_ARG_DWORD},
  76. {L"ACCESS", L"AC", ACCESS_SW, RSS_ARG_DWORD},
  77. {L"INCLUDE", L"IN", INCLUDE_SW, RSS_ARG_STRING},
  78. {L"EXCLUDE", L"EX", EXCLUDE_SW, RSS_ARG_STRING},
  79. {L"RECURSIVE", L"RC", RECURSIVE_SW, RSS_NO_ARG},
  80. {L"QUICK", L"QK", QUICK_SW, RSS_NO_ARG},
  81. {L"FULL", L"FL", FULL_SW, RSS_NO_ARG},
  82. {L"RULE", L"RL", RULE_SW, RSS_ARG_STRING},
  83. {L"STATISTICS", L"ST", STATISTICS_SW, RSS_NO_ARG},
  84. {L"TYPE", L"TY", TYPE_SW, RSS_ARG_STRING},
  85. {L"RUN", L"RN", RUN_SW, RSS_NO_ARG},
  86. {L"CANCEL", L"CX", CANCEL_SW, RSS_NO_ARG},
  87. {L"WAIT", L"WT", WAIT_SW, RSS_NO_ARG},
  88. {L"COPYSET", L"CS", COPYSET_SW, RSS_ARG_DWORD},
  89. {L"NAME", L"NM", NAME_SW, RSS_ARG_STRING},
  90. {L"STATUS", L"SS", STATUS_SW, RSS_NO_ARG},
  91. {L"CAPACITY", L"CP", CAPACITY_SW, RSS_NO_ARG},
  92. {L"FREESPACE", L"FS", FREESPACE_SW, RSS_NO_ARG},
  93. {L"VERSION", L"VR", VERSION_SW, RSS_NO_ARG},
  94. {L"COPIES", L"CP", COPIES_SW, RSS_NO_ARG},
  95. {L"HELP", L"?", HELP_SW, RSS_NO_ARG},
  96. {NULL, NULL, UNKNOWN_SW, RSS_NO_ARG}
  97. };
  98. RSS_JOB_DEFINITION RssJobTypeStrings[] = {
  99. {L"CREATEFREESPACE", L"F", CreateFreeSpace},
  100. {L"COPYFILES", L"C", CopyFiles},
  101. {L"VALIDATE", L"V", Validate},
  102. {NULL, NULL, InvalidJobType}
  103. };
  104. //
  105. // Global arrays of arguments and switches
  106. // These will be used as 'known' entities by all
  107. // the interface implementations instead of passing
  108. // them around as parameters
  109. //
  110. LPWSTR Args[MAX_ARGS];
  111. RSS_SWITCHES Switches[MAX_SWITCHES];
  112. DWORD NumberOfArguments = 0;
  113. DWORD NumberOfSwitches = 0;
  114. //
  115. // Useful macros
  116. //
  117. #define CLIP_ARGS_REQUIRED() { \
  118. if (NumberOfArguments <= 0) { \
  119. WsbThrow(E_NOINTERFACE); \
  120. } \
  121. }
  122. #define CLIP_ARGS_NOT_REQUIRED() { \
  123. if (NumberOfArguments > 0) { \
  124. WsbThrow(E_NOINTERFACE); \
  125. } \
  126. }
  127. #define CLIP_SWITCHES_REQUIRED() { \
  128. if (NumberOfSwitches <= 0) { \
  129. WsbThrow(E_NOINTERFACE); \
  130. } \
  131. }
  132. #define CLIP_SWITCHES_NOT_REQUIRED() { \
  133. if (NumberOfSwitches > 0) { \
  134. WsbThrow(E_NOINTERFACE); \
  135. } \
  136. }
  137. #define CLIP_TRANSLATE_HR_AND_RETURN(__HR) { \
  138. if (__HR == S_OK) { \
  139. return CLIP_ERROR_SUCCESS; \
  140. } else if ((__HR == E_NOINTERFACE) || \
  141. (__HR == E_INVALIDARG)) { \
  142. return CLIP_ERROR_INVALID_PARAMETER; \
  143. } else if (__HR == E_OUTOFMEMORY) { \
  144. return CLIP_ERROR_INSUFFICIENT_MEMORY; \
  145. } else { \
  146. return CLIP_ERROR_UNKNOWN; \
  147. } \
  148. }
  149. #define CLIP_GET_DWORD_ARG(__VAL, __STRING, __STOPSTRING) { \
  150. __VAL = wcstol(__STRING, &(__STOPSTRING), 10); \
  151. if (*(__STOPSTRING) != L'\0') { \
  152. WsbThrow(E_NOINTERFACE); \
  153. } \
  154. }
  155. #define CLIP_VALIDATE_DUPLICATE_DWORD_ARG(__ARG) { \
  156. if ((__ARG) != INVALID_DWORD_ARG) { \
  157. WsbThrow(E_NOINTERFACE); \
  158. } \
  159. }
  160. #define CLIP_VALIDATE_DUPLICATE_POINTER_ARG(__ARG) { \
  161. if ((__ARG) != INVALID_POINTER_ARG) { \
  162. WsbThrow(E_NOINTERFACE); \
  163. } \
  164. }
  165. //
  166. // Local function prototypes
  167. //
  168. RSS_INTERFACE
  169. ClipGetInterface(
  170. IN LPWSTR InterfaceString
  171. );
  172. DWORD
  173. ClipGetSwitchTypeIndex(
  174. IN LPWSTR SwitchString
  175. );
  176. HSM_JOB_TYPE
  177. ClipGetJobType(
  178. IN LPWSTR JobTypeString
  179. );
  180. HRESULT
  181. ClipCompileSwitchesAndArgs(
  182. IN LPWSTR CommandLine,
  183. IN RSS_INTERFACE Interface,
  184. IN RSS_INTERFACE SubInterface
  185. );
  186. VOID
  187. ClipCleanup(
  188. VOID
  189. );
  190. HRESULT
  191. ClipAdminShow(
  192. VOID
  193. );
  194. HRESULT
  195. ClipAdminSet(
  196. VOID
  197. );
  198. HRESULT
  199. ClipVolumeShow(
  200. VOID
  201. );
  202. HRESULT
  203. ClipVolumeUnmanage(
  204. VOID
  205. );
  206. HRESULT
  207. ClipVolumeSetManage(
  208. IN BOOL Set
  209. );
  210. HRESULT
  211. ClipVolumeDelete(
  212. VOID
  213. );
  214. HRESULT
  215. ClipVolumeJob(
  216. VOID
  217. );
  218. HRESULT
  219. ClipMediaShow(
  220. VOID
  221. );
  222. HRESULT
  223. ClipMediaSynchronize(
  224. VOID
  225. );
  226. HRESULT
  227. ClipMediaRecreateMaster(
  228. VOID
  229. );
  230. HRESULT
  231. ClipMediaDelete(
  232. VOID
  233. );
  234. HRESULT
  235. ClipFileRecall(
  236. VOID
  237. );
  238. VOID
  239. ClipHelp(
  240. IN RSS_INTERFACE Interface,
  241. IN RSS_INTERFACE SubInterface
  242. );
  243. HRESULT
  244. ClipParseTime(
  245. IN LPWSTR TimeString,
  246. OUT PSYSTEMTIME ScheduledTime
  247. );
  248. HRESULT
  249. ClipParseSchedule(
  250. IN LPWSTR ScheduleString,
  251. OUT PHSM_JOB_SCHEDULE Schedule
  252. );
  253. BOOL
  254. ClipInitializeTrace(
  255. VOID
  256. );
  257. VOID
  258. ClipUninitializeTrace(
  259. VOID
  260. );
  261. VOID
  262. ClipHandleErrors(
  263. IN HRESULT RetCode,
  264. IN RSS_INTERFACE Interface,
  265. IN RSS_INTERFACE SubInterface
  266. );
  267. //
  268. // Function bodies start here
  269. //
  270. RSS_INTERFACE
  271. ClipGetInterface(
  272. IN LPWSTR InterfaceString
  273. )
  274. /*++
  275. Routine Description:
  276. Maps the interface string that is supplied to an enum
  277. Arguments
  278. InterfaceString - Pointer to the interface string
  279. TBD: implement a binary search
  280. Return Value
  281. UNKNOWN_IF - if the interface string is not recognized
  282. An RSS_INTERFACE value if it is.
  283. --*/
  284. {
  285. DWORD i;
  286. RSS_INTERFACE ret = UNKNOWN_IF;
  287. WsbTraceIn(OLESTR("ClipHandleErrors"), OLESTR(""));
  288. for (i=0 ; TRUE ; i++) {
  289. if (RssInterfaceStrings[i].Long == NULL) {
  290. //
  291. // Reached end of table.
  292. //
  293. break;
  294. } else if ((_wcsicmp(RssInterfaceStrings[i].Short,
  295. InterfaceString) == 0) ||
  296. (_wcsicmp(RssInterfaceStrings[i].Long,
  297. InterfaceString) == 0)) {
  298. ret = RssInterfaceStrings[i].Interface;
  299. break;
  300. }
  301. }
  302. WsbTraceOut(OLESTR("ClipGetInterface"), OLESTR("Interface = <%ls>"), WsbLongAsString((LONG) ret));
  303. return ret;
  304. }
  305. DWORD
  306. ClipGetSwitchTypeIndex(
  307. IN LPWSTR SwitchString
  308. )
  309. /*++
  310. Routine Description
  311. Maps the Switch to an entry in the global list of switches
  312. and returns the index
  313. Arguments
  314. SwitchString - Pointer to switch string
  315. TBD: implement a binary search
  316. Return Value
  317. -1 - If the switch is not recognized
  318. A positive value (index to the entry) if it is
  319. --*/
  320. {
  321. DWORD i;
  322. WsbTraceIn(OLESTR("ClipGetSwitchTypeIndex"), OLESTR(""));
  323. for (i = 0; TRUE; i++) {
  324. if (RssSwitchStrings[i].Long == NULL) {
  325. //
  326. // Reached end of table.
  327. //
  328. i = -1;
  329. break;
  330. } else if ((_wcsicmp(RssSwitchStrings[i].Short,
  331. SwitchString) == 0) ||
  332. (_wcsicmp(RssSwitchStrings[i].Long,
  333. SwitchString) == 0)) {
  334. break;
  335. }
  336. }
  337. WsbTraceOut(OLESTR("ClipGetSwitchTypeIndex"), OLESTR("index = <%ls>"), WsbLongAsString((LONG) i));
  338. return i;
  339. }
  340. HSM_JOB_TYPE
  341. ClipGetJobType(
  342. IN LPWSTR JobTypeString
  343. )
  344. /*++
  345. Routine Description
  346. Maps the job string to an enum
  347. Arguments
  348. JobTypeString - Pointer to JobType string
  349. TBD: implement a binary search
  350. Return Value
  351. InvalidJobType - If the job type is not recognized
  352. HSM_JOB_TYPE value if it is
  353. --*/
  354. {
  355. DWORD i;
  356. HSM_JOB_TYPE jobType = InvalidJobType;
  357. WsbTraceIn(OLESTR("ClipGetJobType"), OLESTR(""));
  358. for (i = 0; TRUE; i++) {
  359. if (RssJobTypeStrings[i].Long == NULL) {
  360. //
  361. // Reached end of table.
  362. //
  363. break;
  364. }
  365. if ((_wcsicmp(RssJobTypeStrings[i].Short,
  366. JobTypeString) == 0) ||
  367. (_wcsicmp(RssJobTypeStrings[i].Long,
  368. JobTypeString) == 0)) {
  369. jobType = RssJobTypeStrings[i].JobType;
  370. break;
  371. }
  372. }
  373. WsbTraceOut(OLESTR("ClipGetJobType"), OLESTR("JobType = <%ls>"), WsbLongAsString((LONG) jobType));
  374. return jobType;
  375. }
  376. HRESULT
  377. ClipCompileSwitchesAndArgs(
  378. IN LPWSTR CommandLine,
  379. IN RSS_INTERFACE Interface,
  380. IN RSS_INTERFACE SubInterface
  381. )
  382. /*++
  383. Routine Description
  384. Parses the passed in string and compiles all switches
  385. (a switch is identified by an appropriate delimiter preceding
  386. it, such as a '/') into a global switches array (along with
  387. the arguments to the switch) and the rest of the parameters
  388. into an Args array
  389. Arguments
  390. CommandLine - String to be parsed
  391. Return Value
  392. S_OK if success
  393. --*/
  394. {
  395. HRESULT hr = S_OK;
  396. WCHAR token[MAX_PATH+1];
  397. LPWSTR p = CommandLine, pToken = token, switchArg = NULL, switchString = NULL;
  398. int cToken = 0;
  399. RSS_SWITCH_TYPE switchType;
  400. DWORD index;
  401. BOOL isSwitch, skipSpace;
  402. WsbTraceIn(OLESTR("ClipCompileSwitchesAndArgs"), OLESTR(""));
  403. try {
  404. if (p == NULL) {
  405. WsbThrow(S_OK);
  406. }
  407. while (*p != L'\0') {
  408. if (wcschr(SEPARATORS, *p) != NULL) {
  409. //
  410. // Skip white space
  411. //
  412. p++;
  413. continue;
  414. }
  415. if (wcschr(SWITCH_DELIMITERS, *p) != NULL) {
  416. isSwitch = TRUE;
  417. p++;
  418. if (*p == L'\0') {
  419. //
  420. // Badly formed - a SWITCH_DELIMITER with no switch
  421. //
  422. WsbThrow(E_NOINTERFACE);
  423. }
  424. } else {
  425. isSwitch = FALSE;
  426. }
  427. //
  428. // Get the rest of the word
  429. //
  430. skipSpace = FALSE;
  431. while (*p != L'\0' && *p != L'\n') {
  432. //
  433. // We wish to consider stuff enclosed entirely in
  434. // quotes as a single token. As a result
  435. // we won't consider white space to be a delimiter
  436. // for tokens when they are in quotes.
  437. //
  438. if (*p == QUOTE) {
  439. if (skipSpace) {
  440. //
  441. // A quote was encountered previously.
  442. // This signifies - hence - the end of the token
  443. //
  444. p++;
  445. break;
  446. } else {
  447. //
  448. // Start of quoted string..don't treat whitespace
  449. // as a delimiter anymore, only a quote will end the token
  450. //
  451. skipSpace = TRUE;
  452. p++;
  453. continue;
  454. }
  455. }
  456. if (!skipSpace && (wcschr(SEPARATORS, *p) != NULL)) {
  457. //
  458. // This is not quoted and white space was encountered..
  459. //
  460. break;
  461. }
  462. cToken++;
  463. if (cToken > MAX_PATH) {
  464. // Token is too large
  465. WsbThrow(E_NOINTERFACE);
  466. }
  467. *pToken++ = *p++;
  468. }
  469. *pToken = L'\0';
  470. if (isSwitch) {
  471. //
  472. // For a switch, we will have to further split it into
  473. // the switch part and the argument part
  474. //
  475. switchString = wcstok(token, SWITCH_ARG_DELIMITERS);
  476. index = ClipGetSwitchTypeIndex(switchString);
  477. if (index == -1) {
  478. //
  479. // Invalid switch. Get out.
  480. //
  481. WsbThrow(E_NOINTERFACE);
  482. }
  483. switchType = RssSwitchStrings[index].SwitchType;
  484. switchArg = wcstok(NULL, L"");
  485. //
  486. // Validation - badly formed commandline if either:
  487. // 1. An argument was supplied and the switch definition indicated
  488. // no argument was required
  489. // OR
  490. // 2. This is a non-SHOW interface (by default show interface
  491. // don't require arguments for options), and an argument was not
  492. // supplied even though the switch definition indicated one is
  493. // required.
  494. //
  495. // 3. This is a SHOW interface and an argument was supplied
  496. //
  497. if ( ((switchArg != NULL) &&
  498. (RssSwitchStrings[index].ArgRequired == RSS_NO_ARG)) ||
  499. ((SubInterface != SHOW_IF) && (switchArg == NULL) &&
  500. (RssSwitchStrings[index].ArgRequired != RSS_NO_ARG)) ||
  501. ((SubInterface == SHOW_IF) && (switchArg != NULL))) {
  502. WsbThrow(E_NOINTERFACE);
  503. }
  504. Switches[NumberOfSwitches].SwitchType = switchType;
  505. if (switchArg != NULL) {
  506. Switches[NumberOfSwitches].Arg = new WCHAR [wcslen(switchArg)+1];
  507. if (Switches[NumberOfSwitches].Arg == NULL) {
  508. WsbThrow(E_OUTOFMEMORY);
  509. }
  510. wcscpy(Switches[NumberOfSwitches].Arg, switchArg);
  511. } else {
  512. //
  513. // No arg for this switch
  514. //
  515. Switches[NumberOfSwitches].Arg = NULL;
  516. }
  517. NumberOfSwitches++;
  518. } else {
  519. //
  520. // This is an argument..
  521. //
  522. Args[NumberOfArguments] = new WCHAR [wcslen(token)+1];
  523. if (Args[NumberOfArguments] == NULL) {
  524. WsbThrow(E_OUTOFMEMORY);
  525. }
  526. wcscpy(Args[NumberOfArguments],
  527. token);
  528. NumberOfArguments++;
  529. }
  530. pToken = token;
  531. cToken = 0;
  532. }
  533. }WsbCatch(hr);
  534. WsbTraceOut(OLESTR("ClipCompileSwitchesAndArgs"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  535. return hr;
  536. }
  537. VOID
  538. ClipCleanup(VOID)
  539. /*++
  540. Routine Description
  541. Performs global cleanup for CLI parse module.
  542. Mainly - frees up all allocated arguments and switches
  543. Arguments
  544. None
  545. Return Value
  546. None
  547. --*/
  548. {
  549. DWORD i;
  550. WsbTraceIn(OLESTR("ClipCleanup"), OLESTR(""));
  551. for (i = 0; i < NumberOfArguments; i++) {
  552. delete [] Args[i];
  553. }
  554. for (i = 0; i < NumberOfSwitches; i++) {
  555. if (Switches[i].Arg != NULL) {
  556. delete [] Switches[i].Arg;
  557. }
  558. }
  559. WsbTraceOut(OLESTR("ClipCleanup"), OLESTR(""));
  560. }
  561. HRESULT
  562. ClipAdminShow(VOID)
  563. /*++
  564. Routine Description
  565. Implements RSS ADMIN SHOW interface.
  566. Arguments are in global arrays:
  567. Args - containing list of arguments
  568. Switches - containing list of switches
  569. Arguments
  570. None
  571. Return Value
  572. S_OK if everything's ok
  573. E_NOINTERFACE if args/switches are bad
  574. --*/
  575. {
  576. DWORD i;
  577. HRESULT hr;
  578. BOOL recallLimit = FALSE;
  579. BOOL adminExempt = FALSE;
  580. BOOL mediaCopies = FALSE;
  581. BOOL concurrency = FALSE;
  582. BOOL schedule = FALSE;
  583. BOOL general = FALSE;
  584. BOOL manageables = FALSE;
  585. BOOL managed = FALSE;
  586. BOOL media = FALSE;
  587. WsbTraceIn(OLESTR("ClipAdminShow"), OLESTR(""));
  588. try {
  589. //
  590. // No arguments needed for this interface
  591. //
  592. CLIP_ARGS_NOT_REQUIRED();
  593. if (NumberOfSwitches) {
  594. for (i = 0; i < NumberOfSwitches; i++) {
  595. switch (Switches[i].SwitchType) {
  596. case RECALLLIMIT_SW: {
  597. recallLimit = TRUE;
  598. break;
  599. }
  600. case ADMINEXEMPT_SW: {
  601. adminExempt = TRUE;
  602. break;
  603. }
  604. case MEDIACOPIES_SW: {
  605. mediaCopies = TRUE;
  606. break;
  607. }
  608. case CONCURRENCY_SW: {
  609. concurrency = TRUE;
  610. break;
  611. }
  612. case SCHEDULE_SW: {
  613. schedule = TRUE;
  614. break;
  615. }
  616. case GENERAL_SW: {
  617. general = TRUE;
  618. break;
  619. }
  620. case MANAGEABLES_SW: {
  621. manageables = TRUE;
  622. break;
  623. }
  624. case MANAGED_SW: {
  625. managed = TRUE;
  626. break;
  627. }
  628. case MEDIA_SW: {
  629. media = TRUE;
  630. break;
  631. }
  632. default: {
  633. // Unknown switch - get out
  634. WsbThrow(E_NOINTERFACE);
  635. }
  636. }
  637. }
  638. hr = AdminShow(recallLimit,
  639. adminExempt,
  640. mediaCopies,
  641. concurrency,
  642. schedule,
  643. general,
  644. manageables,
  645. managed,
  646. media);
  647. } else {
  648. hr = AdminShow(TRUE,
  649. TRUE,
  650. TRUE,
  651. TRUE,
  652. TRUE,
  653. TRUE,
  654. TRUE,
  655. TRUE,
  656. TRUE);
  657. }
  658. }WsbCatch(hr);
  659. WsbTraceOut(OLESTR("ClipAdminShow"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  660. return hr;
  661. }
  662. HRESULT
  663. ClipAdminSet(VOID)
  664. /*++
  665. Routine Description
  666. Implements RSS ADMIN SET interface.
  667. Arguments are in global arrays:
  668. Args - containing list of arguments
  669. Switches - containing list of switches
  670. Arguments
  671. None
  672. Return Value
  673. S_OK if everything's ok
  674. E_NOINTERFACE if arguments are invalid
  675. --*/
  676. {
  677. DWORD i;
  678. HRESULT hr;
  679. LPWSTR stopString = NULL;
  680. DWORD recallLimit = INVALID_DWORD_ARG;
  681. DWORD adminExempt = INVALID_DWORD_ARG;
  682. DWORD mediaCopies = INVALID_DWORD_ARG;
  683. DWORD concurrency = INVALID_DWORD_ARG;
  684. PHSM_JOB_SCHEDULE schedule = INVALID_POINTER_ARG;
  685. HSM_JOB_SCHEDULE schedAllocated;
  686. WsbTraceIn(OLESTR("ClipAdminSet"), OLESTR(""));
  687. try {
  688. //
  689. // No arguments needed for this interface
  690. //
  691. CLIP_ARGS_NOT_REQUIRED();
  692. if (NumberOfSwitches) {
  693. for (i = 0; i < NumberOfSwitches; i++) {
  694. switch (Switches[i].SwitchType) {
  695. case RECALLLIMIT_SW: {
  696. CLIP_VALIDATE_DUPLICATE_DWORD_ARG(recallLimit);
  697. CLIP_GET_DWORD_ARG(recallLimit,
  698. Switches[i].Arg,
  699. stopString);
  700. break;
  701. }
  702. case ADMINEXEMPT_SW: {
  703. CLIP_VALIDATE_DUPLICATE_DWORD_ARG(adminExempt);
  704. CLIP_GET_DWORD_ARG(adminExempt,
  705. Switches[i].Arg,
  706. stopString);
  707. break;
  708. }
  709. case MEDIACOPIES_SW: {
  710. CLIP_VALIDATE_DUPLICATE_DWORD_ARG(mediaCopies);
  711. CLIP_GET_DWORD_ARG(mediaCopies,
  712. Switches[i].Arg,
  713. stopString);
  714. break;
  715. }
  716. case CONCURRENCY_SW: {
  717. CLIP_VALIDATE_DUPLICATE_DWORD_ARG(concurrency);
  718. CLIP_GET_DWORD_ARG(concurrency,
  719. Switches[i].Arg,
  720. stopString);
  721. break;
  722. }
  723. case SCHEDULE_SW: {
  724. CLIP_VALIDATE_DUPLICATE_POINTER_ARG(schedule);
  725. hr = ClipParseSchedule(Switches[i].Arg,
  726. &schedAllocated);
  727. if (!SUCCEEDED(hr)) {
  728. WsbThrow(E_NOINTERFACE);
  729. } else {
  730. //
  731. // schedAllocated has the schedule
  732. //
  733. schedule = &schedAllocated;
  734. }
  735. break;
  736. }
  737. default: {
  738. // Unknown switch - get out
  739. WsbThrow(E_NOINTERFACE);
  740. }
  741. }
  742. }
  743. }
  744. hr = AdminSet(recallLimit,
  745. adminExempt,
  746. mediaCopies,
  747. concurrency,
  748. schedule);
  749. }WsbCatch(hr);
  750. WsbTraceOut(OLESTR("ClipAdminSet"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  751. return hr;
  752. }
  753. HRESULT
  754. ClipVolumeShow(VOID)
  755. /*++
  756. Routine Description
  757. Implements RSS VOLUME SHOW interface.
  758. Arguments are in global arrays:
  759. Args - containing list of arguments
  760. Switches - containing list of switches
  761. Arguments
  762. None
  763. Return Value
  764. S_OK if everything's ok
  765. E_NOINTERFACE if arguments are invalid
  766. --*/
  767. {
  768. DWORD i;
  769. HRESULT hr;
  770. LPWSTR stopString = NULL;
  771. BOOL dfs = FALSE;
  772. BOOL size = FALSE;
  773. BOOL access = FALSE;
  774. BOOL rules = FALSE;
  775. BOOL statistics = FALSE;
  776. WsbTraceIn(OLESTR("ClipVolumeShow"), OLESTR(""));
  777. try {
  778. //
  779. // Atleast one arg. required for this interface
  780. //
  781. CLIP_ARGS_REQUIRED();
  782. if (NumberOfSwitches == 0) {
  783. dfs = size = access = rules = statistics = TRUE;
  784. } else {
  785. for (i = 0; i < NumberOfSwitches; i++) {
  786. switch (Switches[i].SwitchType) {
  787. case DFS_SW: {
  788. dfs = TRUE;
  789. break;
  790. }
  791. case SIZE_SW: {
  792. size = TRUE;
  793. break;
  794. }
  795. case ACCESS_SW: {
  796. access = TRUE;
  797. break;
  798. }
  799. case RULE_SW: {
  800. rules = TRUE;
  801. break;
  802. }
  803. case STATISTICS_SW: {
  804. statistics = TRUE;
  805. break;
  806. }
  807. default: {
  808. //
  809. // Invalid option
  810. //
  811. WsbThrow(E_NOINTERFACE);
  812. }
  813. }
  814. }
  815. }
  816. hr = VolumeShow(Args,
  817. NumberOfArguments,
  818. dfs,
  819. size,
  820. access,
  821. rules,
  822. statistics);
  823. }WsbCatch(hr);
  824. WsbTraceOut(OLESTR("ClipVolumeShow"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  825. return hr;
  826. }
  827. HRESULT
  828. ClipVolumeUnmanage(VOID)
  829. /*++
  830. Routine Description
  831. Implements RSS VOLUME UNMANAGE interface.
  832. Arguments are in global arrays:
  833. Args - containing list of arguments
  834. Switches - containing list of switches
  835. Arguments
  836. None
  837. Return Value
  838. S_OK if everything's ok
  839. E_NOINTERFACE if arguments are invalid
  840. --*/
  841. {
  842. DWORD i = 0;
  843. HRESULT hr;
  844. #define QUICK_UNMANAGE 0
  845. #define FULL_UNMANAGE 1
  846. DWORD fullOrQuick = INVALID_DWORD_ARG;
  847. WsbTraceIn(OLESTR("ClipVolumeUnmanage"), OLESTR(""));
  848. try {
  849. //
  850. // Atleast one arg. required for this interface
  851. //
  852. CLIP_ARGS_REQUIRED();
  853. if (NumberOfSwitches) {
  854. for (i = 0; i < NumberOfSwitches; i++) {
  855. switch (Switches[i].SwitchType) {
  856. case FULL_SW: {
  857. CLIP_VALIDATE_DUPLICATE_DWORD_ARG(fullOrQuick);
  858. fullOrQuick = FULL_UNMANAGE;
  859. break;
  860. }
  861. case QUICK_SW: {
  862. CLIP_VALIDATE_DUPLICATE_DWORD_ARG(fullOrQuick);
  863. fullOrQuick = QUICK_UNMANAGE;
  864. break;
  865. }
  866. default: {
  867. //
  868. // Invalid option
  869. //
  870. WsbThrow(E_NOINTERFACE);
  871. }
  872. }
  873. }
  874. }
  875. //
  876. // The default for UNMANAGE is quick. So if fullOrQuick is either
  877. // QUICK_UNMANAGE or INVALID_DWORD_ARG, we call unmanage of the quick
  878. // variety
  879. //
  880. hr = VolumeUnmanage(Args,
  881. NumberOfArguments,
  882. (fullOrQuick == FULL_UNMANAGE)? TRUE : FALSE);
  883. }WsbCatch(hr);
  884. WsbTraceOut(OLESTR("ClipVolumeUnmanage"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  885. return hr;
  886. }
  887. HRESULT
  888. ClipVolumeSetManage(IN BOOL Set)
  889. /*++
  890. Routine Description
  891. Implements RSS VOLUME MANAGE & RSS VOLUME SET interfaces.
  892. Arguments are in global arrays:
  893. Args - containing list of arguments
  894. Switches - containing list of switches
  895. Arguments
  896. None
  897. Return Value
  898. CLIP_ERROR_SUCCESS if everything's ok
  899. CLIP_ERROR_INVALID_PARAMETER if args/switches are bad
  900. CLIP_ERROR_UNKNOWN any other error
  901. --*/
  902. {
  903. DWORD i = 0;
  904. HRESULT hr;
  905. LPWSTR stopString = NULL;
  906. DWORD dfs = INVALID_DWORD_ARG;
  907. DWORD size = INVALID_DWORD_ARG;
  908. DWORD access = INVALID_DWORD_ARG;
  909. LPWSTR rulePath = INVALID_POINTER_ARG;
  910. LPWSTR ruleFileSpec = INVALID_POINTER_ARG;
  911. BOOL include = FALSE;
  912. BOOL recursive = FALSE;
  913. WsbTraceIn(OLESTR("ClipVolumeSetManage"), OLESTR(""));
  914. try {
  915. //
  916. // Atleast one arg. required for this interface
  917. //
  918. CLIP_ARGS_REQUIRED();
  919. if (NumberOfSwitches) {
  920. for (i = 0; i < NumberOfSwitches; i++) {
  921. switch (Switches[i].SwitchType) {
  922. case DFS_SW: {
  923. CLIP_VALIDATE_DUPLICATE_DWORD_ARG(dfs);
  924. CLIP_GET_DWORD_ARG(dfs, Switches[i].Arg, stopString);
  925. break;
  926. }
  927. case SIZE_SW: {
  928. CLIP_VALIDATE_DUPLICATE_DWORD_ARG(size);
  929. CLIP_GET_DWORD_ARG(size, Switches[i].Arg, stopString);
  930. break;
  931. }
  932. case ACCESS_SW: {
  933. CLIP_VALIDATE_DUPLICATE_DWORD_ARG(access);
  934. CLIP_GET_DWORD_ARG(access, Switches[i].Arg, stopString);
  935. break;
  936. }
  937. case INCLUDE_SW: {
  938. include = TRUE;
  939. //
  940. // Deliberately fall down to the EXCLUDE case
  941. // (break intentionally omitted)
  942. //
  943. }
  944. case EXCLUDE_SW: {
  945. CLIP_VALIDATE_DUPLICATE_POINTER_ARG(rulePath);
  946. rulePath = wcstok(Switches[i].Arg, RULE_DELIMITERS);
  947. ruleFileSpec = wcstok(NULL, L"");
  948. if (ruleFileSpec == NULL) {
  949. //
  950. // Omission of this indicates all files
  951. //
  952. ruleFileSpec = CLI_ALL_STR;
  953. }
  954. break;
  955. }
  956. case RECURSIVE_SW: {
  957. recursive = TRUE;
  958. break;
  959. }
  960. default: {
  961. WsbThrow(E_NOINTERFACE);
  962. }
  963. }
  964. }
  965. }
  966. //
  967. // Validate the rule arguments
  968. //
  969. if ((rulePath == INVALID_POINTER_ARG) && recursive) {
  970. //
  971. // The recursive flag is valid only if a rule was specified
  972. //
  973. WsbThrow(E_NOINTERFACE);
  974. }
  975. if (Set) {
  976. hr = VolumeSet(Args,
  977. NumberOfArguments,
  978. dfs,
  979. size,
  980. access,
  981. rulePath,
  982. ruleFileSpec,
  983. include,
  984. recursive);
  985. } else {
  986. hr = VolumeManage(Args,
  987. NumberOfArguments,
  988. dfs,
  989. size,
  990. access,
  991. rulePath,
  992. ruleFileSpec,
  993. include,
  994. recursive);
  995. }
  996. }WsbCatch(hr);
  997. WsbTraceOut(OLESTR("ClipVolumeSetManage"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  998. return hr;
  999. }
  1000. HRESULT
  1001. ClipVolumeDelete(VOID)
  1002. /*++
  1003. Routine Description
  1004. Implements RSS VOLUME DELETE interface.
  1005. Arguments are in global arrays:
  1006. Args - containing list of arguments
  1007. Switches - containing list of switches
  1008. Arguments
  1009. None
  1010. Return Value
  1011. S_OK if everything's ok
  1012. E_NOINTERFACE if arguments are invalid
  1013. --*/
  1014. {
  1015. DWORD i;
  1016. HRESULT hr;
  1017. BOOL rule = FALSE;
  1018. LPWSTR rulePath = INVALID_POINTER_ARG;
  1019. LPWSTR ruleFileSpec = INVALID_POINTER_ARG;
  1020. WsbTraceIn(OLESTR("ClipVolumeDelete"), OLESTR(""));
  1021. try {
  1022. //
  1023. // Atleast one arg. required for this interface
  1024. //
  1025. CLIP_ARGS_REQUIRED();
  1026. for (i = 0; i < NumberOfSwitches; i++) {
  1027. switch (Switches[i].SwitchType) {
  1028. case RULE_SW: {
  1029. CLIP_VALIDATE_DUPLICATE_POINTER_ARG(rulePath);
  1030. rule = TRUE;
  1031. rulePath = wcstok(Switches[i].Arg, RULE_DELIMITERS);
  1032. ruleFileSpec = wcstok(NULL, L"");
  1033. if (ruleFileSpec == NULL) {
  1034. //
  1035. // Omission of this indicates all files
  1036. //
  1037. ruleFileSpec = CLI_ALL_STR;
  1038. }
  1039. break;
  1040. }
  1041. default: {
  1042. //
  1043. // Invalid option
  1044. //
  1045. WsbThrow(E_NOINTERFACE);
  1046. }
  1047. }
  1048. }
  1049. //
  1050. // Only deleting rules is supported now
  1051. //
  1052. if (rule) {
  1053. hr = VolumeDeleteRule(Args,
  1054. NumberOfArguments,
  1055. rulePath,
  1056. ruleFileSpec);
  1057. } else {
  1058. hr = E_NOINTERFACE;
  1059. }
  1060. }WsbCatch(hr);
  1061. WsbTraceOut(OLESTR("ClipVolumeDelete"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1062. return hr;
  1063. }
  1064. HRESULT
  1065. ClipVolumeJob(VOID)
  1066. /*++
  1067. Routine Description
  1068. Implements RSS VOLUME JOB interface.
  1069. Arguments are in global arrays:
  1070. Args - containing list of arguments
  1071. Switches - containing list of switches
  1072. Arguments
  1073. None
  1074. Return Value
  1075. S_OK if everything's ok
  1076. E_NOINTERFACE if arguments are invalid
  1077. --*/
  1078. {
  1079. DWORD i;
  1080. HRESULT hr;
  1081. HSM_JOB_TYPE jobType = InvalidJobType;
  1082. #define CANCEL_JOB 0
  1083. #define RUN_JOB 1
  1084. DWORD runOrCancel = INVALID_DWORD_ARG;
  1085. BOOL synchronous = FALSE;
  1086. WsbTraceIn(OLESTR("ClipVolumeJob"), OLESTR(""));
  1087. try {
  1088. //
  1089. // Atleast one arg. required for this interface
  1090. //
  1091. CLIP_ARGS_REQUIRED();
  1092. for (i = 0; i < NumberOfSwitches; i++) {
  1093. switch (Switches[i].SwitchType) {
  1094. case RUN_SW: {
  1095. CLIP_VALIDATE_DUPLICATE_DWORD_ARG(runOrCancel);
  1096. runOrCancel = RUN_JOB;
  1097. break;
  1098. }
  1099. case CANCEL_SW: {
  1100. CLIP_VALIDATE_DUPLICATE_DWORD_ARG(runOrCancel);
  1101. runOrCancel = CANCEL_JOB;
  1102. break;
  1103. }
  1104. case WAIT_SW: {
  1105. synchronous = TRUE;
  1106. break;
  1107. }
  1108. case TYPE_SW: {
  1109. if (jobType != InvalidJobType) {
  1110. //
  1111. // Duplicate switch. Bail
  1112. //
  1113. WsbThrow(E_NOINTERFACE);
  1114. }
  1115. jobType = ClipGetJobType(Switches[i].Arg);
  1116. if (jobType == InvalidJobType) {
  1117. //
  1118. // Invalid job type supplied..
  1119. //
  1120. WsbThrow(E_NOINTERFACE);
  1121. }
  1122. break;
  1123. }
  1124. default: {
  1125. WsbThrow(E_NOINTERFACE);
  1126. }
  1127. }
  1128. }
  1129. //
  1130. // More validation:
  1131. // job type should be valid i.e., specified
  1132. //
  1133. if (jobType == InvalidJobType) {
  1134. WsbThrow(E_NOINTERFACE);
  1135. }
  1136. //
  1137. // Run is the default.. (i.e. TRUE). So if runOrCancel is either
  1138. // INVALID_DWORD_ARG or RUN_JOB, we pass TRUE
  1139. //
  1140. hr = VolumeJob(Args,
  1141. NumberOfArguments,
  1142. jobType,
  1143. (runOrCancel == CANCEL_JOB)? FALSE: TRUE,
  1144. synchronous);
  1145. }WsbCatch(hr);
  1146. WsbTraceOut(OLESTR("ClipVolumeJob"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1147. return hr;
  1148. }
  1149. HRESULT
  1150. ClipMediaShow(VOID)
  1151. /*++
  1152. Routine Description
  1153. Implements RSS MEDIA SHOW interface.
  1154. Arguments are in global arrays:
  1155. Args - containing list of arguments
  1156. Switches - containing list of switches
  1157. Arguments
  1158. None
  1159. Return Value
  1160. S_OK if everything's ok
  1161. E_NOINTERFACE if arguments are invalid
  1162. --*/
  1163. {
  1164. DWORD i;
  1165. HRESULT hr;
  1166. BOOL name = FALSE;
  1167. BOOL status = FALSE;
  1168. BOOL capacity = FALSE;
  1169. BOOL freeSpace = FALSE;
  1170. BOOL version = FALSE;
  1171. BOOL copies = FALSE;
  1172. WsbTraceIn(OLESTR("ClipMediaShow"), OLESTR(""));
  1173. try {
  1174. //
  1175. // Atleast one arg. required for this interface
  1176. //
  1177. CLIP_ARGS_REQUIRED();
  1178. if (NumberOfSwitches == 0) {
  1179. name = status = capacity = freeSpace = version = copies = TRUE;
  1180. } else {
  1181. for (i = 0; i < NumberOfSwitches; i++) {
  1182. switch (Switches[i].SwitchType) {
  1183. case NAME_SW: {
  1184. name = TRUE;
  1185. break;
  1186. }
  1187. case STATUS_SW: {
  1188. status = TRUE;
  1189. break;
  1190. }
  1191. case CAPACITY_SW: {
  1192. capacity = TRUE;
  1193. break;
  1194. }
  1195. case FREESPACE_SW: {
  1196. freeSpace = TRUE;
  1197. break;
  1198. }
  1199. case VERSION_SW: {
  1200. version = TRUE;
  1201. break;
  1202. }
  1203. case COPIES_SW: {
  1204. copies = TRUE;
  1205. break;
  1206. }
  1207. default: {
  1208. //
  1209. // Invalid option
  1210. //
  1211. WsbThrow(E_NOINTERFACE);
  1212. }
  1213. }
  1214. }
  1215. }
  1216. hr = MediaShow(Args,
  1217. NumberOfArguments,
  1218. name,
  1219. status,
  1220. capacity,
  1221. freeSpace,
  1222. version,
  1223. copies);
  1224. }WsbCatch(hr);
  1225. WsbTraceOut(OLESTR("ClipMediaShow"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1226. return hr;
  1227. }
  1228. HRESULT
  1229. ClipMediaSynchronize(VOID)
  1230. /*++
  1231. Routine Description
  1232. Implements RSS MEDIA SYNCHRONIZE interface.
  1233. Arguments are in global arrays:
  1234. Args - containing list of arguments
  1235. Switches - containing list of switches
  1236. Arguments
  1237. None
  1238. Return Value
  1239. S_OK if everything's ok
  1240. E_NOINTERFACE if arguments are invalid
  1241. --*/
  1242. {
  1243. DWORD i;
  1244. HRESULT hr;
  1245. DWORD copySetNumber = INVALID_DWORD_ARG;
  1246. BOOL synchronous = FALSE;
  1247. LPWSTR stopString = NULL;
  1248. WsbTraceIn(OLESTR("ClipMediaSynchronize"), OLESTR(""));
  1249. try {
  1250. //
  1251. // No arguments needed
  1252. //
  1253. CLIP_ARGS_NOT_REQUIRED();
  1254. for (i = 0; i < NumberOfSwitches; i++) {
  1255. switch (Switches[i].SwitchType) {
  1256. case COPYSET_SW: {
  1257. CLIP_VALIDATE_DUPLICATE_DWORD_ARG(copySetNumber);
  1258. CLIP_GET_DWORD_ARG(copySetNumber, Switches[i].Arg, stopString);
  1259. break;
  1260. }
  1261. case WAIT_SW: {
  1262. synchronous = TRUE;
  1263. break;
  1264. }
  1265. default: {
  1266. //
  1267. // Invalid option
  1268. //
  1269. WsbThrow(E_NOINTERFACE);
  1270. }
  1271. }
  1272. }
  1273. //
  1274. // Need copy set number..
  1275. //
  1276. if (copySetNumber == INVALID_DWORD_ARG) {
  1277. //
  1278. // None was specified
  1279. //
  1280. WsbThrow(E_NOINTERFACE);
  1281. }
  1282. hr = MediaSynchronize(copySetNumber, synchronous);
  1283. }WsbCatch(hr);
  1284. WsbTraceOut(OLESTR("ClipMediaRecreateMaster"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1285. return hr;
  1286. }
  1287. HRESULT
  1288. ClipMediaRecreateMaster(VOID)
  1289. /*++
  1290. Routine Description
  1291. Implements RSS MEDIA RECREATEMASTER interface.
  1292. Arguments are in global arrays:
  1293. Args - containing list of arguments
  1294. Switches - containing list of switches
  1295. Arguments
  1296. None
  1297. Return Value
  1298. S_OK if everything's ok
  1299. E_NOINTERFACE if arguments are invalid
  1300. --*/
  1301. {
  1302. DWORD i;
  1303. HRESULT hr;
  1304. DWORD copySetNumber = INVALID_DWORD_ARG;
  1305. LPWSTR stopString = NULL;
  1306. BOOL synchronous = FALSE;
  1307. WsbTraceIn(OLESTR("ClipMediaRecreateMaster"), OLESTR(""));
  1308. try {
  1309. //
  1310. // Atleast one arg required
  1311. //
  1312. CLIP_ARGS_REQUIRED();
  1313. if (NumberOfArguments > 1) {
  1314. //
  1315. // Only one argument supported...
  1316. //
  1317. WsbThrow(E_NOINTERFACE);
  1318. }
  1319. for (i = 0; i < NumberOfSwitches; i++) {
  1320. switch (Switches[i].SwitchType) {
  1321. case COPYSET_SW: {
  1322. CLIP_VALIDATE_DUPLICATE_DWORD_ARG(copySetNumber);
  1323. CLIP_GET_DWORD_ARG(copySetNumber, Switches[i].Arg, stopString);
  1324. break;
  1325. }
  1326. case WAIT_SW: {
  1327. synchronous = TRUE;
  1328. break;
  1329. }
  1330. default: {
  1331. //
  1332. // Invalid option
  1333. //
  1334. WsbThrow(E_NOINTERFACE);
  1335. }
  1336. }
  1337. }
  1338. //
  1339. // Need copy set number..
  1340. //
  1341. if (copySetNumber == INVALID_DWORD_ARG) {
  1342. //
  1343. // None was specified
  1344. //
  1345. WsbThrow(E_NOINTERFACE);
  1346. }
  1347. hr = MediaRecreateMaster(Args[0],
  1348. copySetNumber,
  1349. synchronous);
  1350. }WsbCatch(hr);
  1351. WsbTraceOut(OLESTR("ClipRecreateMaster"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1352. return hr;
  1353. }
  1354. HRESULT
  1355. ClipMediaDelete(VOID)
  1356. /*++
  1357. Routine Description
  1358. Implements RSS MEDIA DELETE interface.
  1359. Arguments are in global arrays:
  1360. Args - containing list of arguments
  1361. Switches - containing list of switches
  1362. Arguments
  1363. None
  1364. Return Value
  1365. S_OK if everything's ok
  1366. E_NOINTERFACE if arguments are invalid
  1367. --*/
  1368. {
  1369. DWORD i;
  1370. HRESULT hr;
  1371. DWORD copySetNumber = INVALID_DWORD_ARG;
  1372. LPWSTR stopString = NULL;
  1373. WsbTraceIn(OLESTR("ClipMediaDelete"), OLESTR(""));
  1374. try {
  1375. //
  1376. // Atleast one arg required
  1377. //
  1378. CLIP_ARGS_REQUIRED();
  1379. for (i = 0; i < NumberOfSwitches; i++) {
  1380. switch (Switches[i].SwitchType) {
  1381. case COPYSET_SW: {
  1382. CLIP_VALIDATE_DUPLICATE_DWORD_ARG(copySetNumber);
  1383. CLIP_GET_DWORD_ARG(copySetNumber, Switches[i].Arg, stopString);
  1384. break;
  1385. }
  1386. default: {
  1387. //
  1388. // Invalid option
  1389. //
  1390. WsbThrow(E_NOINTERFACE);
  1391. }
  1392. }
  1393. }
  1394. //
  1395. // Need copy set number..
  1396. //
  1397. if (copySetNumber == INVALID_DWORD_ARG) {
  1398. //
  1399. // None was specified
  1400. //
  1401. WsbThrow(E_NOINTERFACE);
  1402. }
  1403. hr = MediaDelete(Args,
  1404. NumberOfArguments,
  1405. copySetNumber);
  1406. }WsbCatch(hr);
  1407. WsbTraceOut(OLESTR("ClipMediaDelete"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1408. return hr;
  1409. }
  1410. HRESULT
  1411. ClipFileRecall(VOID)
  1412. /*++
  1413. Routine Description
  1414. Implements RSS FILE RECALL interface.
  1415. Arguments are in global arrays:
  1416. Args - containing list of arguments
  1417. Switches - containing list of switches
  1418. Arguments
  1419. None
  1420. Return Value
  1421. S_OK if everything's ok
  1422. E_NOINTERFACE if arguments are invalid
  1423. --*/
  1424. {
  1425. HRESULT hr;
  1426. WsbTraceIn(OLESTR("ClipFileRecall"), OLESTR(""));
  1427. try {
  1428. //
  1429. // Atleast one arg. required for this interface
  1430. //
  1431. CLIP_ARGS_REQUIRED();
  1432. //
  1433. // No switches supported
  1434. //
  1435. CLIP_SWITCHES_NOT_REQUIRED();
  1436. hr = FileRecall(Args,
  1437. NumberOfArguments);
  1438. }WsbCatch(hr);
  1439. WsbTraceOut(OLESTR("ClipFileRecall"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1440. return hr;
  1441. }
  1442. VOID
  1443. ClipHelp(
  1444. IN RSS_INTERFACE Interface,
  1445. IN RSS_INTERFACE SubInterface
  1446. )
  1447. /*++
  1448. Routine Description
  1449. Prints appropriate help message depending on the interface
  1450. Arguments
  1451. Interface - Specifies interface for which help has to be
  1452. displayed
  1453. SubInterface - Specifies sub-interface for which help has to be
  1454. displayed
  1455. Return Value:
  1456. NONE
  1457. --*/
  1458. {
  1459. #define BREAK_IF_NOT_UNKNOWN_IF(__INTERFACE) { \
  1460. if (((__INTERFACE) != UNKNOWN_IF) && \
  1461. ((__INTERFACE) != HELP_IF)) { \
  1462. break; \
  1463. } \
  1464. }
  1465. WsbTraceIn(OLESTR("ClipHelp"), OLESTR(""));
  1466. switch (Interface) {
  1467. case HELP_IF:
  1468. case UNKNOWN_IF: {
  1469. WsbTraceAndPrint(CLI_MESSAGE_MAIN_HELP, NULL);
  1470. BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
  1471. }
  1472. case ADMIN_IF: {
  1473. switch (SubInterface) {
  1474. case HELP_IF:
  1475. case UNKNOWN_IF:
  1476. case SHOW_IF: {
  1477. WsbTraceAndPrint(CLI_MESSAGE_ADMIN_SHOW_HELP, NULL);
  1478. BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
  1479. }
  1480. case SET_IF: {
  1481. WsbTraceAndPrint(CLI_MESSAGE_ADMIN_SET_HELP, NULL);
  1482. BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
  1483. }
  1484. }
  1485. BREAK_IF_NOT_UNKNOWN_IF(Interface);
  1486. }
  1487. case VOLUME_IF: {
  1488. switch (SubInterface) {
  1489. case HELP_IF:
  1490. case UNKNOWN_IF:
  1491. case SHOW_IF: {
  1492. WsbTraceAndPrint(CLI_MESSAGE_VOLUME_SHOW_HELP, NULL);
  1493. BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
  1494. }
  1495. case SET_IF: {
  1496. WsbTraceAndPrint(CLI_MESSAGE_VOLUME_SET_HELP, NULL);
  1497. BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
  1498. }
  1499. case MANAGE_IF: {
  1500. WsbTraceAndPrint(CLI_MESSAGE_VOLUME_MANAGE_HELP, NULL);
  1501. BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
  1502. }
  1503. case UNMANAGE_IF: {
  1504. WsbTraceAndPrint(CLI_MESSAGE_VOLUME_UNMANAGE_HELP, NULL);
  1505. BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
  1506. }
  1507. case JOB_IF: {
  1508. WsbTraceAndPrint(CLI_MESSAGE_VOLUME_JOB_HELP, NULL);
  1509. BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
  1510. }
  1511. case DELETE_IF: {
  1512. WsbTraceAndPrint(CLI_MESSAGE_VOLUME_DELETE_HELP, NULL);
  1513. BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
  1514. }
  1515. }
  1516. BREAK_IF_NOT_UNKNOWN_IF(Interface);
  1517. }
  1518. case MEDIA_IF: {
  1519. switch (SubInterface) {
  1520. case HELP_IF:
  1521. case UNKNOWN_IF:
  1522. case SHOW_IF: {
  1523. WsbTraceAndPrint(CLI_MESSAGE_MEDIA_SHOW_HELP, NULL);
  1524. BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
  1525. }
  1526. case DELETE_IF: {
  1527. WsbTraceAndPrint(CLI_MESSAGE_MEDIA_DELETE_HELP, NULL);
  1528. BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
  1529. }
  1530. case SYNCHRONIZE_IF: {
  1531. WsbTraceAndPrint(CLI_MESSAGE_MEDIA_SYNCHRONIZE_HELP, NULL);
  1532. BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
  1533. }
  1534. case RECREATEMASTER_IF: {
  1535. WsbTraceAndPrint(CLI_MESSAGE_MEDIA_RECREATEMASTER_HELP, NULL);
  1536. BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
  1537. }
  1538. }
  1539. BREAK_IF_NOT_UNKNOWN_IF(Interface);
  1540. }
  1541. case FILE_IF: {
  1542. switch (SubInterface) {
  1543. case HELP_IF:
  1544. case UNKNOWN_IF:
  1545. case RECALL_IF: {
  1546. WsbTraceAndPrint(CLI_MESSAGE_FILE_RECALL_HELP, NULL);
  1547. BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
  1548. }
  1549. }
  1550. BREAK_IF_NOT_UNKNOWN_IF(Interface);
  1551. }
  1552. }
  1553. WsbTraceOut(OLESTR("ClipHelp"), OLESTR(""));
  1554. }
  1555. HRESULT
  1556. ClipParseTime(
  1557. IN LPWSTR TimeString,
  1558. OUT PSYSTEMTIME ScheduledTime)
  1559. /*++
  1560. Routine Description
  1561. Parses the passed in TimeString as a 24 hour format
  1562. (hh:mm:ss) and sets hour/minute/sec/millisec in the passed
  1563. in SYSTEMTIME structure
  1564. Arguments
  1565. TimeString - String in the format "hh:mm:ss"
  1566. ScheduledTime - Pointer to SYSTEMTIME structure. Time parsed from TimeString
  1567. (if ok) will be used to set hour/min/sec/millisec fields in this struc.
  1568. Return Value
  1569. S_OK - TimeString is valid and time was successfully parsed
  1570. Any other - Syntax error in TimeString
  1571. --*/
  1572. {
  1573. LPWSTR stopString = NULL, hourString = NULL, minuteString = NULL, secondString = NULL;
  1574. DWORD hour, minute, second = 0;
  1575. HRESULT hr = S_OK;
  1576. WsbTraceIn(OLESTR("ClipParseTime"), OLESTR(""));
  1577. try {
  1578. hourString = wcstok(TimeString, HSM_SCHED_TIME_SEPARATORS);
  1579. WsbAssert(hourString != NULL, E_NOINTERFACE);
  1580. CLIP_GET_DWORD_ARG(hour, hourString, stopString);
  1581. if (hour > 23) {
  1582. WsbThrow(E_NOINTERFACE);
  1583. }
  1584. minuteString = wcstok(NULL, HSM_SCHED_TIME_SEPARATORS);
  1585. WsbAssert(minuteString != NULL, E_NOINTERFACE);
  1586. CLIP_GET_DWORD_ARG(minute, minuteString, stopString);
  1587. if (minute > 59) {
  1588. WsbThrow(E_NOINTERFACE);
  1589. }
  1590. secondString = wcstok(NULL, HSM_SCHED_TIME_SEPARATORS);
  1591. if (secondString != NULL) {
  1592. CLIP_GET_DWORD_ARG(second, secondString, stopString);
  1593. if (second > 59) {
  1594. WsbThrow(E_NOINTERFACE);
  1595. }
  1596. }
  1597. ScheduledTime->wHour = (WORD) hour;
  1598. ScheduledTime->wMinute = (WORD) minute;
  1599. ScheduledTime->wSecond = (WORD) second;
  1600. ScheduledTime->wMilliseconds = 0;
  1601. }WsbCatch(hr);
  1602. WsbTraceOut(OLESTR("ClipParseTime"), OLESTR(""));
  1603. return hr;
  1604. }
  1605. HRESULT
  1606. ClipParseSchedule(
  1607. IN LPWSTR ScheduleString,
  1608. OUT PHSM_JOB_SCHEDULE Schedule
  1609. )
  1610. /*++
  1611. Routine Description
  1612. Parses the passed in schedule string, and constructs the canonical schedule
  1613. form (of type HSM_JOB_SCHEDULE)
  1614. Examples of schedule parameter:
  1615. "At 21:03:00"
  1616. "At Startup"
  1617. "At Login"
  1618. "At Idle"
  1619. "Every 1 Week 1 21:03:00"
  1620. "Every 2 Day 21:03:00"
  1621. "Every 1 Month 2 21:03:00"
  1622. Arguments
  1623. ScheduleString - String specifying the schedule in user-readable syntax
  1624. Schedule - Pointer to canonical schedule form will be returned in this var.
  1625. Return Value
  1626. S_OK - Successful, Schedule contains a pointer to the constructed schedule.
  1627. E_OUTOFMEMORY - Lack of sufficient system resources
  1628. Any other error: incorrect schedule specification
  1629. --*/
  1630. {
  1631. LPWSTR token;
  1632. DWORD occurrence;
  1633. HSM_JOB_FREQUENCY frequency;
  1634. SYSTEMTIME scheduledTime;
  1635. DWORD day;
  1636. HRESULT hr = S_OK;
  1637. WsbTraceIn(OLESTR("ClipParseSchedule"), OLESTR(""));
  1638. try {
  1639. token = wcstok(ScheduleString, SEPARATORS);
  1640. WsbAssert(token != NULL, E_NOINTERFACE);
  1641. if (!_wcsicmp(token, HSM_SCHED_AT)) {
  1642. token = wcstok(NULL, SEPARATORS);
  1643. if (token == NULL) {
  1644. //
  1645. // Bad arguments
  1646. //
  1647. WsbThrow(E_NOINTERFACE);
  1648. } else if (!_wcsicmp(token, HSM_SCHED_SYSTEMSTARTUP)) {
  1649. //
  1650. // Once at system startup
  1651. //
  1652. Schedule->Frequency = SystemStartup;
  1653. WsbThrow(S_OK);
  1654. } else if (!_wcsicmp(token, HSM_SCHED_LOGIN)) {
  1655. //
  1656. // Once at login time
  1657. //
  1658. Schedule->Frequency = Login;
  1659. WsbThrow(S_OK);
  1660. } else if (!_wcsicmp(token, HSM_SCHED_IDLE)) {
  1661. //
  1662. // Whenever system's idle
  1663. //
  1664. Schedule->Frequency = WhenIdle;
  1665. WsbThrow(S_OK);
  1666. } else {
  1667. GetSystemTime(&scheduledTime);
  1668. //
  1669. // Once at specified time.
  1670. // Parse the time string and obtain it
  1671. // TBD - Add provision to specify date as well as time
  1672. //
  1673. hr = ClipParseTime(token,
  1674. &scheduledTime);
  1675. WsbAssertHr(hr);
  1676. Schedule->Frequency = Once;
  1677. Schedule->Parameters.Once.Time = scheduledTime;
  1678. WsbThrow(S_OK);
  1679. }
  1680. } else if (!_wcsicmp(token, HSM_SCHED_EVERY)) {
  1681. LPWSTR stopString = NULL;
  1682. //
  1683. // Get the occurrence
  1684. //
  1685. token = wcstok(NULL, SEPARATORS);
  1686. WsbAssert(token != NULL, E_NOINTERFACE);
  1687. CLIP_GET_DWORD_ARG(occurrence, token, stopString);
  1688. //
  1689. // Get the qualifier: Daily/Weekly/Monthly
  1690. //
  1691. token = wcstok(NULL, SEPARATORS);
  1692. WsbAssert(token != NULL, E_NOINTERFACE);
  1693. if (!_wcsicmp(token, HSM_SCHED_DAILY)) {
  1694. frequency = Daily;
  1695. } else if (!_wcsicmp(token, HSM_SCHED_WEEKLY)) {
  1696. frequency = Weekly;
  1697. } else if (!_wcsicmp(token, HSM_SCHED_MONTHLY)) {
  1698. frequency = Monthly;
  1699. } else {
  1700. //
  1701. // Badly constructed argument
  1702. //
  1703. WsbThrow(E_NOINTERFACE);
  1704. }
  1705. //
  1706. // Get current time
  1707. //
  1708. GetSystemTime(&scheduledTime);
  1709. //
  1710. // For weekly/monthly we also need to get the day of the week/month
  1711. // Monday = 1, Sunday = 7 for weekly
  1712. //
  1713. if ((frequency == Weekly) || (frequency == Monthly)) {
  1714. token = wcstok(NULL, SEPARATORS);
  1715. WsbAssert(token != NULL, E_NOINTERFACE);
  1716. CLIP_GET_DWORD_ARG(day, token, stopString);
  1717. //
  1718. // Validate & update the parameters
  1719. //
  1720. if (frequency == Weekly) {
  1721. if (day > 6) {
  1722. WsbThrow(E_NOINTERFACE);
  1723. }
  1724. scheduledTime.wDayOfWeek = (WORD) day;
  1725. }
  1726. if (frequency == Monthly) {
  1727. if ((day > 31) || (day < 1)) {
  1728. WsbThrow(E_NOINTERFACE);
  1729. }
  1730. scheduledTime.wDay = (WORD) day;
  1731. }
  1732. }
  1733. //
  1734. // Fetch the time
  1735. //
  1736. token = wcstok(NULL, SEPARATORS);
  1737. WsbAssert(token != NULL, E_NOINTERFACE);
  1738. hr = ClipParseTime(token,
  1739. &scheduledTime);
  1740. WsbAssertHr(hr);
  1741. Schedule->Frequency = frequency;
  1742. Schedule->Parameters.Daily.Occurrence = occurrence;
  1743. Schedule->Parameters.Daily.Time = scheduledTime;
  1744. } else {
  1745. WsbThrow(E_NOINTERFACE);
  1746. }
  1747. }WsbCatch(hr);
  1748. WsbTraceOut(OLESTR("ClipParseSchedule"), OLESTR(""));
  1749. return hr;
  1750. }
  1751. BOOL
  1752. ClipInitializeTrace(
  1753. VOID
  1754. )
  1755. /*++
  1756. Routine Description
  1757. Initializes the trace/printing mechanism for CLI
  1758. Arguments
  1759. NONE
  1760. Return Value
  1761. TRUE if successful, FALSE otherwise
  1762. --*/
  1763. {
  1764. BOOL ret = TRUE;
  1765. if (S_OK == CoCreateInstance(CLSID_CWsbTrace, 0, CLSCTX_SERVER, IID_IWsbTrace, (void **)&g_pTrace)) {
  1766. CWsbStringPtr tracePath;
  1767. CWsbStringPtr regPath;
  1768. CWsbStringPtr outString;
  1769. // Registry path for CLI settings
  1770. // If those expand beyond Trace settings, this path should go to a header file
  1771. regPath = L"SOFTWARE\\Microsoft\\RemoteStorage\\CLI";
  1772. // Check if tracing path already exists, if not - set it (this should happen only once)
  1773. WsbAffirmHr(outString.Alloc(WSB_TRACE_BUFF_SIZE));
  1774. if ( WsbGetRegistryValueString(NULL, regPath, L"WsbTraceFileName", outString, WSB_TRACE_BUFF_SIZE, 0) != S_OK) {
  1775. // No trace settings yet
  1776. WCHAR *systemPath;
  1777. systemPath = _wgetenv(L"SystemRoot");
  1778. WsbAffirmHr(tracePath.Printf( L"%ls\\System32\\RemoteStorage\\Trace\\RsCli.Trc", systemPath));
  1779. // Set default settings in the Registry
  1780. WsbEnsureRegistryKeyExists(0, regPath);
  1781. WsbSetRegistryValueString(0, regPath, L"WsbTraceFileName", tracePath);
  1782. // Make sure the trace directory exists.
  1783. WsbAffirmHr(tracePath.Printf( L"%ls\\System32\\RemoteStorage", systemPath));
  1784. CreateDirectory(tracePath, 0);
  1785. WsbAffirmHr(tracePath.Printf( L"%ls\\System32\\RemoteStorage\\Trace", systemPath));
  1786. CreateDirectory(tracePath, 0);
  1787. }
  1788. g_pTrace->SetRegistryEntry(regPath);
  1789. g_pTrace->LoadFromRegistry();
  1790. }
  1791. return ret;
  1792. }
  1793. VOID
  1794. ClipUninitializeTrace(
  1795. VOID
  1796. )
  1797. /*++
  1798. Routine Description
  1799. Uninitializes the trace/print mechansim
  1800. Paired with ClipInitializeTrace
  1801. Arguments
  1802. NONE
  1803. Return Value
  1804. NONE
  1805. --*/
  1806. {
  1807. g_pTrace = 0;
  1808. }
  1809. VOID
  1810. ClipHandleErrors(
  1811. IN HRESULT RetCode,
  1812. IN RSS_INTERFACE Interface,
  1813. IN RSS_INTERFACE SubInterface
  1814. )
  1815. /*++
  1816. Routine Description
  1817. Translates the main return value & displays any appropriate
  1818. error messages and returns
  1819. Arguments
  1820. RetCode - Error to handle
  1821. Interface - RSS interface specified in the command
  1822. SubInterface - RSS sub-interface specified in the command
  1823. Return Value
  1824. None
  1825. --*/
  1826. {
  1827. WsbTraceIn(OLESTR("ClipHandleErrors"), OLESTR(""));
  1828. switch (RetCode) {
  1829. case E_INVALIDARG:
  1830. case S_OK:{
  1831. //
  1832. // Nothing to print
  1833. //
  1834. break;}
  1835. case E_NOINTERFACE:{
  1836. WsbTraceAndPrint(CLI_MESSAGE_VALUE_DISPLAY, WsbHrAsString(E_INVALIDARG));
  1837. ClipHelp(Interface,
  1838. SubInterface);
  1839. break;}
  1840. default:{
  1841. WsbTraceAndPrint(CLI_MESSAGE_VALUE_DISPLAY, WsbHrAsString(RetCode));
  1842. break;}
  1843. }
  1844. WsbTraceOut(OLESTR("ClipHandleErrors"), OLESTR(""));
  1845. }
  1846. extern "C"
  1847. int __cdecl
  1848. wmain()
  1849. {
  1850. LPWSTR commandLine, token;
  1851. HRESULT hr = E_NOINTERFACE;
  1852. RSS_INTERFACE intrface = HELP_IF, subInterface = UNKNOWN_IF;
  1853. try {
  1854. WsbAffirmHr(CoInitialize(NULL));
  1855. //
  1856. // Set to OEM page locale
  1857. //
  1858. _wsetlocale(LC_ALL, L".OCP");
  1859. //
  1860. // Set to console UI langauge
  1861. //
  1862. SetThreadUILanguage(0);
  1863. ClipInitializeTrace();
  1864. commandLine = GetCommandLine();
  1865. //
  1866. // Get argv[0] out of the way
  1867. //
  1868. token = wcstok(commandLine, SEPARATORS);
  1869. //
  1870. // Get the interface string
  1871. //
  1872. token = wcstok(NULL, SEPARATORS);
  1873. if (token == NULL) {
  1874. ClipHelp(HELP_IF,
  1875. UNKNOWN_IF);
  1876. hr = S_OK;
  1877. goto exit;
  1878. }
  1879. intrface = ClipGetInterface(token);
  1880. if (intrface == UNKNOWN_IF) {
  1881. hr = E_NOINTERFACE;
  1882. intrface = HELP_IF;
  1883. goto exit;
  1884. }
  1885. if (intrface == HELP_IF) {
  1886. ClipHelp(HELP_IF,
  1887. UNKNOWN_IF);
  1888. hr = S_OK;
  1889. goto exit;
  1890. }
  1891. //
  1892. // Get sub interface string
  1893. //
  1894. token = wcstok(NULL, SEPARATORS);
  1895. if (token == NULL) {
  1896. hr = E_NOINTERFACE;
  1897. goto exit;
  1898. }
  1899. subInterface = ClipGetInterface(token);
  1900. if (subInterface == UNKNOWN_IF) {
  1901. hr = E_NOINTERFACE;
  1902. goto exit;
  1903. }
  1904. if (subInterface == HELP_IF) {
  1905. ClipHelp(intrface,
  1906. UNKNOWN_IF);
  1907. hr = S_OK;
  1908. goto exit;
  1909. }
  1910. //
  1911. // Now compile the switches & arguments into separate arrays
  1912. // First, get the rest of line ..
  1913. //
  1914. token = wcstok(NULL, L"");
  1915. hr = ClipCompileSwitchesAndArgs(token,
  1916. intrface,
  1917. subInterface);
  1918. if (hr != S_OK) {
  1919. goto exit;
  1920. }
  1921. switch (intrface) {
  1922. case ADMIN_IF:{
  1923. if (subInterface == SHOW_IF) {
  1924. hr = ClipAdminShow();
  1925. } else if (subInterface == SET_IF) {
  1926. hr = ClipAdminSet();
  1927. } else {
  1928. hr = E_NOINTERFACE;
  1929. }
  1930. break;
  1931. }
  1932. case VOLUME_IF:{
  1933. if (subInterface == MANAGE_IF) {
  1934. hr = ClipVolumeSetManage(FALSE);
  1935. } else if (subInterface == UNMANAGE_IF) {
  1936. hr = ClipVolumeUnmanage();
  1937. } else if (subInterface == SET_IF) {
  1938. hr = ClipVolumeSetManage(TRUE);
  1939. } else if (subInterface == SHOW_IF) {
  1940. hr = ClipVolumeShow();
  1941. } else if (subInterface == DELETE_IF) {
  1942. hr = ClipVolumeDelete();
  1943. } else if (subInterface == JOB_IF) {
  1944. hr = ClipVolumeJob();
  1945. } else {
  1946. hr = E_NOINTERFACE;
  1947. }
  1948. break;
  1949. }
  1950. case FILE_IF:{
  1951. if (subInterface == RECALL_IF) {
  1952. hr = ClipFileRecall();
  1953. } else {
  1954. hr = E_NOINTERFACE;
  1955. }
  1956. break;
  1957. }
  1958. case MEDIA_IF:{
  1959. if (subInterface == SYNCHRONIZE_IF) {
  1960. hr = ClipMediaSynchronize();
  1961. } else if (subInterface == RECREATEMASTER_IF) {
  1962. hr = ClipMediaRecreateMaster();
  1963. } else if (subInterface == DELETE_IF) {
  1964. hr = ClipMediaDelete();
  1965. } else if (subInterface == SHOW_IF) {
  1966. hr = ClipMediaShow();
  1967. } else {
  1968. hr = E_NOINTERFACE;
  1969. }
  1970. break;
  1971. }
  1972. default:{
  1973. hr = E_NOINTERFACE;
  1974. break;
  1975. }
  1976. }
  1977. exit:
  1978. ClipHandleErrors(hr,
  1979. intrface,
  1980. subInterface);
  1981. ClipCleanup();
  1982. ClipUninitializeTrace();
  1983. CoUninitialize();
  1984. }WsbCatchAndDo(hr,
  1985. WsbTraceAndPrint(CLI_MESSAGE_GENERIC_ERROR, WsbHrAsString(hr));
  1986. );
  1987. CLIP_TRANSLATE_HR_AND_RETURN(hr);
  1988. }