Пример #1
0
void QLCFixtureEditor::slotChannelListContextMenuRequested()
{
    QAction editAction(QIcon(":/edit.png"), tr("Edit"), this);
    QAction copyAction(QIcon(":/editcopy.png"), tr("Copy"), this);
    QAction pasteAction(QIcon(":/editpaste.png"), tr("Paste"), this);
    QAction removeAction(QIcon(":/editdelete.png"), tr("Remove"), this);

    /* Group menu */
    QMenu groupMenu;
    groupMenu.setTitle("Set group");
    QStringListIterator it(QLCChannel::groupList());
    while (it.hasNext() == true)
        groupMenu.addAction(it.next());

    /* Master edit menu */
    QMenu menu;
    menu.setTitle(tr("Channels"));
    menu.addAction(&editAction);
    menu.addAction(&copyAction);
    menu.addAction(&pasteAction);
    menu.addSeparator();
    menu.addAction(&removeAction);
    menu.addSeparator();
    menu.addMenu(&groupMenu);

    if (m_channelList->currentItem() == NULL)
    {
        copyAction.setEnabled(false);
        removeAction.setEnabled(false);
    }

    if (_app->copyChannel() == NULL)
        pasteAction.setEnabled(false);

    QAction* selectedAction = menu.exec(QCursor::pos());
    if (selectedAction == NULL)
        return;
    else if (selectedAction->text() == tr("Edit"))
        slotEditChannel();
    else if (selectedAction->text() == tr("Copy"))
        slotCopyChannel();
    else if (selectedAction->text() == tr("Paste"))
        slotPasteChannel();
    else if (selectedAction->text() == tr("Remove"))
        slotRemoveChannel();
    else
    {
        /* Group menu hook */
        QLCChannel* ch = NULL;
        QTreeWidgetItem* node = NULL;

        ch = currentChannel();
        if (ch != NULL)
            ch->setGroup(QLCChannel::stringToGroup(selectedAction->text()));
        node = m_channelList->currentItem();
        if (node != NULL)
            node->setText(CH_COL_GRP, selectedAction->text());
        setModified();
    }
}
Пример #2
0
void HistoryDialog::contextMenu(QPoint point)
{
  mContextIndex = ui->tableView->indexAt(point);;

  QMenu contextMenu(ui->tableView);

  QAction copyAction((mContextIndex.column() == 0) ? tr("Copy Path") : tr("Copy URL"), &contextMenu);
  connect(&copyAction, SIGNAL(triggered()), this, SLOT(copy()));
  contextMenu.addAction(&copyAction);

  QAction deleteAction(tr("Delete from imgur.com"), &contextMenu);
  QAction locationAction(tr("Open Location"), &contextMenu);

  QAction removeAction(tr("Remove history entry"), &contextMenu);

  if (mContextIndex.data().toString().isEmpty()) {
    copyAction.setEnabled(false);
    deleteAction.setEnabled(false);
  }

  if (mContextIndex.column() == 0) {
    connect(&locationAction, SIGNAL(triggered()), this, SLOT(location()));
    contextMenu.addAction(&locationAction);
  }
  else {
    connect(&deleteAction, SIGNAL(triggered()), this, SLOT(deleteImage()));
    contextMenu.addAction(&deleteAction);
  }

  connect(&removeAction, SIGNAL(triggered()), this, SLOT(removeHistoryEntry()));
  contextMenu.addAction(&removeAction);
  contextMenu.exec(QCursor::pos());
}
Пример #3
0
void QsciEditor::setupActions() {

	cutAct = new QAction( QIcon::fromTheme( "edit-cut" ), "Cu&t", this );
	cutAct->setStatusTip( "Cut the selected text" );
	cutAct->setShortcut( tr( "Ctrl+X" ) );

	copyAct = new QAction( QIcon::fromTheme( "edit-copy" ), "&Copy", this );
	copyAct->setStatusTip( "Copy the selected text" );
	copyAct->setShortcut( tr( "Ctrl+C" ) );

	pasteAct = new QAction( QIcon::fromTheme( "edit-paste" ), "&Paste", this );
	pasteAct->setStatusTip( "Paste the text on the clipboard" );
	pasteAct->setShortcut( tr( "Ctrl+V" ) );

	deleteAct = new QAction( QIcon::fromTheme( "edit-delete" ), "&Delete", this );
	deleteAct->setStatusTip( "Delete the selected Text" );
	deleteAct->setShortcut( tr( "Delete" ) );

	selectAct = new QAction( QIcon::fromTheme( "edit-select-all" ), "Select &All", this );
	selectAct->setStatusTip( "Select all the text" );
	selectAct->setShortcut( tr( "Ctrl+A" ) );

	deselectAct = new QAction( QIcon(), "Deselect &All", this );
	deselectAct->setStatusTip( "Deselect all the text" );
	deselectAct->setShortcut( tr( "Ctrl+Shift+A" ) );

	undoAct = new QAction( QIcon::fromTheme( "edit-undo" ), "&Undo", this );
	undoAct->setStatusTip( "Undo the last change" );
	undoAct->setShortcut( tr( "Ctrl+Z" ) );

	redoAct = new QAction( QIcon::fromTheme( "edit-redo" ), "&Redo", this );
	redoAct->setStatusTip( "Redo the undone change" );
	redoAct->setShortcut( tr( "Ctrl+Y" ) );

	searchAct = new QAction( QIcon::fromTheme( "edit-find" ), "&Search", this );
	searchAct->setStatusTip( "Search the document" );
	searchAct->setShortcut( tr( "Ctrl+F" ) );

	replaceAct = new QAction( QIcon::fromTheme( "edit-find-replace" ), "&Replace", this );
	replaceAct->setStatusTip( "Replace text in the document" );
	replaceAct->setShortcut( tr( "Ctrl+R" ) );

	changeFontAct = new QAction( QIcon::fromTheme( "preferences-desktop-font" ), "Change &Font", this );
	changeFontAct->setStatusTip( "Change the font of the document" );
	changeFontAct->setShortcut( tr( "Ctrl+Shift+F" ) );

	toggleCaseAct = new QAction( "T&oggle Case of Selection", this );
	toggleCaseAct->setStatusTip( "Toggle the case of the selected text" );
	toggleCaseAct->setShortcut( tr( "Ctrl+Alt+U" ) );

	connect( this, SIGNAL( customContextMenuRequested( const QPoint& ) ), this, SLOT( showCustomMenu( const QPoint& ) ) );

	connect( cutAct, SIGNAL( triggered() ), this, SLOT( cutAction() ) );
	connect( copyAct, SIGNAL( triggered() ), this, SLOT( copyAction() ) );
	connect( pasteAct, SIGNAL( triggered() ), this, SLOT( pasteAction() ) );
	connect( deleteAct, SIGNAL( triggered() ), this, SLOT( deleteAction() ) );

	connect( undoAct, SIGNAL( triggered() ), this, SLOT( undoAction() ) );
	connect( redoAct, SIGNAL( triggered() ), this, SLOT( redoAction() ) );

	connect( selectAct, SIGNAL( triggered() ), this, SLOT( selectAction() ) );
	connect( deselectAct, SIGNAL( triggered() ), this, SLOT( deselectAction() ) );

	connect( changeFontAct, SIGNAL( triggered() ), this, SLOT( changeFont() ) );
	connect( toggleCaseAct, SIGNAL( triggered() ), this, SLOT( toggleCase() ) );

	connect( searchAct, SIGNAL( triggered() ), this, SLOT( showSearch() ) );
	connect( this, SIGNAL( linesChanged() ), this, SLOT( resizeMargins() ) );

	addAction( cutAct );
	addAction( copyAct );
	addAction( pasteAct );
	addAction( deleteAct );
	addAction( selectAct );
	addAction( deselectAct );
	addAction( undoAct );
	addAction( redoAct );
	addAction( searchAct );
	addAction( replaceAct );
	addAction( changeFontAct );
	addAction( toggleCaseAct );

	/* Change keyBindings */
	SendScintilla( SCI_ASSIGNCMDKEY, SCK_DOWN + ( SCMOD_CTRL << 16 ), SCI_PARADOWN );
	SendScintilla( SCI_ASSIGNCMDKEY, SCK_UP + ( SCMOD_CTRL << 16 ), SCI_PARAUP );
	SendScintilla( SCI_ASSIGNCMDKEY, SCK_DOWN + ( SCMOD_ALT << 16 ), SCI_LINESCROLLDOWN );
	SendScintilla( SCI_ASSIGNCMDKEY, SCK_UP + ( SCMOD_ALT << 16 ), SCI_LINESCROLLUP );

	/* Remove Ctrl+D as duplicate line */
	SendScintilla( SCI_CLEARCMDKEY, 68 + ( SCMOD_CTRL << 16 ) );
};
Пример #4
0
void startBackup(COptions options)
{
	GUID snapshotSetId = GUID_NULL;
	bool bSnapshotCreated = false;
	bool bAbnormalAbort = true;
	CComPtr<IVssBackupComponents> pBackupComponents;

	int fileCount = 0;
	LONGLONG byteCount = 0;
	int directoryCount = 0;
	int skipCount = 0;
	SYSTEMTIME startTime;
	
	try
	{
		OutputWriter::SetVerbosityLevel((VERBOSITY_LEVEL)options.get_VerbosityLevel());

		//for (int i = 0; i < argc; ++i)
		//{
		//	CString message;
		//	message.AppendFormat(TEXT("Argument %d: %s"), i, argv[i]);
		//	OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_IF_VERBOSE);
		//}

		OutputWriter::WriteLine(TEXT("Calling CoInitialize"));
		CHECK_HRESULT(::CoInitialize(NULL));
		CHECK_HRESULT(
			::CoInitializeSecurity(
			NULL,
			-1,
			NULL,
			NULL,
			RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
			RPC_C_IMP_LEVEL_IDENTIFY,
			NULL,
			EOAC_NONE,
			NULL));

		::GetSystemTime(&startTime);
		CString startTimeString;
		Utilities::FormatDateTime(&startTime, TEXT(" "), false, startTimeString);

		CString message;
		message.AppendFormat(TEXT("Starting a %s copy from %s to %s"),
			options.get_BackupType() == VSS_BT_FULL ? TEXT("full") : TEXT("incremental"),
			options.get_Source(),
			options.get_Destination());
		OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL);

			if (options.get_ClearDestination())
			{
				if (!Utilities::DirectoryExists(options.get_Destination()))
				{
					CString message;
					message.AppendFormat(TEXT("Skipping recursive delete of destination directory %s because it appears not to exist."),
						options.get_Destination());
					OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL);
				}
				else
				{
					CString message;
					message.AppendFormat(TEXT("Recursively deleting destination directory %s."),
						options.get_Destination());
					OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL);

					bool doDelete = options.get_AcceptAll();

					if (!doDelete)
					{
						if (Confirm(message))
						{
							doDelete = true;
						}
						else
						{
							OutputWriter::WriteLine(TEXT("Aborting backup."), VERBOSITY_THRESHOLD_NORMAL);
							return;
						}
					}

					if (doDelete)
					{
						DeleteRecursive(options.get_Destination(), options.get_IgnorePattern());
					}
				}
			}

			CBackupState backupState;

			LPSYSTEMTIME lastBackupTime;

			if (options.get_BackupType() == VSS_BT_INCREMENTAL)
			{
				backupState.Load(options.get_StateFile());

				LPSYSTEMTIME lastFullBackupTime = backupState.get_LastFullBackupTime();
				LPSYSTEMTIME lastIncrementalBackupTime = backupState.get_LastIncrementalBackupTime();
				if (lastIncrementalBackupTime != NULL)
				{
					lastBackupTime = lastIncrementalBackupTime;
				}
				else
				{
					lastBackupTime = lastFullBackupTime;
				}
			}


			OutputWriter::WriteLine(TEXT("Calling CreateVssBackupComponents"));
			CHECK_HRESULT(::CreateVssBackupComponents(&pBackupComponents));

			OutputWriter::WriteLine(TEXT("Calling InitializeForBackup"));
			CHECK_HRESULT(pBackupComponents->InitializeForBackup());

			CComPtr<IVssAsync> pWriterMetadataStatus;

			OutputWriter::WriteLine(TEXT("Calling GatherWriterMetadata"));
			CHECK_HRESULT(pBackupComponents->GatherWriterMetadata(&pWriterMetadataStatus));

			OutputWriter::WriteLine(TEXT("Waiting for call to GatherWriterMetadata to finish..."));
			CHECK_HRESULT(pWriterMetadataStatus->Wait());

			HRESULT hrGatherStatus;
			OutputWriter::WriteLine(TEXT("Calling QueryStatus for GatherWriterMetadata"));
			CHECK_HRESULT(pWriterMetadataStatus->QueryStatus(&hrGatherStatus, NULL));

			if (hrGatherStatus == VSS_S_ASYNC_CANCELLED)
			{
				throw new CVSSCopyException(L"GatherWriterMetadata was cancelled.");
			}

			OutputWriter::WriteLine(TEXT("Call to GatherWriterMetadata finished."));


			OutputWriter::WriteLine(TEXT("Calling GetWriterMetadataCount"));

			vector<CWriter> writers;

			UINT cWriters;
			CHECK_HRESULT(pBackupComponents->GetWriterMetadataCount(&cWriters));

			for (UINT iWriter = 0; iWriter < cWriters; ++iWriter)
			{
				CWriter writer;
				CComPtr<IVssExamineWriterMetadata> pExamineWriterMetadata;
				GUID id;
				OutputWriter::WriteLine(TEXT("Calling GetWriterMetadata"));
				CHECK_HRESULT(pBackupComponents->GetWriterMetadata(iWriter, &id, &pExamineWriterMetadata));
				GUID idInstance;
				GUID idWriter;
				BSTR bstrWriterName;
				VSS_USAGE_TYPE usage;
				VSS_SOURCE_TYPE source;
				CHECK_HRESULT(pExamineWriterMetadata->GetIdentity(&idInstance, &idWriter, &bstrWriterName, &usage, &source));

				writer.set_InstanceId(idInstance);
				writer.set_Name(bstrWriterName);
				writer.set_WriterId(idWriter);

				CComBSTR writerName(bstrWriterName);
				CString message;
				message.AppendFormat(TEXT("Writer %d named %s"), iWriter, (LPCTSTR)writerName);
				OutputWriter::WriteLine(message);

				UINT cIncludeFiles;
				UINT cExcludeFiles;
				UINT cComponents;
				CHECK_HRESULT(pExamineWriterMetadata->GetFileCounts(&cIncludeFiles, &cExcludeFiles, &cComponents));

				message.Empty();
				message.AppendFormat(TEXT("Writer has %d components"), cComponents);
				OutputWriter::WriteLine(message);

				for (UINT iComponent = 0; iComponent < cComponents; ++iComponent)
				{
					CWriterComponent component;

					CComPtr<IVssWMComponent> pComponent;
					CHECK_HRESULT(pExamineWriterMetadata->GetComponent(iComponent, &pComponent));

					PVSSCOMPONENTINFO pComponentInfo;
					CHECK_HRESULT(pComponent->GetComponentInfo(&pComponentInfo));

					CString message;
					message.AppendFormat(TEXT("Component %d is named %s, has a path of %s, and is %sselectable for backup. %d files, %d databases, %d log files."),
						iComponent,
						pComponentInfo->bstrComponentName,
						pComponentInfo->bstrLogicalPath,
						pComponentInfo->bSelectable ? TEXT("") : TEXT("not "),
						pComponentInfo->cFileCount,
						pComponentInfo->cDatabases,
						pComponentInfo->cLogFiles);
					OutputWriter::WriteLine(message);

					component.set_LogicalPath(pComponentInfo->bstrLogicalPath);
					component.set_SelectableForBackup(pComponentInfo->bSelectable);
					component.set_Writer(iWriter);
					component.set_Name(pComponentInfo->bstrComponentName);
					component.set_Type(pComponentInfo->type);

					for (UINT iFile = 0; iFile < pComponentInfo->cFileCount; ++iFile)
					{
						CComPtr<IVssWMFiledesc> pFileDesc;
						CHECK_HRESULT(pComponent->GetFile(iFile, &pFileDesc));

						CComBSTR bstrPath;
						CHECK_HRESULT(pFileDesc->GetPath(&bstrPath));

						CComBSTR bstrFileSpec;
						CHECK_HRESULT(pFileDesc->GetFilespec(&bstrFileSpec));

						CString message;
						message.AppendFormat(TEXT("File %d has path %s\\%s"), iFile, bstrPath, bstrFileSpec);
						OutputWriter::WriteLine(message);
					}

					for (UINT iDatabase = 0; iDatabase < pComponentInfo->cDatabases; ++iDatabase)
					{
						CComPtr<IVssWMFiledesc> pFileDesc;
						CHECK_HRESULT(pComponent->GetDatabaseFile(iDatabase, &pFileDesc));

						CComBSTR bstrPath;
						CHECK_HRESULT(pFileDesc->GetPath(&bstrPath));

						CComBSTR bstrFileSpec;
						CHECK_HRESULT(pFileDesc->GetFilespec(&bstrFileSpec));

						CString message;
						message.AppendFormat(TEXT("Database file %d has path %s\\%s"), iDatabase, bstrPath, bstrFileSpec);
						OutputWriter::WriteLine(message);
					}

					for (UINT iDatabaseLogFile = 0; iDatabaseLogFile < pComponentInfo->cLogFiles; ++iDatabaseLogFile)
					{
						CComPtr<IVssWMFiledesc> pFileDesc;
						CHECK_HRESULT(pComponent->GetDatabaseLogFile(iDatabaseLogFile, &pFileDesc));

						CComBSTR bstrPath;
						CHECK_HRESULT(pFileDesc->GetPath(&bstrPath));

						CComBSTR bstrFileSpec;
						CHECK_HRESULT(pFileDesc->GetFilespec(&bstrFileSpec));

						CString message;
						message.AppendFormat(TEXT("Database log file %d has path %s\\%s"), iDatabaseLogFile, bstrPath, bstrFileSpec);
						OutputWriter::WriteLine(message);
					}

					CHECK_HRESULT(pComponent->FreeComponentInfo(pComponentInfo));

					writer.get_Components().push_back(component);

				}

				writer.ComputeComponentTree();

				for (unsigned int iComponent = 0; iComponent < writer.get_Components().size(); ++iComponent)
				{
					CWriterComponent& component = writer.get_Components()[iComponent];
					CString message;
					message.AppendFormat(TEXT("Component %d has name %s, path %s, is %sselectable for backup, and has parent %s"),
						iComponent,
						component.get_Name(),
						component.get_LogicalPath(),
						component.get_SelectableForBackup() ? TEXT("") : TEXT("not "),
						component.get_Parent() == NULL ? TEXT("(no parent)") : component.get_Parent()->get_Name());
					OutputWriter::WriteLine(message);
				}

				writers.push_back(writer);
			}

			OutputWriter::WriteLine(TEXT("Calling StartSnapshotSet"));
			CHECK_HRESULT(pBackupComponents->StartSnapshotSet(&snapshotSetId));

			OutputWriter::WriteLine(TEXT("Calling GetVolumePathName"));
			WCHAR wszVolumePathName[MAX_PATH];
			BOOL bWorked = ::GetVolumePathName(options.get_Source(), wszVolumePathName, MAX_PATH);

			if (!bWorked)
			{
				DWORD error = ::GetLastError();
				CString errorMessage;
				Utilities::FormatErrorMessage(error, errorMessage);
				CString message;
				message.AppendFormat(TEXT("There was an error retrieving the volume name from the path. Path: %s Error: %s"),
					options.get_Source(), errorMessage);
				throw new CVSSCopyException(message.GetString());
			}

			OutputWriter::WriteLine(TEXT("Calling AddToSnapshotSet"));
			GUID snapshotId;
			CHECK_HRESULT(pBackupComponents->AddToSnapshotSet(wszVolumePathName, GUID_NULL, &snapshotId));

			for (unsigned int iWriter = 0; iWriter < writers.size(); ++iWriter)
			{
				CWriter writer = writers[iWriter];

				CString message;
				message.AppendFormat(TEXT("Adding components to snapshot set for writer %s"), writer.get_Name());
				OutputWriter::WriteLine(message);
				for (unsigned int iComponent = 0; iComponent < writer.get_Components().size(); ++iComponent)
				{
					CWriterComponent component = writer.get_Components()[iComponent];

					if (ShouldAddComponent(component))
					{
						CString message;
						message.AppendFormat(TEXT("Adding component %s (%s) from writer %s"),
							component.get_Name(),
							component.get_LogicalPath(),
							writer.get_Name());
						OutputWriter::WriteLine(message);
						CHECK_HRESULT(pBackupComponents->AddComponent(
							writer.get_InstanceId(),
							writer.get_WriterId(),
							component.get_Type(),
							component.get_LogicalPath(),
							component.get_Name()
							));
					}
					else
					{
						CString message;
						message.AppendFormat(TEXT("Not adding component %s from writer %s."),
							component.get_Name(), writer.get_Name());
						OutputWriter::WriteLine(message);
					}
				}
			}

			OutputWriter::WriteLine(TEXT("Calling SetBackupState"));
			// Issue #29: trying to figure out if using VSS_BT_INCREMENTAL causes a problem
			CHECK_HRESULT(pBackupComponents->SetBackupState(TRUE, FALSE, VSS_BT_FULL, FALSE));

			OutputWriter::WriteLine(TEXT("Calling PrepareForBackup"));
			CComPtr<IVssAsync> pPrepareForBackupResults;
			CHECK_HRESULT(pBackupComponents->PrepareForBackup(&pPrepareForBackupResults));

			OutputWriter::WriteLine(TEXT("Waiting for call to PrepareForBackup to finish..."));
			CHECK_HRESULT(pPrepareForBackupResults->Wait());

			HRESULT hrPrepareForBackupResults;
			CHECK_HRESULT(pPrepareForBackupResults->QueryStatus(&hrPrepareForBackupResults, NULL));

			if (hrPrepareForBackupResults != VSS_S_ASYNC_FINISHED)
			{
				throw new CVSSCopyException(TEXT("Prepare for backup failed."));
			}

			OutputWriter::WriteLine(TEXT("Call to PrepareForBackup finished."));

			SYSTEMTIME snapshotTime;
			::GetSystemTime(&snapshotTime);

			bWorked = ::SetConsoleCtrlHandler(CtrlHandler, TRUE);

			if (!bWorked)
			{
				OutputWriter::WriteLine(TEXT("Unable to set control handler. Ctrl-C and Ctrl-Break may have undesirable results."),
					VERBOSITY_THRESHOLD_NORMAL);
			}

			if (!options.get_Simulate())
			{
				OutputWriter::WriteLine(TEXT("Calling DoSnapshotSet"));
				CComPtr<IVssAsync> pDoSnapshotSetResults;
				CHECK_HRESULT(pBackupComponents->DoSnapshotSet(&pDoSnapshotSetResults));

				OutputWriter::WriteLine(TEXT("Waiting for call to DoSnapshotSet to finish..."));

				CHECK_HRESULT(pDoSnapshotSetResults->Wait());

				bSnapshotCreated = true;

				if (s_cancel)
				{
					throw new CVSSCopyException(TEXT("Processing was cancelled by control-c, control-break, or a shutdown event. Terminating."));
				}

				bWorked = ::SetConsoleCtrlHandler(CtrlHandler, FALSE);

				if (!bWorked)
				{
					OutputWriter::WriteLine(TEXT("Unable to reset control handler. Ctrl-C and Ctrl-Break may have undesirable results."), VERBOSITY_THRESHOLD_NORMAL);
				}

				HRESULT hrDoSnapshotSetResults;
				CHECK_HRESULT(pDoSnapshotSetResults->QueryStatus(&hrDoSnapshotSetResults, NULL));

				if (hrDoSnapshotSetResults != VSS_S_ASYNC_FINISHED)
				{
					throw new CVSSCopyException(L"DoSnapshotSet failed.");
				}

				OutputWriter::WriteLine(TEXT("Call to DoSnapshotSet finished."));

				OutputWriter::WriteLine(TEXT("Calling GetSnapshotProperties"));
				VSS_SNAPSHOT_PROP snapshotProperties;
				CHECK_HRESULT(pBackupComponents->GetSnapshotProperties(snapshotId, &snapshotProperties));

				OutputWriter::WriteLine(TEXT("Calling CalculateSourcePath"));
				// TODO: We'll eventually have to deal with mount points
				CString wszSource;
				CalculateSourcePath(
					snapshotProperties.m_pwszSnapshotDeviceObject,
					options.get_Source(),
					wszVolumePathName,
					wszSource
					);

				message.Empty();
				message.AppendFormat(TEXT("Recursively creating destination directory %s."),
					options.get_Destination());
				OutputWriter::WriteLine(message);

				Utilities::CreateDirectory(options.get_Destination());

				OutputWriter::WriteLine(TEXT("Calling CopyRecursive"));

				vector<CCopyFilter*> filters;

				if (options.get_BackupType() == VSS_BT_FULL)
				{
					filters.push_back(new CIncludeAllCopyFilter());
				}
				else if (options.get_BackupType() == VSS_BT_INCREMENTAL)
				{
					filters.push_back(new CModifiedSinceCopyFilter(lastBackupTime, options.get_SkipDenied()));
				}

				filters.push_back(new CFilespecCopyFilter(options.get_Filespecs()));

				CCopyAction copyAction(wszSource, options.get_Destination(), options.get_SkipDenied(), filters);
				ProcessDirectory(wszSource, copyAction, TEXT(""), options.get_Recursive(), options.get_IgnorePattern());

				for (unsigned int iFilter = 0; iFilter < filters.size(); ++iFilter)
				{
					delete filters[iFilter];
				}

				fileCount = copyAction.get_FileCount();
				directoryCount = copyAction.get_DirectoryCount();
				skipCount = copyAction.get_SkipCount();
				byteCount = copyAction.get_ByteCount();

				OutputWriter::WriteLine(TEXT("Calling BackupComplete"));
				CComPtr<IVssAsync> pBackupCompleteResults;
				CHECK_HRESULT(pBackupComponents->BackupComplete(&pBackupCompleteResults));

				OutputWriter::WriteLine(TEXT("Waiting for call to BackupComplete to finish..."));
				CHECK_HRESULT(pBackupCompleteResults->Wait());

				HRESULT hrBackupCompleteResults;
				CHECK_HRESULT(pBackupCompleteResults->QueryStatus(&hrBackupCompleteResults, NULL));

				if (hrBackupCompleteResults != VSS_S_ASYNC_FINISHED)
				{
					throw new CVSSCopyException(TEXT("Completion of backup failed."));
				}

				OutputWriter::WriteLine(TEXT("Call to BackupComplete finished."));

				bAbnormalAbort = false;

				if (options.get_StateFile() != NULL)
				{
					OutputWriter::WriteLine(TEXT("Calling SaveAsXML"));
					CComBSTR bstrBackupDocument;
					CHECK_HRESULT(pBackupComponents->SaveAsXML(&bstrBackupDocument));

					if (options.get_BackupType() == VSS_BT_FULL)
					{
						backupState.set_LastFullBackupTime(&snapshotTime);
					}
					else if (options.get_BackupType() == VSS_BT_INCREMENTAL)
					{
						backupState.set_LastIncrementalBackupTime(&snapshotTime);
					}
					else
					{
						throw new CVSSCopyException(TEXT("Unsupported backup type."));
					}

					backupState.Save(options.get_StateFile(), bstrBackupDocument);
				}
			}
		}
		catch (CComException* e)
		{
			Cleanup(bAbnormalAbort, bSnapshotCreated, pBackupComponents, snapshotSetId);
			CString message;
			CString file;
			e->get_File(file);
			message.Format(TEXT("There was a COM failure 0x%x - %s (%d)"),
				e->get_Hresult(), file, e->get_Line());
			OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_UNLESS_SILENT);
			return;
		}
		catch (CVSSCopyException* e)
		{
			Cleanup(bAbnormalAbort, bSnapshotCreated, pBackupComponents, snapshotSetId);
			OutputWriter::WriteLine(e->get_Message(), VERBOSITY_THRESHOLD_UNLESS_SILENT);
			return;
		}
		catch (CParseOptionsException* e)
		{
			Cleanup(bAbnormalAbort, bSnapshotCreated, pBackupComponents, snapshotSetId);
			CString message;
			message.AppendFormat(TEXT("Error: %s\n"), e->get_Message());
			OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_UNLESS_SILENT);
			OutputWriter::WriteLine(COptions::get_Usage(), VERBOSITY_THRESHOLD_UNLESS_SILENT);
			return;
		}

		Cleanup(false, bSnapshotCreated, pBackupComponents, snapshotSetId);
		OutputWriter::WriteLine(TEXT("Backup successfully completed."), VERBOSITY_THRESHOLD_UNLESS_SILENT);

		CString message;
		CString startTimeStringLocal;
		Utilities::FormatDateTime(&startTime, TEXT(" "), true, startTimeStringLocal);
		CString finishTimeString;
		SYSTEMTIME finishTime;
		::GetSystemTime(&finishTime);
		Utilities::FormatDateTime(&finishTime, TEXT(" "), true, finishTimeString);
		message.AppendFormat(TEXT("Backup started at %s, completed at %s."),
			startTimeStringLocal, finishTimeString);
		OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL);
		message.Empty();

		float unitCount = (float)byteCount;
		LPCTSTR units = TEXT("bytes");

		if (unitCount > 1024)
		{
			unitCount = unitCount / 1024.0F;
			units = TEXT("KB");
		}

		if (unitCount > 1024)
		{
			unitCount = unitCount / 1024.0F;
			units = TEXT("MB");
		}

		if (unitCount > 1024)
		{
			unitCount = unitCount / 1024.0F;
			units = TEXT("GB");
		}

		message.AppendFormat(TEXT("%d files (%.2f %s, %d directories) copied, %d files skipped"),
			fileCount, unitCount, units, directoryCount, skipCount);
		OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL);

		OutputWriter::SetVerbosityLevel((VERBOSITY_LEVEL)options.get_VerbosityLevel());

		//for (int i = 0; i < argc; ++i)
		//{
		//	CString message;
		//	message.AppendFormat(TEXT("Argument %d: %s"), i, argv[i]);
		//	OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_IF_VERBOSE);
		//}
}