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.
 
 
 
 
 
 

451 lines
17 KiB

/*
**++
**
** Copyright (c) 2000-2001 Microsoft Corporation
**
**
** Module Name:
**
** util.cpp
**
**
** Abstract:
**
** Sample program to
** - obtain and display the Writer metadata.
** - create a snapshot set
**
** Author:
**
** Adi Oltean [aoltean] 05-Dec-2000
**
** The sample is based on the Metasnap test program written by Michael C. Johnson.
**
**
** Revision History:
**
**--
*/
///////////////////////////////////////////////////////////////////////////////
// Includes
#include "vsreq.h"
///////////////////////////////////////////////////////////////////////////////
// Print usage
void CVssSampleRequestor::PrintUsage()
{
wprintf(
L"\nUsage:\n"
L" vsreq [-b] [-s] [-x <file.xml>] [<volumes>]\n"
L"\nOptions:\n"
L" -b Backup includes bootable & system state.\n"
L" -s Enable component selection.\n"
L" -x <file.xml> Generate an XML file containing the backup metadata\n"
L" <volumes> Specifies the volumes to be part of the snapshot set\n"
L" The volumes in the list must be distinct and \n"
L" must be separated by space. A volume must be \n"
L" terminated with a trailing backslask (for example C:\\).\n"
L"\n"
L"\nExample:\n"
L" The following command will create a snapshot set\n"
L" on the volumes mounted under c:\\ and d:\\\n"
L"\n"
L" vsreq c:\\ d:\\ \n"
L"\n"
L" The following command will create a snapshot set on the volumes \n"
L" that contain selected components and also the volume c:\\\n"
L" Also, the backup will contain bootable and system state.\n"
L" The XML results will be stored in file.xml\n"
L"\n"
L" vsreq -b -s -x file.xml c:\\ \n"
);
throw(2);
}
void CVssSampleRequestor::ParseCommandLine(
IN INT nArgsCount,
IN WCHAR ** ppwszArgsArray
)
{
if (nArgsCount == 0)
PrintUsage();
// For each argument in the command line
bool bParsingVolumes = false;
INT nCurrentArg = nArgsCount;
WCHAR ** ppwszCurrentArg = ppwszArgsArray;
for(; nCurrentArg--; ppwszCurrentArg++)
{
if (!bParsingVolumes) {
// Check for Bootable & system state option
if (!m_bBootableSystemState && !wcscmp(*ppwszCurrentArg, L"-b")) {
m_bBootableSystemState = true;
continue;
}
// Check for Selected components option
if (!m_bComponentSelectionEnabled && !wcscmp(*ppwszCurrentArg, L"-s")) {
m_bComponentSelectionEnabled = true;
continue;
}
// Check for Xml file option
if (!m_pwszXmlFile && !wcscmp(*ppwszCurrentArg, L"-x")) {
if (nCurrentArg-- == 0)
return PrintUsage();
ppwszCurrentArg++;
m_pwszXmlFile = *ppwszCurrentArg;
continue;
}
}
// We suppose that the next arguments are the volumes
bParsingVolumes = true;
// Add the volume to the list of snapshotting volumes
// Make sure that the volume name is valid
bool bAdded = false;
if (!AddVolume(*ppwszCurrentArg, bAdded)) {
wprintf(L"\nError while parsing the command line:\n"
L"\t%s is not a valid option or a mount point [0x%08lx]\n\n",
*ppwszCurrentArg, GetLastError() );
PrintUsage();
}
// Check if the same volume is added twice
if (!bAdded) {
wprintf(L"\nError while parsing the command line:\n"
L"\tThe volume %s is specified twice\n\n", *ppwszCurrentArg );
PrintUsage();
}
}
// Check if we added at least one volume
if ((m_nVolumesCount == 0) && !m_bComponentSelectionEnabled) {
wprintf(L"\nError while parsing the command line:\n"
L"\t- You should specify at least one volume or enable component selection\n\n");
PrintUsage();
}
}
// Add the given volume by the contained path
void CVssSampleRequestor::AddVolumeForComponent(
IN IVssWMFiledesc* pFileDesc
)
{
// Get the component path
CComBSTR bstrPath;
CHECK_SUCCESS(pFileDesc->GetPath(&bstrPath));
// Trying to find the volume that will contain the path.
WCHAR wszExpandedPath[MAX_TEXT_BUFFER];
if (!ExpandEnvironmentStringsW(bstrPath, wszExpandedPath, MAX_TEXT_BUFFER))
Error( 1, L"\nExpandEnvironmentStringsW(%s, wszExpandedPath, MAX_TEXT_BUFFER) failed with [0x%08lx]\n",
bstrPath, GetLastError());
// Eliminate one by one the terminating folder names, until we reach an existing path.
// Then get the volume name for that path
WCHAR wszMountPoint[MAX_TEXT_BUFFER];
while(true) {
if (GetVolumePathNameW(wszExpandedPath, wszMountPoint, MAX_TEXT_BUFFER))
break;
if (GetLastError() != ERROR_FILE_NOT_FOUND)
Error( 1, L"\nGetVolumePathNameW(%s, wszMountPoint, MAX_TEXT_BUFFER) failed with [0x%08lx]\n",
wszExpandedPath, GetLastError());
WCHAR* pwszLastBackslashIndex = wcsrchr(wszExpandedPath, L'\\');
if (!pwszLastBackslashIndex)
Error( 1, L"\nCannot find anymore a backslash in path %s. \n"
L"The original path %s seems invalid.\n", wszExpandedPath, bstrPath);
// Eliminate the last folder name
pwszLastBackslashIndex[0] = L'\0';
}
// Add the volume, if possible
bool bAdded = false;
if (!AddVolume( wszMountPoint, bAdded ))
Error( 1, L"\nUnexpected error: cannot add volume %s to the snapshot set.\n", wszMountPoint);
wprintf (L" [Volume %s (that contains the file) %s marked as a candidate for snapshot]\n",
wszMountPoint, bAdded? L"is": L"is already");
}
// Add the given volume in the list of potential candidates for snapshots
// - Returns "false" if the volume does not correspond to a real mount point
// (and GetLastError() will contain the correct Win32 error code)
// - Sets "true" in the bAdded parameter if the volume is actually added
bool CVssSampleRequestor::AddVolume(
IN WCHAR* pwszVolume,
OUT bool & bAdded
)
{
// Initialize [out] parameters
bAdded = false;
// Check if the volume represents a real mount point
WCHAR wszVolumeName[MAX_TEXT_BUFFER];
if (!GetVolumeNameForVolumeMountPoint(pwszVolume, wszVolumeName, MAX_TEXT_BUFFER))
return false; // Invalid volume
// Check if the volume is already added.
for (INT nIndex = 0; nIndex < m_nVolumesCount; nIndex++)
if (!wcscmp(wszVolumeName, m_ppwszVolumeNamesList[nIndex]))
return true; // Volume already added. Stop here.
// Check if we exceeded the maximum number of volumes
if (m_nVolumesCount == MAX_VOLUMES)
Error( 1, L"Maximum number of volumes exceeded");
// Create a copy of the volume
WCHAR* pwszNewVolume = _wcsdup(pwszVolume);
if (pwszNewVolume == NULL)
Error( 1, L"Memory allocation error");
// Create a copy of the volume name
WCHAR* pwszNewVolumeName = _wcsdup(wszVolumeName);
if (pwszNewVolumeName == NULL) {
free(pwszNewVolume);
Error( 1, L"Memory allocation error");
}
// Add the volume in our internal list of snapshotted volumes
m_ppwszVolumesList[m_nVolumesCount] = pwszNewVolume;
m_ppwszVolumeNamesList[m_nVolumesCount] = pwszNewVolumeName;
m_nVolumesCount++;
bAdded = true;
return true;
}
// This function displays the formatted message at the console and throws
// The passed return code will be returned by vsreq.exe
void CVssSampleRequestor::Error(
IN INT nReturnCode,
IN const WCHAR* pwszMsgFormat,
IN ...
)
{
va_list marker;
va_start( marker, pwszMsgFormat );
vwprintf( pwszMsgFormat, marker );
va_end( marker );
// throw that return code.
throw(nReturnCode);
}
///////////////////////////////////////////////////////////////////////////////
// Utility functions
// Print a file description object
void CVssSampleRequestor::PrintFiledesc (IVssWMFiledesc *pFiledesc, LPCWSTR wszDescription)
{
CComBSTR bstrPath;
CComBSTR bstrFilespec;
CComBSTR bstrAlternate;
bool bRecursive;
CHECK_SUCCESS(pFiledesc->GetPath(&bstrPath));
CHECK_SUCCESS(pFiledesc->GetFilespec (&bstrFilespec));
CHECK_NOFAIL(pFiledesc->GetRecursive(&bRecursive));
CHECK_NOFAIL(pFiledesc->GetAlternateLocation(&bstrAlternate));
wprintf (L"%s\n"
L" Path = %s\n"
L" Filespec = %s\n"
L" Recursive = %s\n",
wszDescription,
bstrPath,
bstrFilespec,
bRecursive ? L"yes" : L"no");
if (bstrAlternate && wcslen (bstrAlternate) > 0)
wprintf(L" Alternate Location = %s\n", bstrAlternate);
}
// Convert a usage type into a string
LPCWSTR CVssSampleRequestor::GetStringFromUsageType (VSS_USAGE_TYPE eUsageType)
{
LPCWSTR pwszRetString = L"UNDEFINED";
switch (eUsageType)
{
case VSS_UT_BOOTABLESYSTEMSTATE: pwszRetString = L"BootableSystemState"; break;
case VSS_UT_SYSTEMSERVICE: pwszRetString = L"SystemService"; break;
case VSS_UT_USERDATA: pwszRetString = L"UserData"; break;
case VSS_UT_OTHER: pwszRetString = L"Other"; break;
default:
break;
}
return (pwszRetString);
}
// Convert a source type into a string
LPCWSTR CVssSampleRequestor::GetStringFromSourceType (VSS_SOURCE_TYPE eSourceType)
{
LPCWSTR pwszRetString = L"UNDEFINED";
switch (eSourceType)
{
case VSS_ST_TRANSACTEDDB: pwszRetString = L"TransactionDb"; break;
case VSS_ST_NONTRANSACTEDDB: pwszRetString = L"NonTransactionDb"; break;
case VSS_ST_OTHER: pwszRetString = L"Other"; break;
default:
break;
}
return (pwszRetString);
}
// Convert a restore method into a string
LPCWSTR CVssSampleRequestor::GetStringFromRestoreMethod (VSS_RESTOREMETHOD_ENUM eRestoreMethod)
{
LPCWSTR pwszRetString = L"UNDEFINED";
switch (eRestoreMethod)
{
case VSS_RME_RESTORE_IF_NOT_THERE: pwszRetString = L"RestoreIfNotThere"; break;
case VSS_RME_RESTORE_IF_CAN_REPLACE: pwszRetString = L"RestoreIfCanReplace"; break;
case VSS_RME_STOP_RESTORE_START: pwszRetString = L"StopRestoreStart"; break;
case VSS_RME_RESTORE_TO_ALTERNATE_LOCATION: pwszRetString = L"RestoreToAlternateLocation"; break;
case VSS_RME_RESTORE_AT_REBOOT: pwszRetString = L"RestoreAtReboot"; break;
case VSS_RME_CUSTOM: pwszRetString = L"Custom"; break;
default:
break;
}
return (pwszRetString);
}
// Convert a writer restore method into a string
LPCWSTR CVssSampleRequestor::GetStringFromWriterRestoreMethod (VSS_WRITERRESTORE_ENUM eWriterRestoreMethod)
{
LPCWSTR pwszRetString = L"UNDEFINED";
switch (eWriterRestoreMethod)
{
case VSS_WRE_NEVER: pwszRetString = L"RestoreNever"; break;
case VSS_WRE_IF_REPLACE_FAILS: pwszRetString = L"RestoreIfReplaceFailsI"; break;
case VSS_WRE_ALWAYS: pwszRetString = L"RestoreAlways"; break;
default:
break;
}
return (pwszRetString);
}
// Convert a component type into a string
LPCWSTR CVssSampleRequestor::GetStringFromComponentType (VSS_COMPONENT_TYPE eComponentType)
{
LPCWSTR pwszRetString = L"UNDEFINED";
switch (eComponentType)
{
case VSS_CT_DATABASE: pwszRetString = L"Database"; break;
case VSS_CT_FILEGROUP: pwszRetString = L"FileGroup"; break;
default:
break;
}
return (pwszRetString);
}
// Convert a failure type into a string
LPCWSTR CVssSampleRequestor::GetStringFromFailureType(HRESULT hrStatus)
{
LPCWSTR pwszFailureType = L"";
switch (hrStatus)
{
case VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT: pwszFailureType = L"VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT"; break;
case VSS_E_WRITERERROR_OUTOFRESOURCES: pwszFailureType = L"VSS_E_WRITERERROR_OUTOFRESOURCES"; break;
case VSS_E_WRITERERROR_TIMEOUT: pwszFailureType = L"VSS_E_WRITERERROR_TIMEOUT"; break;
case VSS_E_WRITERERROR_NONRETRYABLE: pwszFailureType = L"VSS_E_WRITERERROR_NONRETRYABLE"; break;
case VSS_E_WRITERERROR_RETRYABLE: pwszFailureType = L"VSS_E_WRITERERROR_RETRYABLE"; break;
case VSS_E_BAD_STATE: pwszFailureType = L"VSS_E_BAD_STATE"; break;
case VSS_E_PROVIDER_ALREADY_REGISTERED: pwszFailureType = L"VSS_E_PROVIDER_ALREADY_REGISTERED"; break;
case VSS_E_PROVIDER_NOT_REGISTERED: pwszFailureType = L"VSS_E_PROVIDER_NOT_REGISTERED"; break;
case VSS_E_PROVIDER_VETO: pwszFailureType = L"VSS_E_PROVIDER_VETO"; break;
case VSS_E_PROVIDER_IN_USE: pwszFailureType = L"VSS_E_PROVIDER_IN_USE"; break;
case VSS_E_OBJECT_NOT_FOUND: pwszFailureType = L"VSS_E_OBJECT_NOT_FOUND"; break;
case VSS_S_ASYNC_PENDING: pwszFailureType = L"VSS_S_ASYNC_PENDING"; break;
case VSS_S_ASYNC_FINISHED: pwszFailureType = L"VSS_S_ASYNC_FINISHED"; break;
case VSS_S_ASYNC_CANCELLED: pwszFailureType = L"VSS_S_ASYNC_CANCELLED"; break;
case VSS_E_VOLUME_NOT_SUPPORTED: pwszFailureType = L"VSS_E_VOLUME_NOT_SUPPORTED"; break;
case VSS_E_VOLUME_NOT_SUPPORTED_BY_PROVIDER: pwszFailureType = L"VSS_E_VOLUME_NOT_SUPPORTED_BY_PROVIDER"; break;
case VSS_E_OBJECT_ALREADY_EXISTS: pwszFailureType = L"VSS_E_OBJECT_ALREADY_EXISTS"; break;
case VSS_E_UNEXPECTED_PROVIDER_ERROR: pwszFailureType = L"VSS_E_UNEXPECTED_PROVIDER_ERROR"; break;
case VSS_E_CORRUPT_XML_DOCUMENT: pwszFailureType = L"VSS_E_CORRUPT_XML_DOCUMENT"; break;
case VSS_E_INVALID_XML_DOCUMENT: pwszFailureType = L"VSS_E_INVALID_XML_DOCUMENT"; break;
case VSS_E_MAXIMUM_NUMBER_OF_VOLUMES_REACHED: pwszFailureType = L"VSS_E_MAXIMUM_NUMBER_OF_VOLUMES_REACHED"; break;
case VSS_E_FLUSH_WRITES_TIMEOUT: pwszFailureType = L"VSS_E_FLUSH_WRITES_TIMEOUT"; break;
case VSS_E_HOLD_WRITES_TIMEOUT: pwszFailureType = L"VSS_E_HOLD_WRITES_TIMEOUT"; break;
case VSS_E_UNEXPECTED_WRITER_ERROR: pwszFailureType = L"VSS_E_UNEXPECTED_WRITER_ERROR"; break;
case VSS_E_SNAPSHOT_SET_IN_PROGRESS: pwszFailureType = L"VSS_E_SNAPSHOT_SET_IN_PROGRESS"; break;
case VSS_E_MAXIMUM_NUMBER_OF_SNAPSHOTS_REACHED: pwszFailureType = L"VSS_E_MAXIMUM_NUMBER_OF_SNAPSHOTS_REACHED"; break;
case VSS_E_WRITER_INFRASTRUCTURE: pwszFailureType = L"VSS_E_WRITER_INFRASTRUCTURE"; break;
case VSS_E_WRITER_NOT_RESPONDING: pwszFailureType = L"VSS_E_WRITER_NOT_RESPONDING"; break;
case VSS_E_WRITER_ALREADY_SUBSCRIBED: pwszFailureType = L"VSS_E_WRITER_ALREADY_SUBSCRIBED"; break;
case NOERROR:
default:
break;
}
return (pwszFailureType);
}
// Convert a writer status into a string
LPCWSTR CVssSampleRequestor::GetStringFromWriterStatus(VSS_WRITER_STATE eWriterStatus)
{
LPCWSTR pwszRetString = L"UNDEFINED";
switch (eWriterStatus)
{
case VSS_WS_STABLE: pwszRetString = L"STABLE"; break;
case VSS_WS_WAITING_FOR_FREEZE: pwszRetString = L"WAITING_FOR_FREEZE"; break;
case VSS_WS_WAITING_FOR_THAW: pwszRetString = L"WAITING_FOR_THAW"; break;
case VSS_WS_WAITING_FOR_BACKUP_COMPLETE:pwszRetString = L"VSS_WS_WAITING_FOR_BACKUP_COMPLETE"; break;
case VSS_WS_FAILED_AT_IDENTIFY: pwszRetString = L"FAILED_AT_IDENTIFY"; break;
case VSS_WS_FAILED_AT_PREPARE_BACKUP: pwszRetString = L"FAILED_AT_PREPARE_BACKUP";break;
case VSS_WS_FAILED_AT_PREPARE_SNAPSHOT: pwszRetString = L"VSS_WS_FAILED_AT_PREPARE_SNAPSHOT"; break;
case VSS_WS_FAILED_AT_FREEZE: pwszRetString = L"FAILED_AT_FREEZE"; break;
case VSS_WS_FAILED_AT_THAW: pwszRetString = L"FAILED_AT_THAW"; break;
default:
break;
}
return (pwszRetString);
}