2409 lines
64 KiB
C++
2409 lines
64 KiB
C++
|
/*++
|
|||
|
|
|||
|
Copyright (c) 2000 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
cliparse.cpp
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Implements CLI parsing engine
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Ravisankar Pudipeddi [ravisp] 3-March-2000
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
//
|
|||
|
// Throughout this parse module, we return E_NOINTERFACE
|
|||
|
// to indicate invalid command line syntax/parameters.
|
|||
|
// This is to explicitly distinguish from E_INVALIDARG that may
|
|||
|
// be returned by the CLI dll: we wish to distinguish a syntax error
|
|||
|
// detected by the parser from a syntax error detected by the CLI dll
|
|||
|
// because in the latter case we do not print the usage for the interface.
|
|||
|
// Whereas for errors detected by the parser, we *do* print the usage.
|
|||
|
// This rule needs to be strictly adhered to
|
|||
|
//
|
|||
|
|
|||
|
#include "stdafx.h"
|
|||
|
#include "stdlib.h"
|
|||
|
#include "cliparse.h"
|
|||
|
#include "string.h"
|
|||
|
#include "locale.h"
|
|||
|
|
|||
|
#pragma warning( disable : 4100 )
|
|||
|
|
|||
|
CComModule _Module;
|
|||
|
CComPtr<IWsbTrace> g_pTrace;
|
|||
|
|
|||
|
#define MAX_ARGS 40
|
|||
|
#define MAX_SWITCHES 20
|
|||
|
//
|
|||
|
// List of all CLI keywords
|
|||
|
// TBD: Sort them!
|
|||
|
//
|
|||
|
RSS_KEYWORD RssInterfaceStrings[] = {
|
|||
|
{L"ADMIN", L"AD", ADMIN_IF},
|
|||
|
{L"VOLUME", L"VL", VOLUME_IF},
|
|||
|
{L"MEDIA", L"MD", MEDIA_IF},
|
|||
|
{L"FILE", L"FL", FILE_IF},
|
|||
|
{L"SHOW", L"SH", SHOW_IF},
|
|||
|
{L"SET", L"ST", SET_IF},
|
|||
|
{L"MANAGE", L"MG", MANAGE_IF},
|
|||
|
{L"UNMANAGE", L"UM", UNMANAGE_IF},
|
|||
|
{L"DELETE", L"DL", DELETE_IF},
|
|||
|
{L"JOB", L"JB", JOB_IF},
|
|||
|
{L"RECALL", L"RC", RECALL_IF},
|
|||
|
{L"SYNCHRONIZE", L"SN", SYNCHRONIZE_IF},
|
|||
|
{L"RECREATEMASTER", L"RM", RECREATEMASTER_IF},
|
|||
|
{L"HELP", L"/?", HELP_IF},
|
|||
|
//
|
|||
|
// Duplicate entry for HELP to recognize -? also as a help
|
|||
|
// interface
|
|||
|
//
|
|||
|
{L"HELP", L"-?", HELP_IF},
|
|||
|
{NULL, NULL, UNKNOWN_IF}
|
|||
|
};
|
|||
|
|
|||
|
//
|
|||
|
// Rss option strings - listed here without the preceding
|
|||
|
// '/' or '-' (or whatever that distinguishes a switch from
|
|||
|
// an argument)
|
|||
|
// TBD: Sort them!
|
|||
|
//
|
|||
|
|
|||
|
RSS_SWITCH_DEFINITION RssSwitchStrings[] = {
|
|||
|
{L"RECALLLIMIT", L"LM", RECALLLIMIT_SW, RSS_ARG_DWORD},
|
|||
|
{L"MEDIACOPIES", L"MC", MEDIACOPIES_SW, RSS_ARG_DWORD},
|
|||
|
{L"SCHEDULE", L"SC", SCHEDULE_SW, RSS_ARG_STRING},
|
|||
|
{L"CONCURRENCY", L"CN", CONCURRENCY_SW, RSS_ARG_DWORD},
|
|||
|
{L"ADMINEXEMPT", L"AE", ADMINEXEMPT_SW, RSS_ARG_DWORD},
|
|||
|
{L"GENERAL", L"GN", GENERAL_SW, RSS_NO_ARG},
|
|||
|
{L"MANAGEABLES", L"MS", MANAGEABLES_SW, RSS_NO_ARG},
|
|||
|
{L"MANAGED", L"MN", MANAGED_SW, RSS_NO_ARG},
|
|||
|
{L"MEDIA", L"MD", MEDIA_SW, RSS_NO_ARG},
|
|||
|
{L"DFS", L"DF", DFS_SW, RSS_ARG_DWORD},
|
|||
|
{L"SIZE", L"SZ", SIZE_SW, RSS_ARG_DWORD},
|
|||
|
{L"ACCESS", L"AC", ACCESS_SW, RSS_ARG_DWORD},
|
|||
|
{L"INCLUDE", L"IN", INCLUDE_SW, RSS_ARG_STRING},
|
|||
|
{L"EXCLUDE", L"EX", EXCLUDE_SW, RSS_ARG_STRING},
|
|||
|
{L"RECURSIVE", L"RC", RECURSIVE_SW, RSS_NO_ARG},
|
|||
|
{L"QUICK", L"QK", QUICK_SW, RSS_NO_ARG},
|
|||
|
{L"FULL", L"FL", FULL_SW, RSS_NO_ARG},
|
|||
|
{L"RULE", L"RL", RULE_SW, RSS_ARG_STRING},
|
|||
|
{L"STATISTICS", L"ST", STATISTICS_SW, RSS_NO_ARG},
|
|||
|
{L"TYPE", L"TY", TYPE_SW, RSS_ARG_STRING},
|
|||
|
{L"RUN", L"RN", RUN_SW, RSS_NO_ARG},
|
|||
|
{L"CANCEL", L"CX", CANCEL_SW, RSS_NO_ARG},
|
|||
|
{L"WAIT", L"WT", WAIT_SW, RSS_NO_ARG},
|
|||
|
{L"COPYSET", L"CS", COPYSET_SW, RSS_ARG_DWORD},
|
|||
|
{L"NAME", L"NM", NAME_SW, RSS_ARG_STRING},
|
|||
|
{L"STATUS", L"SS", STATUS_SW, RSS_NO_ARG},
|
|||
|
{L"CAPACITY", L"CP", CAPACITY_SW, RSS_NO_ARG},
|
|||
|
{L"FREESPACE", L"FS", FREESPACE_SW, RSS_NO_ARG},
|
|||
|
{L"VERSION", L"VR", VERSION_SW, RSS_NO_ARG},
|
|||
|
{L"COPIES", L"CP", COPIES_SW, RSS_NO_ARG},
|
|||
|
{L"HELP", L"?", HELP_SW, RSS_NO_ARG},
|
|||
|
{NULL, NULL, UNKNOWN_SW, RSS_NO_ARG}
|
|||
|
};
|
|||
|
|
|||
|
RSS_JOB_DEFINITION RssJobTypeStrings[] = {
|
|||
|
{L"CREATEFREESPACE", L"F", CreateFreeSpace},
|
|||
|
{L"COPYFILES", L"C", CopyFiles},
|
|||
|
{L"VALIDATE", L"V", Validate},
|
|||
|
{NULL, NULL, InvalidJobType}
|
|||
|
};
|
|||
|
|
|||
|
//
|
|||
|
// Global arrays of arguments and switches
|
|||
|
// These will be used as 'known' entities by all
|
|||
|
// the interface implementations instead of passing
|
|||
|
// them around as parameters
|
|||
|
//
|
|||
|
LPWSTR Args[MAX_ARGS];
|
|||
|
RSS_SWITCHES Switches[MAX_SWITCHES];
|
|||
|
DWORD NumberOfArguments = 0;
|
|||
|
DWORD NumberOfSwitches = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Useful macros
|
|||
|
//
|
|||
|
|
|||
|
#define CLIP_ARGS_REQUIRED() { \
|
|||
|
if (NumberOfArguments <= 0) { \
|
|||
|
WsbThrow(E_NOINTERFACE); \
|
|||
|
} \
|
|||
|
}
|
|||
|
|
|||
|
#define CLIP_ARGS_NOT_REQUIRED() { \
|
|||
|
if (NumberOfArguments > 0) { \
|
|||
|
WsbThrow(E_NOINTERFACE); \
|
|||
|
} \
|
|||
|
}
|
|||
|
|
|||
|
#define CLIP_SWITCHES_REQUIRED() { \
|
|||
|
if (NumberOfSwitches <= 0) { \
|
|||
|
WsbThrow(E_NOINTERFACE); \
|
|||
|
} \
|
|||
|
}
|
|||
|
|
|||
|
#define CLIP_SWITCHES_NOT_REQUIRED() { \
|
|||
|
if (NumberOfSwitches > 0) { \
|
|||
|
WsbThrow(E_NOINTERFACE); \
|
|||
|
} \
|
|||
|
}
|
|||
|
|
|||
|
#define CLIP_TRANSLATE_HR_AND_RETURN(__HR) { \
|
|||
|
if (__HR == S_OK) { \
|
|||
|
return CLIP_ERROR_SUCCESS; \
|
|||
|
} else if ((__HR == E_NOINTERFACE) || \
|
|||
|
(__HR == E_INVALIDARG)) { \
|
|||
|
return CLIP_ERROR_INVALID_PARAMETER; \
|
|||
|
} else if (__HR == E_OUTOFMEMORY) { \
|
|||
|
return CLIP_ERROR_INSUFFICIENT_MEMORY; \
|
|||
|
} else { \
|
|||
|
return CLIP_ERROR_UNKNOWN; \
|
|||
|
} \
|
|||
|
}
|
|||
|
|
|||
|
#define CLIP_GET_DWORD_ARG(__VAL, __STRING, __STOPSTRING) { \
|
|||
|
__VAL = wcstol(__STRING, &(__STOPSTRING), 10); \
|
|||
|
if (*(__STOPSTRING) != L'\0') { \
|
|||
|
WsbThrow(E_NOINTERFACE); \
|
|||
|
} \
|
|||
|
}
|
|||
|
|
|||
|
#define CLIP_VALIDATE_DUPLICATE_DWORD_ARG(__ARG) { \
|
|||
|
if ((__ARG) != INVALID_DWORD_ARG) { \
|
|||
|
WsbThrow(E_NOINTERFACE); \
|
|||
|
} \
|
|||
|
}
|
|||
|
|
|||
|
#define CLIP_VALIDATE_DUPLICATE_POINTER_ARG(__ARG) { \
|
|||
|
if ((__ARG) != INVALID_POINTER_ARG) { \
|
|||
|
WsbThrow(E_NOINTERFACE); \
|
|||
|
} \
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Local function prototypes
|
|||
|
//
|
|||
|
|
|||
|
RSS_INTERFACE
|
|||
|
ClipGetInterface(
|
|||
|
IN LPWSTR InterfaceString
|
|||
|
);
|
|||
|
|
|||
|
DWORD
|
|||
|
ClipGetSwitchTypeIndex(
|
|||
|
IN LPWSTR SwitchString
|
|||
|
);
|
|||
|
|
|||
|
HSM_JOB_TYPE
|
|||
|
ClipGetJobType(
|
|||
|
IN LPWSTR JobTypeString
|
|||
|
);
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipCompileSwitchesAndArgs(
|
|||
|
IN LPWSTR CommandLine,
|
|||
|
IN RSS_INTERFACE Interface,
|
|||
|
IN RSS_INTERFACE SubInterface
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
ClipCleanup(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipAdminShow(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipAdminSet(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipVolumeShow(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipVolumeUnmanage(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipVolumeSetManage(
|
|||
|
IN BOOL Set
|
|||
|
);
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipVolumeDelete(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipVolumeJob(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipMediaShow(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipMediaSynchronize(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipMediaRecreateMaster(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipMediaDelete(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipFileRecall(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
ClipHelp(
|
|||
|
IN RSS_INTERFACE Interface,
|
|||
|
IN RSS_INTERFACE SubInterface
|
|||
|
);
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipParseTime(
|
|||
|
IN LPWSTR TimeString,
|
|||
|
OUT PSYSTEMTIME ScheduledTime
|
|||
|
);
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipParseSchedule(
|
|||
|
IN LPWSTR ScheduleString,
|
|||
|
OUT PHSM_JOB_SCHEDULE Schedule
|
|||
|
);
|
|||
|
BOOL
|
|||
|
ClipInitializeTrace(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
ClipUninitializeTrace(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
ClipHandleErrors(
|
|||
|
IN HRESULT RetCode,
|
|||
|
IN RSS_INTERFACE Interface,
|
|||
|
IN RSS_INTERFACE SubInterface
|
|||
|
);
|
|||
|
//
|
|||
|
// Function bodies start here
|
|||
|
//
|
|||
|
|
|||
|
RSS_INTERFACE
|
|||
|
ClipGetInterface(
|
|||
|
IN LPWSTR InterfaceString
|
|||
|
)
|
|||
|
/*++
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Maps the interface string that is supplied to an enum
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
InterfaceString - Pointer to the interface string
|
|||
|
TBD: implement a binary search
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
UNKNOWN_IF - if the interface string is not recognized
|
|||
|
An RSS_INTERFACE value if it is.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
RSS_INTERFACE ret = UNKNOWN_IF;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipHandleErrors"), OLESTR(""));
|
|||
|
|
|||
|
for (i=0 ; TRUE ; i++) {
|
|||
|
if (RssInterfaceStrings[i].Long == NULL) {
|
|||
|
//
|
|||
|
// Reached end of table.
|
|||
|
//
|
|||
|
break;
|
|||
|
|
|||
|
} else if ((_wcsicmp(RssInterfaceStrings[i].Short,
|
|||
|
InterfaceString) == 0) ||
|
|||
|
(_wcsicmp(RssInterfaceStrings[i].Long,
|
|||
|
InterfaceString) == 0)) {
|
|||
|
ret = RssInterfaceStrings[i].Interface;
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipGetInterface"), OLESTR("Interface = <%ls>"), WsbLongAsString((LONG) ret));
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
ClipGetSwitchTypeIndex(
|
|||
|
IN LPWSTR SwitchString
|
|||
|
)
|
|||
|
/*++
|
|||
|
Routine Description
|
|||
|
|
|||
|
Maps the Switch to an entry in the global list of switches
|
|||
|
and returns the index
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
SwitchString - Pointer to switch string
|
|||
|
TBD: implement a binary search
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
-1 - If the switch is not recognized
|
|||
|
A positive value (index to the entry) if it is
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipGetSwitchTypeIndex"), OLESTR(""));
|
|||
|
|
|||
|
for (i = 0; TRUE; i++) {
|
|||
|
if (RssSwitchStrings[i].Long == NULL) {
|
|||
|
//
|
|||
|
// Reached end of table.
|
|||
|
//
|
|||
|
i = -1;
|
|||
|
break;
|
|||
|
} else if ((_wcsicmp(RssSwitchStrings[i].Short,
|
|||
|
SwitchString) == 0) ||
|
|||
|
(_wcsicmp(RssSwitchStrings[i].Long,
|
|||
|
SwitchString) == 0)) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipGetSwitchTypeIndex"), OLESTR("index = <%ls>"), WsbLongAsString((LONG) i));
|
|||
|
return i;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HSM_JOB_TYPE
|
|||
|
ClipGetJobType(
|
|||
|
IN LPWSTR JobTypeString
|
|||
|
)
|
|||
|
/*++
|
|||
|
Routine Description
|
|||
|
|
|||
|
Maps the job string to an enum
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
JobTypeString - Pointer to JobType string
|
|||
|
TBD: implement a binary search
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
InvalidJobType - If the job type is not recognized
|
|||
|
HSM_JOB_TYPE value if it is
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
HSM_JOB_TYPE jobType = InvalidJobType;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipGetJobType"), OLESTR(""));
|
|||
|
|
|||
|
for (i = 0; TRUE; i++) {
|
|||
|
if (RssJobTypeStrings[i].Long == NULL) {
|
|||
|
//
|
|||
|
// Reached end of table.
|
|||
|
//
|
|||
|
break;
|
|||
|
}
|
|||
|
if ((_wcsicmp(RssJobTypeStrings[i].Short,
|
|||
|
JobTypeString) == 0) ||
|
|||
|
(_wcsicmp(RssJobTypeStrings[i].Long,
|
|||
|
JobTypeString) == 0)) {
|
|||
|
jobType = RssJobTypeStrings[i].JobType;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipGetJobType"), OLESTR("JobType = <%ls>"), WsbLongAsString((LONG) jobType));
|
|||
|
|
|||
|
return jobType;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipCompileSwitchesAndArgs(
|
|||
|
IN LPWSTR CommandLine,
|
|||
|
IN RSS_INTERFACE Interface,
|
|||
|
IN RSS_INTERFACE SubInterface
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description
|
|||
|
|
|||
|
Parses the passed in string and compiles all switches
|
|||
|
(a switch is identified by an appropriate delimiter preceding
|
|||
|
it, such as a '/') into a global switches array (along with
|
|||
|
the arguments to the switch) and the rest of the parameters
|
|||
|
into an Args array
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
CommandLine - String to be parsed
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
S_OK if success
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
WCHAR token[MAX_PATH];
|
|||
|
LPWSTR p = CommandLine, pToken = token, switchArg, switchString;
|
|||
|
RSS_SWITCH_TYPE switchType;
|
|||
|
DWORD index;
|
|||
|
BOOL isSwitch, skipSpace;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipCompileSwitchesAndArgs"), OLESTR(""));
|
|||
|
|
|||
|
try {
|
|||
|
if (p == NULL) {
|
|||
|
WsbThrow(S_OK);
|
|||
|
}
|
|||
|
|
|||
|
while (*p != L'\0') {
|
|||
|
|
|||
|
if (wcschr(SEPARATORS, *p) != NULL) {
|
|||
|
//
|
|||
|
// Skip white space
|
|||
|
//
|
|||
|
p++;
|
|||
|
continue;
|
|||
|
}
|
|||
|
if (wcschr(SWITCH_DELIMITERS, *p) != NULL) {
|
|||
|
isSwitch = TRUE;
|
|||
|
p++;
|
|||
|
if (*p == L'\0') {
|
|||
|
//
|
|||
|
// Badly formed - a SWITCH_DELIMITER with no switch
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
} else {
|
|||
|
isSwitch = FALSE;
|
|||
|
}
|
|||
|
//
|
|||
|
// Get the rest of the word
|
|||
|
//
|
|||
|
skipSpace = FALSE;
|
|||
|
while (*p != L'\0' && *p != L'\n') {
|
|||
|
//
|
|||
|
// We wish to consider stuff enclosed entirely in
|
|||
|
// quotes as a single token. As a result
|
|||
|
// we won't consider white space to be a delimiter
|
|||
|
// for tokens when they are in quotes.
|
|||
|
//
|
|||
|
if (*p == QUOTE) {
|
|||
|
if (skipSpace) {
|
|||
|
//
|
|||
|
// A quote was encountered previously.
|
|||
|
// This signifies - hence - the end of the token
|
|||
|
//
|
|||
|
p++;
|
|||
|
break;
|
|||
|
} else {
|
|||
|
//
|
|||
|
// Start of quoted string..don't treat whitespace
|
|||
|
// as a delimiter anymore, only a quote will end the token
|
|||
|
//
|
|||
|
skipSpace = TRUE;
|
|||
|
p++;
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!skipSpace && (wcschr(SEPARATORS, *p) != NULL)) {
|
|||
|
//
|
|||
|
// This is not quoted and white space was encountered..
|
|||
|
//
|
|||
|
break;
|
|||
|
}
|
|||
|
*pToken++ = *p++;
|
|||
|
}
|
|||
|
|
|||
|
*pToken = L'\0';
|
|||
|
|
|||
|
if (isSwitch) {
|
|||
|
//
|
|||
|
// For a switch, we will have to further split it into
|
|||
|
// the switch part and the argument part
|
|||
|
//
|
|||
|
switchString = wcstok(token, SWITCH_ARG_DELIMITERS);
|
|||
|
|
|||
|
index = ClipGetSwitchTypeIndex(switchString);
|
|||
|
if (index == -1) {
|
|||
|
//
|
|||
|
// Invalid switch. Get out.
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
switchType = RssSwitchStrings[index].SwitchType;
|
|||
|
|
|||
|
switchArg = wcstok(NULL, L"");
|
|||
|
//
|
|||
|
// Validation - badly formed commandline if either:
|
|||
|
// 1. An argument was supplied and the switch definition indicated
|
|||
|
// no argument was required
|
|||
|
// OR
|
|||
|
// 2. This is a non-SHOW interface (by default show interface
|
|||
|
// don't require arguments for options), and an argument was not
|
|||
|
// supplied even though the switch definition indicated one is
|
|||
|
// required.
|
|||
|
//
|
|||
|
// 3. This is a SHOW interface and an argument was supplied
|
|||
|
//
|
|||
|
if ( ((switchArg != NULL) &&
|
|||
|
(RssSwitchStrings[index].ArgRequired == RSS_NO_ARG)) ||
|
|||
|
|
|||
|
((SubInterface != SHOW_IF) && (switchArg == NULL) &&
|
|||
|
(RssSwitchStrings[index].ArgRequired != RSS_NO_ARG)) ||
|
|||
|
((SubInterface == SHOW_IF) && (switchArg != NULL))) {
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
|
|||
|
Switches[NumberOfSwitches].SwitchType = switchType;
|
|||
|
|
|||
|
if (switchArg != NULL) {
|
|||
|
Switches[NumberOfSwitches].Arg = new WCHAR [wcslen(switchArg)+1];
|
|||
|
|
|||
|
if (Switches[NumberOfSwitches].Arg == NULL) {
|
|||
|
WsbThrow(E_OUTOFMEMORY);
|
|||
|
}
|
|||
|
|
|||
|
wcscpy(Switches[NumberOfSwitches].Arg, switchArg);
|
|||
|
|
|||
|
} else {
|
|||
|
//
|
|||
|
// No arg for this switch
|
|||
|
//
|
|||
|
Switches[NumberOfSwitches].Arg = NULL;
|
|||
|
}
|
|||
|
|
|||
|
NumberOfSwitches++;
|
|||
|
} else {
|
|||
|
//
|
|||
|
// This is an argument..
|
|||
|
//
|
|||
|
Args[NumberOfArguments] = new WCHAR [wcslen(token)+1];
|
|||
|
|
|||
|
if (Args[NumberOfArguments] == NULL) {
|
|||
|
WsbThrow(E_OUTOFMEMORY);
|
|||
|
}
|
|||
|
|
|||
|
wcscpy(Args[NumberOfArguments],
|
|||
|
token);
|
|||
|
NumberOfArguments++;
|
|||
|
}
|
|||
|
pToken = token;
|
|||
|
}
|
|||
|
}WsbCatch(hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipCompileSwitchesAndArgs"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
ClipCleanup(VOID)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description
|
|||
|
|
|||
|
Performs global cleanup for CLI parse module.
|
|||
|
Mainly - frees up all allocated arguments and switches
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
None
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipCleanup"), OLESTR(""));
|
|||
|
|
|||
|
for (i = 0; i < NumberOfArguments; i++) {
|
|||
|
delete [] Args[i];
|
|||
|
}
|
|||
|
for (i = 0; i < NumberOfSwitches; i++) {
|
|||
|
if (Switches[i].Arg != NULL) {
|
|||
|
delete [] Switches[i].Arg;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipCleanup"), OLESTR(""));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipAdminShow(VOID)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description
|
|||
|
|
|||
|
Implements RSS ADMIN SHOW interface.
|
|||
|
Arguments are in global arrays:
|
|||
|
Args - containing list of arguments
|
|||
|
Switches - containing list of switches
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
S_OK if everything's ok
|
|||
|
E_NOINTERFACE if args/switches are bad
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
HRESULT hr;
|
|||
|
BOOL recallLimit = FALSE;
|
|||
|
BOOL adminExempt = FALSE;
|
|||
|
BOOL mediaCopies = FALSE;
|
|||
|
BOOL concurrency = FALSE;
|
|||
|
BOOL schedule = FALSE;
|
|||
|
BOOL general = FALSE;
|
|||
|
BOOL manageables = FALSE;
|
|||
|
BOOL managed = FALSE;
|
|||
|
BOOL media = FALSE;
|
|||
|
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipAdminShow"), OLESTR(""));
|
|||
|
try {
|
|||
|
//
|
|||
|
// No arguments needed for this interface
|
|||
|
//
|
|||
|
CLIP_ARGS_NOT_REQUIRED();
|
|||
|
|
|||
|
if (NumberOfSwitches) {
|
|||
|
for (i = 0; i < NumberOfSwitches; i++) {
|
|||
|
switch (Switches[i].SwitchType) {
|
|||
|
case RECALLLIMIT_SW: {
|
|||
|
recallLimit = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case ADMINEXEMPT_SW: {
|
|||
|
adminExempt = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case MEDIACOPIES_SW: {
|
|||
|
mediaCopies = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case CONCURRENCY_SW: {
|
|||
|
concurrency = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case SCHEDULE_SW: {
|
|||
|
schedule = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case GENERAL_SW: {
|
|||
|
general = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case MANAGEABLES_SW: {
|
|||
|
manageables = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case MANAGED_SW: {
|
|||
|
managed = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case MEDIA_SW: {
|
|||
|
media = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
default: {
|
|||
|
// Unknown switch - get out
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
hr = AdminShow(recallLimit,
|
|||
|
adminExempt,
|
|||
|
mediaCopies,
|
|||
|
concurrency,
|
|||
|
schedule,
|
|||
|
general,
|
|||
|
manageables,
|
|||
|
managed,
|
|||
|
media);
|
|||
|
|
|||
|
} else {
|
|||
|
hr = AdminShow(TRUE,
|
|||
|
TRUE,
|
|||
|
TRUE,
|
|||
|
TRUE,
|
|||
|
TRUE,
|
|||
|
TRUE,
|
|||
|
TRUE,
|
|||
|
TRUE,
|
|||
|
TRUE);
|
|||
|
}
|
|||
|
}WsbCatch(hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipAdminShow"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipAdminSet(VOID)
|
|||
|
/*++
|
|||
|
Routine Description
|
|||
|
|
|||
|
Implements RSS ADMIN SET interface.
|
|||
|
Arguments are in global arrays:
|
|||
|
Args - containing list of arguments
|
|||
|
Switches - containing list of switches
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
S_OK if everything's ok
|
|||
|
E_NOINTERFACE if arguments are invalid
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
HRESULT hr;
|
|||
|
LPWSTR stopString = NULL;
|
|||
|
DWORD recallLimit = INVALID_DWORD_ARG;
|
|||
|
DWORD adminExempt = INVALID_DWORD_ARG;
|
|||
|
DWORD mediaCopies = INVALID_DWORD_ARG;
|
|||
|
DWORD concurrency = INVALID_DWORD_ARG;
|
|||
|
PHSM_JOB_SCHEDULE schedule = INVALID_POINTER_ARG;
|
|||
|
HSM_JOB_SCHEDULE schedAllocated;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipAdminSet"), OLESTR(""));
|
|||
|
try {
|
|||
|
//
|
|||
|
// No arguments needed for this interface
|
|||
|
//
|
|||
|
CLIP_ARGS_NOT_REQUIRED();
|
|||
|
|
|||
|
if (NumberOfSwitches) {
|
|||
|
for (i = 0; i < NumberOfSwitches; i++) {
|
|||
|
switch (Switches[i].SwitchType) {
|
|||
|
case RECALLLIMIT_SW: {
|
|||
|
CLIP_VALIDATE_DUPLICATE_DWORD_ARG(recallLimit);
|
|||
|
CLIP_GET_DWORD_ARG(recallLimit,
|
|||
|
Switches[i].Arg,
|
|||
|
stopString);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case ADMINEXEMPT_SW: {
|
|||
|
CLIP_VALIDATE_DUPLICATE_DWORD_ARG(adminExempt);
|
|||
|
CLIP_GET_DWORD_ARG(adminExempt,
|
|||
|
Switches[i].Arg,
|
|||
|
stopString);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case MEDIACOPIES_SW: {
|
|||
|
CLIP_VALIDATE_DUPLICATE_DWORD_ARG(mediaCopies);
|
|||
|
CLIP_GET_DWORD_ARG(mediaCopies,
|
|||
|
Switches[i].Arg,
|
|||
|
stopString);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case CONCURRENCY_SW: {
|
|||
|
CLIP_VALIDATE_DUPLICATE_DWORD_ARG(concurrency);
|
|||
|
CLIP_GET_DWORD_ARG(concurrency,
|
|||
|
Switches[i].Arg,
|
|||
|
stopString);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case SCHEDULE_SW: {
|
|||
|
CLIP_VALIDATE_DUPLICATE_POINTER_ARG(schedule);
|
|||
|
hr = ClipParseSchedule(Switches[i].Arg,
|
|||
|
&schedAllocated);
|
|||
|
if (!SUCCEEDED(hr)) {
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
} else {
|
|||
|
//
|
|||
|
// schedAllocated has the schedule
|
|||
|
//
|
|||
|
schedule = &schedAllocated;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
default: {
|
|||
|
// Unknown switch - get out
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
hr = AdminSet(recallLimit,
|
|||
|
adminExempt,
|
|||
|
mediaCopies,
|
|||
|
concurrency,
|
|||
|
schedule);
|
|||
|
}WsbCatch(hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipAdminSet"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipVolumeShow(VOID)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description
|
|||
|
|
|||
|
Implements RSS VOLUME SHOW interface.
|
|||
|
Arguments are in global arrays:
|
|||
|
Args - containing list of arguments
|
|||
|
Switches - containing list of switches
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
S_OK if everything's ok
|
|||
|
E_NOINTERFACE if arguments are invalid
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
HRESULT hr;
|
|||
|
LPWSTR stopString = NULL;
|
|||
|
BOOL dfs = FALSE;
|
|||
|
BOOL size = FALSE;
|
|||
|
BOOL access = FALSE;
|
|||
|
BOOL rules = FALSE;
|
|||
|
BOOL statistics = FALSE;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipVolumeShow"), OLESTR(""));
|
|||
|
try {
|
|||
|
//
|
|||
|
// Atleast one arg. required for this interface
|
|||
|
//
|
|||
|
CLIP_ARGS_REQUIRED();
|
|||
|
|
|||
|
if (NumberOfSwitches == 0) {
|
|||
|
dfs = size = access = rules = statistics = TRUE;
|
|||
|
} else {
|
|||
|
for (i = 0; i < NumberOfSwitches; i++) {
|
|||
|
switch (Switches[i].SwitchType) {
|
|||
|
case DFS_SW: {
|
|||
|
dfs = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case SIZE_SW: {
|
|||
|
size = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case ACCESS_SW: {
|
|||
|
access = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case RULE_SW: {
|
|||
|
rules = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case STATISTICS_SW: {
|
|||
|
statistics = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
default: {
|
|||
|
//
|
|||
|
// Invalid option
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
hr = VolumeShow(Args,
|
|||
|
NumberOfArguments,
|
|||
|
dfs,
|
|||
|
size,
|
|||
|
access,
|
|||
|
rules,
|
|||
|
statistics);
|
|||
|
}WsbCatch(hr);
|
|||
|
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipVolumeShow"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipVolumeUnmanage(VOID)
|
|||
|
/*++
|
|||
|
Routine Description
|
|||
|
|
|||
|
Implements RSS VOLUME UNMANAGE interface.
|
|||
|
Arguments are in global arrays:
|
|||
|
Args - containing list of arguments
|
|||
|
Switches - containing list of switches
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
S_OK if everything's ok
|
|||
|
E_NOINTERFACE if arguments are invalid
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i = 0;
|
|||
|
HRESULT hr;
|
|||
|
|
|||
|
|
|||
|
#define QUICK_UNMANAGE 0
|
|||
|
#define FULL_UNMANAGE 1
|
|||
|
|
|||
|
DWORD fullOrQuick = INVALID_DWORD_ARG;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipVolumeUnmanage"), OLESTR(""));
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// Atleast one arg. required for this interface
|
|||
|
//
|
|||
|
CLIP_ARGS_REQUIRED();
|
|||
|
|
|||
|
if (NumberOfSwitches) {
|
|||
|
for (i = 0; i < NumberOfSwitches; i++) {
|
|||
|
switch (Switches[i].SwitchType) {
|
|||
|
case FULL_SW: {
|
|||
|
CLIP_VALIDATE_DUPLICATE_DWORD_ARG(fullOrQuick);
|
|||
|
fullOrQuick = FULL_UNMANAGE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case QUICK_SW: {
|
|||
|
CLIP_VALIDATE_DUPLICATE_DWORD_ARG(fullOrQuick);
|
|||
|
fullOrQuick = QUICK_UNMANAGE;
|
|||
|
break;
|
|||
|
}
|
|||
|
default: {
|
|||
|
//
|
|||
|
// Invalid option
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
//
|
|||
|
// The default for UNMANAGE is quick. So if fullOrQuick is either
|
|||
|
// QUICK_UNMANAGE or INVALID_DWORD_ARG, we call unmanage of the quick
|
|||
|
// variety
|
|||
|
//
|
|||
|
hr = VolumeUnmanage(Args,
|
|||
|
NumberOfArguments,
|
|||
|
(fullOrQuick == FULL_UNMANAGE)? TRUE : FALSE);
|
|||
|
}WsbCatch(hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipVolumeUnmanage"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
|
|||
|
return hr;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipVolumeSetManage(IN BOOL Set)
|
|||
|
/*++
|
|||
|
Routine Description
|
|||
|
|
|||
|
Implements RSS VOLUME MANAGE & RSS VOLUME SET interfaces.
|
|||
|
Arguments are in global arrays:
|
|||
|
Args - containing list of arguments
|
|||
|
Switches - containing list of switches
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
CLIP_ERROR_SUCCESS if everything's ok
|
|||
|
CLIP_ERROR_INVALID_PARAMETER if args/switches are bad
|
|||
|
CLIP_ERROR_UNKNOWN any other error
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i = 0;
|
|||
|
HRESULT hr;
|
|||
|
LPWSTR stopString = NULL;
|
|||
|
DWORD dfs = INVALID_DWORD_ARG;
|
|||
|
DWORD size = INVALID_DWORD_ARG;
|
|||
|
DWORD access = INVALID_DWORD_ARG;
|
|||
|
LPWSTR rulePath = INVALID_POINTER_ARG;
|
|||
|
LPWSTR ruleFileSpec = INVALID_POINTER_ARG;
|
|||
|
BOOL include = FALSE;
|
|||
|
BOOL recursive = FALSE;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipVolumeSetManage"), OLESTR(""));
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// Atleast one arg. required for this interface
|
|||
|
//
|
|||
|
CLIP_ARGS_REQUIRED();
|
|||
|
|
|||
|
if (NumberOfSwitches) {
|
|||
|
for (i = 0; i < NumberOfSwitches; i++) {
|
|||
|
switch (Switches[i].SwitchType) {
|
|||
|
case DFS_SW: {
|
|||
|
CLIP_VALIDATE_DUPLICATE_DWORD_ARG(dfs);
|
|||
|
CLIP_GET_DWORD_ARG(dfs, Switches[i].Arg, stopString);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case SIZE_SW: {
|
|||
|
CLIP_VALIDATE_DUPLICATE_DWORD_ARG(size);
|
|||
|
CLIP_GET_DWORD_ARG(size, Switches[i].Arg, stopString);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case ACCESS_SW: {
|
|||
|
CLIP_VALIDATE_DUPLICATE_DWORD_ARG(access);
|
|||
|
CLIP_GET_DWORD_ARG(access, Switches[i].Arg, stopString);
|
|||
|
break;
|
|||
|
}
|
|||
|
case INCLUDE_SW: {
|
|||
|
include = TRUE;
|
|||
|
//
|
|||
|
// Deliberately fall down to the EXCLUDE case
|
|||
|
// (break intentionally omitted)
|
|||
|
//
|
|||
|
}
|
|||
|
case EXCLUDE_SW: {
|
|||
|
|
|||
|
CLIP_VALIDATE_DUPLICATE_POINTER_ARG(rulePath);
|
|||
|
|
|||
|
rulePath = wcstok(Switches[i].Arg, RULE_DELIMITERS);
|
|||
|
ruleFileSpec = wcstok(NULL, L"");
|
|||
|
if (ruleFileSpec == NULL) {
|
|||
|
//
|
|||
|
// Omission of this indicates all files
|
|||
|
//
|
|||
|
ruleFileSpec = CLI_ALL_STR;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
case RECURSIVE_SW: {
|
|||
|
recursive = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
default: {
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
//
|
|||
|
// Validate the rule arguments
|
|||
|
//
|
|||
|
if ((rulePath == INVALID_POINTER_ARG) && recursive) {
|
|||
|
//
|
|||
|
// The recursive flag is valid only if a rule was specified
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
|
|||
|
if (Set) {
|
|||
|
hr = VolumeSet(Args,
|
|||
|
NumberOfArguments,
|
|||
|
dfs,
|
|||
|
size,
|
|||
|
access,
|
|||
|
rulePath,
|
|||
|
ruleFileSpec,
|
|||
|
include,
|
|||
|
recursive);
|
|||
|
} else {
|
|||
|
hr = VolumeManage(Args,
|
|||
|
NumberOfArguments,
|
|||
|
dfs,
|
|||
|
size,
|
|||
|
access,
|
|||
|
rulePath,
|
|||
|
ruleFileSpec,
|
|||
|
include,
|
|||
|
recursive);
|
|||
|
}
|
|||
|
}WsbCatch(hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipVolumeSetManage"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipVolumeDelete(VOID)
|
|||
|
/*++
|
|||
|
Routine Description
|
|||
|
|
|||
|
Implements RSS VOLUME DELETE interface.
|
|||
|
Arguments are in global arrays:
|
|||
|
Args - containing list of arguments
|
|||
|
Switches - containing list of switches
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
S_OK if everything's ok
|
|||
|
E_NOINTERFACE if arguments are invalid
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
HRESULT hr;
|
|||
|
BOOL rule = FALSE;
|
|||
|
LPWSTR rulePath = INVALID_POINTER_ARG;
|
|||
|
LPWSTR ruleFileSpec = INVALID_POINTER_ARG;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipVolumeDelete"), OLESTR(""));
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// Atleast one arg. required for this interface
|
|||
|
//
|
|||
|
CLIP_ARGS_REQUIRED();
|
|||
|
|
|||
|
for (i = 0; i < NumberOfSwitches; i++) {
|
|||
|
switch (Switches[i].SwitchType) {
|
|||
|
case RULE_SW: {
|
|||
|
CLIP_VALIDATE_DUPLICATE_POINTER_ARG(rulePath);
|
|||
|
rule = TRUE;
|
|||
|
rulePath = wcstok(Switches[i].Arg, RULE_DELIMITERS);
|
|||
|
ruleFileSpec = wcstok(NULL, L"");
|
|||
|
if (ruleFileSpec == NULL) {
|
|||
|
//
|
|||
|
// Omission of this indicates all files
|
|||
|
//
|
|||
|
ruleFileSpec = CLI_ALL_STR;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
default: {
|
|||
|
//
|
|||
|
// Invalid option
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
//
|
|||
|
// Only deleting rules is supported now
|
|||
|
//
|
|||
|
if (rule) {
|
|||
|
hr = VolumeDeleteRule(Args,
|
|||
|
NumberOfArguments,
|
|||
|
rulePath,
|
|||
|
ruleFileSpec);
|
|||
|
} else {
|
|||
|
hr = E_NOINTERFACE;
|
|||
|
}
|
|||
|
}WsbCatch(hr);
|
|||
|
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipVolumeDelete"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipVolumeJob(VOID)
|
|||
|
/*++
|
|||
|
Routine Description
|
|||
|
|
|||
|
Implements RSS VOLUME JOB interface.
|
|||
|
Arguments are in global arrays:
|
|||
|
Args - containing list of arguments
|
|||
|
Switches - containing list of switches
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
S_OK if everything's ok
|
|||
|
E_NOINTERFACE if arguments are invalid
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
HRESULT hr;
|
|||
|
HSM_JOB_TYPE jobType = InvalidJobType;
|
|||
|
|
|||
|
#define CANCEL_JOB 0
|
|||
|
#define RUN_JOB 1
|
|||
|
|
|||
|
DWORD runOrCancel = INVALID_DWORD_ARG;
|
|||
|
BOOL synchronous = FALSE;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipVolumeJob"), OLESTR(""));
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// Atleast one arg. required for this interface
|
|||
|
//
|
|||
|
CLIP_ARGS_REQUIRED();
|
|||
|
|
|||
|
for (i = 0; i < NumberOfSwitches; i++) {
|
|||
|
switch (Switches[i].SwitchType) {
|
|||
|
case RUN_SW: {
|
|||
|
CLIP_VALIDATE_DUPLICATE_DWORD_ARG(runOrCancel);
|
|||
|
runOrCancel = RUN_JOB;
|
|||
|
break;
|
|||
|
}
|
|||
|
case CANCEL_SW: {
|
|||
|
CLIP_VALIDATE_DUPLICATE_DWORD_ARG(runOrCancel);
|
|||
|
runOrCancel = CANCEL_JOB;
|
|||
|
break;
|
|||
|
}
|
|||
|
case WAIT_SW: {
|
|||
|
synchronous = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case TYPE_SW: {
|
|||
|
if (jobType != InvalidJobType) {
|
|||
|
//
|
|||
|
// Duplicate switch. Bail
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
jobType = ClipGetJobType(Switches[i].Arg);
|
|||
|
if (jobType == InvalidJobType) {
|
|||
|
//
|
|||
|
// Invalid job type supplied..
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
default: {
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// More validation:
|
|||
|
// job type should be valid i.e., specified
|
|||
|
//
|
|||
|
if (jobType == InvalidJobType) {
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Run is the default.. (i.e. TRUE). So if runOrCancel is either
|
|||
|
// INVALID_DWORD_ARG or RUN_JOB, we pass TRUE
|
|||
|
//
|
|||
|
hr = VolumeJob(Args,
|
|||
|
NumberOfArguments,
|
|||
|
jobType,
|
|||
|
(runOrCancel == CANCEL_JOB)? FALSE: TRUE,
|
|||
|
synchronous);
|
|||
|
|
|||
|
}WsbCatch(hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipVolumeJob"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipMediaShow(VOID)
|
|||
|
/*++
|
|||
|
Routine Description
|
|||
|
|
|||
|
Implements RSS MEDIA SHOW interface.
|
|||
|
Arguments are in global arrays:
|
|||
|
Args - containing list of arguments
|
|||
|
Switches - containing list of switches
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
S_OK if everything's ok
|
|||
|
E_NOINTERFACE if arguments are invalid
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
HRESULT hr;
|
|||
|
BOOL name = FALSE;
|
|||
|
BOOL status = FALSE;
|
|||
|
BOOL capacity = FALSE;
|
|||
|
BOOL freeSpace = FALSE;
|
|||
|
BOOL version = FALSE;
|
|||
|
BOOL copies = FALSE;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipMediaShow"), OLESTR(""));
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// Atleast one arg. required for this interface
|
|||
|
//
|
|||
|
CLIP_ARGS_REQUIRED();
|
|||
|
|
|||
|
if (NumberOfSwitches == 0) {
|
|||
|
name = status = capacity = freeSpace = version = copies = TRUE;
|
|||
|
} else {
|
|||
|
for (i = 0; i < NumberOfSwitches; i++) {
|
|||
|
switch (Switches[i].SwitchType) {
|
|||
|
case NAME_SW: {
|
|||
|
name = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case STATUS_SW: {
|
|||
|
status = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case CAPACITY_SW: {
|
|||
|
capacity = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case FREESPACE_SW: {
|
|||
|
freeSpace = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case VERSION_SW: {
|
|||
|
version = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
case COPIES_SW: {
|
|||
|
copies = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
default: {
|
|||
|
//
|
|||
|
// Invalid option
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
hr = MediaShow(Args,
|
|||
|
NumberOfArguments,
|
|||
|
name,
|
|||
|
status,
|
|||
|
capacity,
|
|||
|
freeSpace,
|
|||
|
version,
|
|||
|
copies);
|
|||
|
}WsbCatch(hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipMediaShow"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
return hr;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipMediaSynchronize(VOID)
|
|||
|
/*++
|
|||
|
Routine Description
|
|||
|
|
|||
|
Implements RSS MEDIA SYNCHRONIZE interface.
|
|||
|
Arguments are in global arrays:
|
|||
|
Args - containing list of arguments
|
|||
|
Switches - containing list of switches
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
S_OK if everything's ok
|
|||
|
E_NOINTERFACE if arguments are invalid
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
HRESULT hr;
|
|||
|
DWORD copySetNumber = INVALID_DWORD_ARG;
|
|||
|
BOOL synchronous = FALSE;
|
|||
|
LPWSTR stopString = NULL;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipMediaSynchronize"), OLESTR(""));
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// No arguments needed
|
|||
|
//
|
|||
|
CLIP_ARGS_NOT_REQUIRED();
|
|||
|
|
|||
|
for (i = 0; i < NumberOfSwitches; i++) {
|
|||
|
switch (Switches[i].SwitchType) {
|
|||
|
case COPYSET_SW: {
|
|||
|
CLIP_VALIDATE_DUPLICATE_DWORD_ARG(copySetNumber);
|
|||
|
CLIP_GET_DWORD_ARG(copySetNumber, Switches[i].Arg, stopString);
|
|||
|
break;
|
|||
|
}
|
|||
|
case WAIT_SW: {
|
|||
|
synchronous = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
default: {
|
|||
|
//
|
|||
|
// Invalid option
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
//
|
|||
|
// Need copy set number..
|
|||
|
//
|
|||
|
if (copySetNumber == INVALID_DWORD_ARG) {
|
|||
|
//
|
|||
|
// None was specified
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
hr = MediaSynchronize(copySetNumber, synchronous);
|
|||
|
}WsbCatch(hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipMediaRecreateMaster"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipMediaRecreateMaster(VOID)
|
|||
|
/*++
|
|||
|
Routine Description
|
|||
|
|
|||
|
Implements RSS MEDIA RECREATEMASTER interface.
|
|||
|
Arguments are in global arrays:
|
|||
|
Args - containing list of arguments
|
|||
|
Switches - containing list of switches
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
S_OK if everything's ok
|
|||
|
E_NOINTERFACE if arguments are invalid
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
DWORD i;
|
|||
|
HRESULT hr;
|
|||
|
DWORD copySetNumber = INVALID_DWORD_ARG;
|
|||
|
LPWSTR stopString = NULL;
|
|||
|
BOOL synchronous = FALSE;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipMediaRecreateMaster"), OLESTR(""));
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
//
|
|||
|
// Atleast one arg required
|
|||
|
//
|
|||
|
CLIP_ARGS_REQUIRED();
|
|||
|
|
|||
|
if (NumberOfArguments > 1) {
|
|||
|
//
|
|||
|
// Only one argument supported...
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < NumberOfSwitches; i++) {
|
|||
|
switch (Switches[i].SwitchType) {
|
|||
|
case COPYSET_SW: {
|
|||
|
CLIP_VALIDATE_DUPLICATE_DWORD_ARG(copySetNumber);
|
|||
|
CLIP_GET_DWORD_ARG(copySetNumber, Switches[i].Arg, stopString);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case WAIT_SW: {
|
|||
|
synchronous = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
default: {
|
|||
|
//
|
|||
|
// Invalid option
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
//
|
|||
|
// Need copy set number..
|
|||
|
//
|
|||
|
if (copySetNumber == INVALID_DWORD_ARG) {
|
|||
|
//
|
|||
|
// None was specified
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
|
|||
|
hr = MediaRecreateMaster(Args[0],
|
|||
|
copySetNumber,
|
|||
|
synchronous);
|
|||
|
}WsbCatch(hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipRecreateMaster"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipMediaDelete(VOID)
|
|||
|
/*++
|
|||
|
Routine Description
|
|||
|
|
|||
|
Implements RSS MEDIA DELETE interface.
|
|||
|
Arguments are in global arrays:
|
|||
|
Args - containing list of arguments
|
|||
|
Switches - containing list of switches
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
S_OK if everything's ok
|
|||
|
E_NOINTERFACE if arguments are invalid
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
HRESULT hr;
|
|||
|
DWORD copySetNumber = INVALID_DWORD_ARG;
|
|||
|
LPWSTR stopString = NULL;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipMediaDelete"), OLESTR(""));
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// Atleast one arg required
|
|||
|
//
|
|||
|
CLIP_ARGS_REQUIRED();
|
|||
|
|
|||
|
for (i = 0; i < NumberOfSwitches; i++) {
|
|||
|
switch (Switches[i].SwitchType) {
|
|||
|
case COPYSET_SW: {
|
|||
|
CLIP_VALIDATE_DUPLICATE_DWORD_ARG(copySetNumber);
|
|||
|
CLIP_GET_DWORD_ARG(copySetNumber, Switches[i].Arg, stopString);
|
|||
|
break;
|
|||
|
}
|
|||
|
default: {
|
|||
|
//
|
|||
|
// Invalid option
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
//
|
|||
|
// Need copy set number..
|
|||
|
//
|
|||
|
if (copySetNumber == INVALID_DWORD_ARG) {
|
|||
|
//
|
|||
|
// None was specified
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
hr = MediaDelete(Args,
|
|||
|
NumberOfArguments,
|
|||
|
copySetNumber);
|
|||
|
}WsbCatch(hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipMediaDelete"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipFileRecall(VOID)
|
|||
|
/*++
|
|||
|
Routine Description
|
|||
|
|
|||
|
Implements RSS FILE RECALL interface.
|
|||
|
Arguments are in global arrays:
|
|||
|
Args - containing list of arguments
|
|||
|
Switches - containing list of switches
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
S_OK if everything's ok
|
|||
|
E_NOINTERFACE if arguments are invalid
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipFileRecall"), OLESTR(""));
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// Atleast one arg. required for this interface
|
|||
|
//
|
|||
|
CLIP_ARGS_REQUIRED();
|
|||
|
//
|
|||
|
// No switches supported
|
|||
|
//
|
|||
|
CLIP_SWITCHES_NOT_REQUIRED();
|
|||
|
|
|||
|
hr = FileRecall(Args,
|
|||
|
NumberOfArguments);
|
|||
|
|
|||
|
}WsbCatch(hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipFileRecall"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
ClipHelp(
|
|||
|
IN RSS_INTERFACE Interface,
|
|||
|
IN RSS_INTERFACE SubInterface
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description
|
|||
|
|
|||
|
Prints appropriate help message depending on the interface
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
Interface - Specifies interface for which help has to be
|
|||
|
displayed
|
|||
|
SubInterface - Specifies sub-interface for which help has to be
|
|||
|
displayed
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
#define BREAK_IF_NOT_UNKNOWN_IF(__INTERFACE) { \
|
|||
|
if (((__INTERFACE) != UNKNOWN_IF) && \
|
|||
|
((__INTERFACE) != HELP_IF)) { \
|
|||
|
break; \
|
|||
|
} \
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipHelp"), OLESTR(""));
|
|||
|
|
|||
|
switch (Interface) {
|
|||
|
|
|||
|
case HELP_IF:
|
|||
|
case UNKNOWN_IF: {
|
|||
|
WsbTraceAndPrint(CLI_MESSAGE_MAIN_HELP, NULL);
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
|
|||
|
}
|
|||
|
|
|||
|
case ADMIN_IF: {
|
|||
|
switch (SubInterface) {
|
|||
|
case HELP_IF:
|
|||
|
case UNKNOWN_IF:
|
|||
|
case SHOW_IF: {
|
|||
|
WsbTraceAndPrint(CLI_MESSAGE_ADMIN_SHOW_HELP, NULL);
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
|
|||
|
}
|
|||
|
case SET_IF: {
|
|||
|
WsbTraceAndPrint(CLI_MESSAGE_ADMIN_SET_HELP, NULL);
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
|
|||
|
}
|
|||
|
}
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(Interface);
|
|||
|
}
|
|||
|
case VOLUME_IF: {
|
|||
|
switch (SubInterface) {
|
|||
|
case HELP_IF:
|
|||
|
case UNKNOWN_IF:
|
|||
|
case SHOW_IF: {
|
|||
|
WsbTraceAndPrint(CLI_MESSAGE_VOLUME_SHOW_HELP, NULL);
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
|
|||
|
}
|
|||
|
case SET_IF: {
|
|||
|
WsbTraceAndPrint(CLI_MESSAGE_VOLUME_SET_HELP, NULL);
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
|
|||
|
}
|
|||
|
case MANAGE_IF: {
|
|||
|
WsbTraceAndPrint(CLI_MESSAGE_VOLUME_MANAGE_HELP, NULL);
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
|
|||
|
}
|
|||
|
case UNMANAGE_IF: {
|
|||
|
WsbTraceAndPrint(CLI_MESSAGE_VOLUME_UNMANAGE_HELP, NULL);
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
|
|||
|
}
|
|||
|
case JOB_IF: {
|
|||
|
WsbTraceAndPrint(CLI_MESSAGE_VOLUME_JOB_HELP, NULL);
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
|
|||
|
}
|
|||
|
case DELETE_IF: {
|
|||
|
WsbTraceAndPrint(CLI_MESSAGE_VOLUME_DELETE_HELP, NULL);
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
|
|||
|
}
|
|||
|
}
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(Interface);
|
|||
|
}
|
|||
|
|
|||
|
case MEDIA_IF: {
|
|||
|
switch (SubInterface) {
|
|||
|
case HELP_IF:
|
|||
|
case UNKNOWN_IF:
|
|||
|
case SHOW_IF: {
|
|||
|
WsbTraceAndPrint(CLI_MESSAGE_MEDIA_SHOW_HELP, NULL);
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
|
|||
|
}
|
|||
|
case DELETE_IF: {
|
|||
|
WsbTraceAndPrint(CLI_MESSAGE_MEDIA_DELETE_HELP, NULL);
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
|
|||
|
}
|
|||
|
case SYNCHRONIZE_IF: {
|
|||
|
WsbTraceAndPrint(CLI_MESSAGE_MEDIA_SYNCHRONIZE_HELP, NULL);
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
|
|||
|
}
|
|||
|
case RECREATEMASTER_IF: {
|
|||
|
WsbTraceAndPrint(CLI_MESSAGE_MEDIA_RECREATEMASTER_HELP, NULL);
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
|
|||
|
}
|
|||
|
}
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(Interface);
|
|||
|
}
|
|||
|
case FILE_IF: {
|
|||
|
switch (SubInterface) {
|
|||
|
case HELP_IF:
|
|||
|
case UNKNOWN_IF:
|
|||
|
case RECALL_IF: {
|
|||
|
WsbTraceAndPrint(CLI_MESSAGE_FILE_RECALL_HELP, NULL);
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(SubInterface);
|
|||
|
}
|
|||
|
}
|
|||
|
BREAK_IF_NOT_UNKNOWN_IF(Interface);
|
|||
|
}
|
|||
|
}
|
|||
|
WsbTraceOut(OLESTR("ClipHelp"), OLESTR(""));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipParseTime(
|
|||
|
IN LPWSTR TimeString,
|
|||
|
OUT PSYSTEMTIME ScheduledTime)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description
|
|||
|
|
|||
|
|
|||
|
Parses the passed in TimeString as a 24 hour format
|
|||
|
(hh:mm:ss) and sets hour/minute/sec/millisec in the passed
|
|||
|
in SYSTEMTIME structure
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
TimeString - String in the format "hh:mm:ss"
|
|||
|
ScheduledTime - Pointer to SYSTEMTIME structure. Time parsed from TimeString
|
|||
|
(if ok) will be used to set hour/min/sec/millisec fields in this struc.
|
|||
|
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
S_OK - TimeString is valid and time was successfully parsed
|
|||
|
Any other - Syntax error in TimeString
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
LPWSTR stopString = NULL, hourString = NULL, minuteString = NULL, secondString = NULL;
|
|||
|
DWORD hour, minute, second = 0;
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipParseTime"), OLESTR(""));
|
|||
|
|
|||
|
try {
|
|||
|
hourString = wcstok(TimeString, HSM_SCHED_TIME_SEPARATORS);
|
|||
|
WsbAssert(hourString != NULL, E_NOINTERFACE);
|
|||
|
CLIP_GET_DWORD_ARG(hour, hourString, stopString);
|
|||
|
|
|||
|
if (hour > 23) {
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
minuteString = wcstok(NULL, HSM_SCHED_TIME_SEPARATORS);
|
|||
|
WsbAssert(minuteString != NULL, E_NOINTERFACE);
|
|||
|
CLIP_GET_DWORD_ARG(minute, minuteString, stopString);
|
|||
|
|
|||
|
if (minute > 59) {
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
|
|||
|
secondString = wcstok(NULL, HSM_SCHED_TIME_SEPARATORS);
|
|||
|
if (secondString != NULL) {
|
|||
|
CLIP_GET_DWORD_ARG(second, secondString, stopString);
|
|||
|
if (second > 59) {
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ScheduledTime->wHour = (WORD) hour;
|
|||
|
ScheduledTime->wMinute = (WORD) minute;
|
|||
|
ScheduledTime->wSecond = (WORD) second;
|
|||
|
ScheduledTime->wMilliseconds = 0;
|
|||
|
|
|||
|
}WsbCatch(hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipParseTime"), OLESTR(""));
|
|||
|
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
ClipParseSchedule(
|
|||
|
IN LPWSTR ScheduleString,
|
|||
|
OUT PHSM_JOB_SCHEDULE Schedule
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description
|
|||
|
|
|||
|
Parses the passed in schedule string, and constructs the canonical schedule
|
|||
|
form (of type HSM_JOB_SCHEDULE)
|
|||
|
|
|||
|
Examples of schedule parameter:
|
|||
|
|
|||
|
"At 21:03:00"
|
|||
|
"At Startup"
|
|||
|
"At Login"
|
|||
|
"At Idle"
|
|||
|
"Every 1 Week 1 21:03:00"
|
|||
|
"Every 2 Day 21:03:00"
|
|||
|
"Every 1 Month 2 21:03:00"
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
ScheduleString - String specifying the schedule in user-readable syntax
|
|||
|
Schedule - Pointer to canonical schedule form will be returned in this var.
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
S_OK - Successful, Schedule contains a pointer to the constructed schedule.
|
|||
|
E_OUTOFMEMORY - Lack of sufficient system resources
|
|||
|
Any other error: incorrect schedule specification
|
|||
|
--*/
|
|||
|
{
|
|||
|
LPWSTR token;
|
|||
|
DWORD occurrence;
|
|||
|
HSM_JOB_FREQUENCY frequency;
|
|||
|
SYSTEMTIME scheduledTime;
|
|||
|
DWORD day;
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("ClipParseSchedule"), OLESTR(""));
|
|||
|
|
|||
|
try {
|
|||
|
token = wcstok(ScheduleString, SEPARATORS);
|
|||
|
|
|||
|
WsbAssert(token != NULL, E_NOINTERFACE);
|
|||
|
|
|||
|
if (!_wcsicmp(token, HSM_SCHED_AT)) {
|
|||
|
|
|||
|
token = wcstok(NULL, SEPARATORS);
|
|||
|
|
|||
|
if (token == NULL) {
|
|||
|
//
|
|||
|
// Bad arguments
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
} else if (!_wcsicmp(token, HSM_SCHED_SYSTEMSTARTUP)) {
|
|||
|
//
|
|||
|
// Once at system startup
|
|||
|
//
|
|||
|
Schedule->Frequency = SystemStartup;
|
|||
|
WsbThrow(S_OK);
|
|||
|
} else if (!_wcsicmp(token, HSM_SCHED_LOGIN)) {
|
|||
|
//
|
|||
|
// Once at login time
|
|||
|
//
|
|||
|
Schedule->Frequency = Login;
|
|||
|
WsbThrow(S_OK);
|
|||
|
} else if (!_wcsicmp(token, HSM_SCHED_IDLE)) {
|
|||
|
//
|
|||
|
// Whenever system's idle
|
|||
|
//
|
|||
|
Schedule->Frequency = WhenIdle;
|
|||
|
WsbThrow(S_OK);
|
|||
|
} else {
|
|||
|
|
|||
|
GetSystemTime(&scheduledTime);
|
|||
|
//
|
|||
|
// Once at specified time.
|
|||
|
// Parse the time string and obtain it
|
|||
|
// TBD - Add provision to specify date as well as time
|
|||
|
//
|
|||
|
hr = ClipParseTime(token,
|
|||
|
&scheduledTime);
|
|||
|
WsbAssertHr(hr);
|
|||
|
|
|||
|
Schedule->Frequency = Once;
|
|||
|
Schedule->Parameters.Once.Time = scheduledTime;
|
|||
|
WsbThrow(S_OK);
|
|||
|
}
|
|||
|
} else if (!_wcsicmp(token, HSM_SCHED_EVERY)) {
|
|||
|
LPWSTR stopString = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Get the occurrence
|
|||
|
//
|
|||
|
token = wcstok(NULL, SEPARATORS);
|
|||
|
WsbAssert(token != NULL, E_NOINTERFACE);
|
|||
|
CLIP_GET_DWORD_ARG(occurrence, token, stopString);
|
|||
|
|
|||
|
//
|
|||
|
// Get the qualifier: Daily/Weekly/Monthly
|
|||
|
//
|
|||
|
token = wcstok(NULL, SEPARATORS);
|
|||
|
WsbAssert(token != NULL, E_NOINTERFACE);
|
|||
|
if (!_wcsicmp(token, HSM_SCHED_DAILY)) {
|
|||
|
frequency = Daily;
|
|||
|
} else if (!_wcsicmp(token, HSM_SCHED_WEEKLY)) {
|
|||
|
frequency = Weekly;
|
|||
|
} else if (!_wcsicmp(token, HSM_SCHED_MONTHLY)) {
|
|||
|
frequency = Monthly;
|
|||
|
} else {
|
|||
|
//
|
|||
|
// Badly constructed argument
|
|||
|
//
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
//
|
|||
|
// Get current time
|
|||
|
//
|
|||
|
GetSystemTime(&scheduledTime);
|
|||
|
//
|
|||
|
// For weekly/monthly we also need to get the day of the week/month
|
|||
|
// Monday = 1, Sunday = 7 for weekly
|
|||
|
//
|
|||
|
if ((frequency == Weekly) || (frequency == Monthly)) {
|
|||
|
token = wcstok(NULL, SEPARATORS);
|
|||
|
WsbAssert(token != NULL, E_NOINTERFACE);
|
|||
|
|
|||
|
CLIP_GET_DWORD_ARG(day, token, stopString);
|
|||
|
|
|||
|
//
|
|||
|
// Validate & update the parameters
|
|||
|
//
|
|||
|
if (frequency == Weekly) {
|
|||
|
if (day > 6) {
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
scheduledTime.wDayOfWeek = (WORD) day;
|
|||
|
}
|
|||
|
if (frequency == Monthly) {
|
|||
|
if ((day > 31) || (day < 1)) {
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
scheduledTime.wDay = (WORD) day;
|
|||
|
}
|
|||
|
}
|
|||
|
//
|
|||
|
// Fetch the time
|
|||
|
//
|
|||
|
token = wcstok(NULL, SEPARATORS);
|
|||
|
WsbAssert(token != NULL, E_NOINTERFACE);
|
|||
|
hr = ClipParseTime(token,
|
|||
|
&scheduledTime);
|
|||
|
|
|||
|
WsbAssertHr(hr);
|
|||
|
|
|||
|
Schedule->Frequency = frequency;
|
|||
|
Schedule->Parameters.Daily.Occurrence = occurrence;
|
|||
|
Schedule->Parameters.Daily.Time = scheduledTime;
|
|||
|
} else {
|
|||
|
WsbThrow(E_NOINTERFACE);
|
|||
|
}
|
|||
|
}WsbCatch(hr);
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipParseSchedule"), OLESTR(""));
|
|||
|
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
ClipInitializeTrace(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description
|
|||
|
|
|||
|
Initializes the trace/printing mechanism for CLI
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
TRUE if successful, FALSE otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
BOOL ret = TRUE;
|
|||
|
|
|||
|
|
|||
|
if (S_OK == CoCreateInstance(CLSID_CWsbTrace, 0, CLSCTX_SERVER, IID_IWsbTrace, (void **)&g_pTrace)) {
|
|||
|
CWsbStringPtr tracePath;
|
|||
|
CWsbStringPtr regPath;
|
|||
|
CWsbStringPtr outString;
|
|||
|
|
|||
|
// Registry path for CLI settings
|
|||
|
// If those expand beyond Trace settings, this path should go to a header file
|
|||
|
regPath = L"SOFTWARE\\Microsoft\\RemoteStorage\\CLI";
|
|||
|
|
|||
|
// Check if tracing path already exists, if not - set it (this should happen only once)
|
|||
|
WsbAffirmHr(outString.Alloc(WSB_TRACE_BUFF_SIZE));
|
|||
|
if ( WsbGetRegistryValueString(NULL, regPath, L"WsbTraceFileName", outString, WSB_TRACE_BUFF_SIZE, 0) != S_OK) {
|
|||
|
// No trace settings yet
|
|||
|
WCHAR *systemPath;
|
|||
|
systemPath = _wgetenv(L"SystemRoot");
|
|||
|
WsbAffirmHr(tracePath.Printf( L"%ls\\System32\\RemoteStorage\\Trace\\RsCli.Trc", systemPath));
|
|||
|
|
|||
|
// Set default settings in the Registry
|
|||
|
WsbEnsureRegistryKeyExists(0, regPath);
|
|||
|
WsbSetRegistryValueString(0, regPath, L"WsbTraceFileName", tracePath);
|
|||
|
|
|||
|
// Make sure the trace directory exists.
|
|||
|
WsbAffirmHr(tracePath.Printf( L"%ls\\System32\\RemoteStorage", systemPath));
|
|||
|
CreateDirectory(tracePath, 0);
|
|||
|
WsbAffirmHr(tracePath.Printf( L"%ls\\System32\\RemoteStorage\\Trace", systemPath));
|
|||
|
CreateDirectory(tracePath, 0);
|
|||
|
}
|
|||
|
|
|||
|
g_pTrace->SetRegistryEntry(regPath);
|
|||
|
g_pTrace->LoadFromRegistry();
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
ClipUninitializeTrace(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description
|
|||
|
|
|||
|
Uninitializes the trace/print mechansim
|
|||
|
Paired with ClipInitializeTrace
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
g_pTrace = 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
ClipHandleErrors(
|
|||
|
IN HRESULT RetCode,
|
|||
|
IN RSS_INTERFACE Interface,
|
|||
|
IN RSS_INTERFACE SubInterface
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description
|
|||
|
|
|||
|
Translates the main return value & displays any appropriate
|
|||
|
error messages and returns
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
RetCode - Error to handle
|
|||
|
Interface - RSS interface specified in the command
|
|||
|
SubInterface - RSS sub-interface specified in the command
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
WsbTraceIn(OLESTR("ClipHandleErrors"), OLESTR(""));
|
|||
|
|
|||
|
switch (RetCode) {
|
|||
|
case E_INVALIDARG:
|
|||
|
case S_OK:{
|
|||
|
//
|
|||
|
// Nothing to print
|
|||
|
//
|
|||
|
break;}
|
|||
|
|
|||
|
case E_NOINTERFACE:{
|
|||
|
WsbTraceAndPrint(CLI_MESSAGE_VALUE_DISPLAY, WsbHrAsString(E_INVALIDARG));
|
|||
|
ClipHelp(Interface,
|
|||
|
SubInterface);
|
|||
|
break;}
|
|||
|
default:{
|
|||
|
WsbTraceAndPrint(CLI_MESSAGE_VALUE_DISPLAY, WsbHrAsString(RetCode));
|
|||
|
break;}
|
|||
|
}
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("ClipHandleErrors"), OLESTR(""));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
extern "C"
|
|||
|
int __cdecl
|
|||
|
wmain()
|
|||
|
{
|
|||
|
LPWSTR commandLine, token;
|
|||
|
HRESULT hr = E_NOINTERFACE;
|
|||
|
RSS_INTERFACE intrface = HELP_IF, subInterface = UNKNOWN_IF;
|
|||
|
|
|||
|
try {
|
|||
|
WsbAffirmHr(CoInitialize(NULL));
|
|||
|
|
|||
|
//
|
|||
|
// Set to OEM page locale
|
|||
|
//
|
|||
|
_wsetlocale(LC_ALL, L".OCP");
|
|||
|
|
|||
|
ClipInitializeTrace();
|
|||
|
|
|||
|
commandLine = GetCommandLine();
|
|||
|
//
|
|||
|
// Get argv[0] out of the way
|
|||
|
//
|
|||
|
token = wcstok(commandLine, SEPARATORS);
|
|||
|
|
|||
|
//
|
|||
|
// Get the interface string
|
|||
|
//
|
|||
|
token = wcstok(NULL, SEPARATORS);
|
|||
|
|
|||
|
if (token == NULL) {
|
|||
|
ClipHelp(HELP_IF,
|
|||
|
UNKNOWN_IF);
|
|||
|
hr = S_OK;
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
intrface = ClipGetInterface(token);
|
|||
|
|
|||
|
if (intrface == UNKNOWN_IF) {
|
|||
|
hr = E_NOINTERFACE;
|
|||
|
intrface = HELP_IF;
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
if (intrface == HELP_IF) {
|
|||
|
ClipHelp(HELP_IF,
|
|||
|
UNKNOWN_IF);
|
|||
|
hr = S_OK;
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get sub interface string
|
|||
|
//
|
|||
|
token = wcstok(NULL, SEPARATORS);
|
|||
|
|
|||
|
if (token == NULL) {
|
|||
|
hr = E_NOINTERFACE;
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
subInterface = ClipGetInterface(token);
|
|||
|
|
|||
|
if (subInterface == UNKNOWN_IF) {
|
|||
|
hr = E_NOINTERFACE;
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
if (subInterface == HELP_IF) {
|
|||
|
ClipHelp(intrface,
|
|||
|
UNKNOWN_IF);
|
|||
|
hr = S_OK;
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
//
|
|||
|
// Now compile the switches & arguments into separate arrays
|
|||
|
// First, get the rest of line ..
|
|||
|
//
|
|||
|
token = wcstok(NULL, L"");
|
|||
|
hr = ClipCompileSwitchesAndArgs(token,
|
|||
|
intrface,
|
|||
|
subInterface);
|
|||
|
|
|||
|
if (hr != S_OK) {
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
switch (intrface) {
|
|||
|
|
|||
|
case ADMIN_IF:{
|
|||
|
if (subInterface == SHOW_IF) {
|
|||
|
hr = ClipAdminShow();
|
|||
|
} else if (subInterface == SET_IF) {
|
|||
|
hr = ClipAdminSet();
|
|||
|
} else {
|
|||
|
hr = E_NOINTERFACE;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case VOLUME_IF:{
|
|||
|
if (subInterface == MANAGE_IF) {
|
|||
|
hr = ClipVolumeSetManage(FALSE);
|
|||
|
} else if (subInterface == UNMANAGE_IF) {
|
|||
|
hr = ClipVolumeUnmanage();
|
|||
|
} else if (subInterface == SET_IF) {
|
|||
|
hr = ClipVolumeSetManage(TRUE);
|
|||
|
} else if (subInterface == SHOW_IF) {
|
|||
|
hr = ClipVolumeShow();
|
|||
|
} else if (subInterface == DELETE_IF) {
|
|||
|
hr = ClipVolumeDelete();
|
|||
|
} else if (subInterface == JOB_IF) {
|
|||
|
hr = ClipVolumeJob();
|
|||
|
} else {
|
|||
|
hr = E_NOINTERFACE;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case FILE_IF:{
|
|||
|
if (subInterface == RECALL_IF) {
|
|||
|
hr = ClipFileRecall();
|
|||
|
} else {
|
|||
|
hr = E_NOINTERFACE;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case MEDIA_IF:{
|
|||
|
if (subInterface == SYNCHRONIZE_IF) {
|
|||
|
hr = ClipMediaSynchronize();
|
|||
|
} else if (subInterface == RECREATEMASTER_IF) {
|
|||
|
hr = ClipMediaRecreateMaster();
|
|||
|
} else if (subInterface == DELETE_IF) {
|
|||
|
hr = ClipMediaDelete();
|
|||
|
} else if (subInterface == SHOW_IF) {
|
|||
|
hr = ClipMediaShow();
|
|||
|
} else {
|
|||
|
hr = E_NOINTERFACE;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
default:{
|
|||
|
hr = E_NOINTERFACE;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
exit:
|
|||
|
|
|||
|
ClipHandleErrors(hr,
|
|||
|
intrface,
|
|||
|
subInterface);
|
|||
|
|
|||
|
ClipCleanup();
|
|||
|
ClipUninitializeTrace();
|
|||
|
CoUninitialize();
|
|||
|
|
|||
|
}WsbCatchAndDo(hr,
|
|||
|
WsbTraceAndPrint(CLI_MESSAGE_GENERIC_ERROR, WsbHrAsString(hr));
|
|||
|
);
|
|||
|
|
|||
|
CLIP_TRANSLATE_HR_AND_RETURN(hr);
|
|||
|
}
|