diff --git a/PInvoke/VssApi/AssemblyInfo.cpp b/PInvoke/VssApi/AssemblyInfo.cpp new file mode 100644 index 00000000..a21ff1c2 --- /dev/null +++ b/PInvoke/VssApi/AssemblyInfo.cpp @@ -0,0 +1,20 @@ +#include "pch.h" + +using namespace System; +using namespace System::Reflection; +using namespace System::Runtime::CompilerServices; +using namespace System::Runtime::InteropServices; +using namespace System::Security::Permissions; + +[assembly:AssemblyTitleAttribute(L"VssApi")]; +[assembly:AssemblyDescriptionAttribute(L"")]; +[assembly:AssemblyConfigurationAttribute(L"")]; +[assembly:AssemblyCompanyAttribute(L"")]; +[assembly:AssemblyProductAttribute(L"VssApi")]; +[assembly:AssemblyCopyrightAttribute(L"Copyright (c) 2021")]; +[assembly:AssemblyTrademarkAttribute(L"")]; +[assembly:AssemblyCultureAttribute(L"")]; + +[assembly:AssemblyVersionAttribute("1.0.*")]; + +[assembly:ComVisible(false)]; diff --git a/PInvoke/VssApi/BaseWrapper.h b/PInvoke/VssApi/BaseWrapper.h new file mode 100644 index 00000000..05e6cea1 --- /dev/null +++ b/PInvoke/VssApi/BaseWrapper.h @@ -0,0 +1,25 @@ +#pragma once + +using namespace System; + +template +ref class BaseWrapper : MarshalByRefObject +{ +protected: + T* pNative; +public: + BaseWrapper(T* ptr) : pNative(ptr) {} + ~BaseWrapper() { this->!BaseWrapper(); } + !BaseWrapper() { if (pNative) { pNative->Release(); pNative = nullptr; } } +}; + +template +ref class BaseClassWrapper : MarshalByRefObject +{ +protected: + T* pNative; +public: + BaseClassWrapper(T* ptr) : pNative(ptr) {} + ~BaseClassWrapper() { this->!BaseClassWrapper(); } + !BaseClassWrapper() { if (pNative) { delete pNative; pNative = nullptr; } } +}; \ No newline at end of file diff --git a/PInvoke/VssApi/CliLists.h b/PInvoke/VssApi/CliLists.h new file mode 100644 index 00000000..ef926c9d --- /dev/null +++ b/PInvoke/VssApi/CliLists.h @@ -0,0 +1,70 @@ +#pragma once + +using namespace System; +using namespace System::Collections::Generic; + +delegate int GetCount(); + +generic +delegate T GetValue(int index); + +generic +delegate void AddValue(T value); + +template +ref class IEnumeratorImpl; + +template +ref class ListImplBase : IReadOnlyList +{ +protected: + GetCount^ getCount; + GetValue^ getValue; + + virtual System::Collections::IEnumerator^ ObjGetEnum() = System::Collections::IEnumerable::GetEnumerator{ return GetEnumerator(); } +public: + ListImplBase(GetCount^ gc, GetValue^ gv) : getCount(gc), getValue(gv) { } + ~ListImplBase() {} + !ListImplBase() { getCount = nullptr; getValue = nullptr; } + + virtual property int Count { int get() { return getCount(); } } + virtual property T default[Int32] { T get(Int32 index) { return getValue(index); } } + virtual System::Collections::Generic::IEnumerator^ GetEnumerator() + { + return gcnew ListEnumerator(this); + } +}; + +template +ref class AppendOnlyList : public ListImplBase, public Vanara::PInvoke::VssApi::IAppendOnlyList +{ +protected: + AddValue^ addValue; + +public: + AppendOnlyList(GetCount^ gc, GetValue^ gv, AddValue^ add) : + ListImplBase(gc, gv), addValue(add) {} + ~AppendOnlyList() {} + !AppendOnlyList() { addValue = nullptr; } + + virtual void Add(T item) { addValue(item); } +}; + +template +ref class ListEnumerator : public IEnumerator +{ +protected: + ListImplBase^ list; + + int i; +public: + ListEnumerator(ListImplBase^ l) : list(l), i(0) { } + ~ListEnumerator() {} + !ListEnumerator() { list = nullptr; } + + virtual property T Current { T get() { return list->default[i]; } } + virtual bool MoveNext() { return i++ <= list->Count; } + virtual void Reset() { i = 0; } +private: + property Object^ ObjectCurrent { virtual Object^ get() sealed = System::Collections::IEnumerator::Current::get{ return Current; } }; +}; diff --git a/PInvoke/VssApi/Macros.h b/PInvoke/VssApi/Macros.h new file mode 100644 index 00000000..b2ce2831 --- /dev/null +++ b/PInvoke/VssApi/Macros.h @@ -0,0 +1,85 @@ +#define DECL_WRAPPER_PROP(prop, rtype) \ + property rtype prop { virtual rtype get(); } + +#define DEFINE_WRAPPER_PROPC(prop, rtype, gtype, meth, conv) \ + virtual property rtype prop {\ + rtype get() {\ + gtype v;\ + Utils::ThrowIfFailed(pNative->meth(&v));\ + return conv(v);\ + }\ + } + +#define DEFINE_WRAPPER_GS_PROP(prop, rtype, gtype) \ + virtual property rtype prop {\ + rtype get() {\ + gtype v;\ + Utils::ThrowIfFailed(pNative->Get##prop(&v));\ + return static_cast(v);\ + }\ + void set(rtype value) {\ + Utils::ThrowIfFailed(pNative->Set##prop(static_cast(value)));\ + }\ + } + +#define DEFINE_WRAPPER_QI_PROP(prop, rtype, gtype, meth, qitf) \ + virtual property rtype prop {\ + rtype get() {\ + SafeComPtr p = pNative;\ + gtype v;\ + Utils::ThrowIfFailed(p->meth(&v));\ + return static_cast(v);\ + }\ + } + +#define DEFINE_WRAPPER_PROP(prop, rtype, gtype, meth) \ + DEFINE_WRAPPER_PROPC(prop, rtype, gtype, meth, static_cast) + +#define DEFINE_WRAPPER_STRING_PROP(prop, meth) \ + virtual property String^ prop {\ + String^ get() {\ + SafeBSTR v;\ + Utils::ThrowIfFailed(pNative->meth(&v));\ + return (String^)v;\ + }\ + } + +#define DEFINE_WRAPPER_STRING_QI_PROP(prop, meth, qitf) \ + virtual property String^ prop {\ + String^ get() {\ + SafeComPtr p = pNative;\ + SafeBSTR v;\ + Utils::ThrowIfFailed(p->meth(&v));\ + return (String^)v;\ + }\ + } + +#define DEFINE_WRAPPER_STRING_GS_PROP(prop) \ + virtual property String^ prop {\ + String^ get() {\ + SafeBSTR v;\ + Utils::ThrowIfFailed(pNative->Get##prop(&v));\ + return (String^)v;\ + }\ + void set(String^ value) {\ + SafeString v(value);\ + Utils::ThrowIfFailed(pNative->Set##prop(v));\ + }\ + } + +#define DEFINE_WRAPPER_STRING_QI_GS_PROP(prop, qitf) \ + virtual property String^ prop {\ + String^ get() {\ + SafeComPtr p = pNative;\ + SafeBSTR v;\ + Utils::ThrowIfFailed(p->Get##prop(&v));\ + return (String^)v;\ + }\ + void set(String^ value) {\ + SafeComPtr p = pNative;\ + SafeString v(value);\ + Utils::ThrowIfFailed(p->Set##prop(v));\ + }\ + } + +#define mgd_cast(T, t) (T^)Marshal::GetObjectForIUnknown(IntPtr((void*)t)); diff --git a/PInvoke/VssApi/Resource.h b/PInvoke/VssApi/Resource.h new file mode 100644 index 00000000..d5ac7c42 --- /dev/null +++ b/PInvoke/VssApi/Resource.h @@ -0,0 +1,3 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by app.rc diff --git a/PInvoke/VssApi/SafePtr.h b/PInvoke/VssApi/SafePtr.h new file mode 100644 index 00000000..48527bc0 --- /dev/null +++ b/PInvoke/VssApi/SafePtr.h @@ -0,0 +1,53 @@ +#pragma once +#include + +using namespace System; + +template +class SafePointer +{ +protected: + T m_ptr; +public: + SafePointer() : m_ptr(0) { } + SafePointer(T ptr) : m_ptr(ptr) { } + virtual ~SafePointer() { if (m_ptr != 0) { Release(m_ptr); } } + operator T() { return m_ptr; } + T* operator&() { return &m_ptr; } + virtual void Release(T ptr) {}; +}; + +class SafeBSTR : public SafePointer +{ +public: + SafeBSTR() : SafePointer() {} + SafeBSTR(LPWSTR pString) : SafePointer(::SysAllocString(pString)) {} + void Release(BSTR ptr) override { ::SysFreeString(ptr); } + operator String^() { return (m_ptr == 0) ? nullptr : Runtime::InteropServices::Marshal::PtrToStringBSTR((IntPtr)m_ptr); } +}; + +class SafeString : public SafePointer +{ +public: + SafeString(String^ value) : SafePointer((BSTR)Runtime::InteropServices::Marshal::StringToBSTR(value).ToPointer()) {} + void Release(BSTR ptr) override { System::Runtime::InteropServices::Marshal::FreeBSTR((IntPtr)ptr); } + operator String^() { return (m_ptr == 0) ? nullptr : Runtime::InteropServices::Marshal::PtrToStringBSTR((IntPtr)m_ptr); } +}; + +class SafeWString : public SafePointer +{ +public: + SafeWString(String^ value) : SafePointer((LPWSTR)Runtime::InteropServices::Marshal::StringToCoTaskMemUni(value).ToPointer()) {} + void Release(LPWSTR ptr) override { System::Runtime::InteropServices::Marshal::FreeCoTaskMem((IntPtr)ptr); } + operator String^() { return (m_ptr == 0) ? nullptr : Runtime::InteropServices::Marshal::PtrToStringUni((IntPtr)m_ptr); } +}; + +template +class SafeComPtr : public SafePointer +{ +public: + SafeComPtr() : SafePointer() {} + SafeComPtr(IUnknown* pUnk) { Utils::ThrowIfFailed(pUnk->QueryInterface(IID_PPV_ARGS(&m_ptr))); } + void Release(T ptr) override { ((IUnknown*)m_ptr)->Release(); } + T operator->() const { return m_ptr; } +}; diff --git a/PInvoke/VssApi/Utils.h b/PInvoke/VssApi/Utils.h new file mode 100644 index 00000000..b6747bfa --- /dev/null +++ b/PInvoke/VssApi/Utils.h @@ -0,0 +1,69 @@ +#pragma once +#include +#include + +using namespace System; + +ref class Utils sealed +{ +public: + static void ThrowIfFailed(::HRESULT hr) + { + if (hr < 0) + throw gcnew Runtime::InteropServices::COMException(nullptr, hr); + } + + static Guid FromGUID(_GUID& guid) { + return Guid(guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], + guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]); + } + + static _GUID ToGUID(Guid& guid) { + array^ guidData = guid.ToByteArray(); + pin_ptr data = &(guidData[0]); + + return *(_GUID*)data; + } + + static _GUID* ToGUIDArray([System::Runtime::InteropServices::In] array^ input) + { + if (input == nullptr) + return nullptr; + pin_ptr pg = &input[0]; + VSS_ID* buf = new VSS_ID[input->Length]; + for (int i = 0; i < input->Length; i++) + buf[i] = Utils::ToGUID(pg[i]); + return buf; + } + + generic + delegate TOUT Conv(TIN input); + + template + static TOUT* ToNative(array^ input, Conv^ func) + { + if (input == nullptr) + return nullptr; + if (input->Length == 0) + return new TOUT[0]; + pin_ptr pin = &input[0]; + TIN* p = pin; + TOUT* buf = new TOUT[input->Length]; + for (int i = 0; i < input->Len; i++) + { + input[i] = func(pin[i]); + } + return buf; + } +}; + +class SmartGuid +{ +private: + _GUID mGuid; +public: + SmartGuid(_GUID& guid) : mGuid(guid) {} + SmartGuid(Guid& guid) : mGuid(Utils::ToGUID(guid)) {} + operator Guid() { return Utils::FromGUID(mGuid); } + operator _GUID() { return mGuid; } +}; diff --git a/PInvoke/VssApi/VsBackup.cpp b/PInvoke/VssApi/VsBackup.cpp new file mode 100644 index 00000000..7df84c74 --- /dev/null +++ b/PInvoke/VssApi/VsBackup.cpp @@ -0,0 +1,107 @@ +#include "pch.h" +#include "vsbackup.h" +#include "vswriter.h" + +namespace Vanara { namespace PInvoke { namespace VssApi { + + Vanara::PInvoke::VssApi::VSS_COMPONENTINFO CVssWMComponent::GetComponentInfo() { + RefreshInfo(); + return Marshal::PtrToStructure(IntPtr((void*)pInfo)); + } + + void CVssExamineWriterMetadata::RefreshRestoreMethod() + { + ::VSS_RESTOREMETHOD_ENUM eMethod; + SafeBSTR bstrService; + SafeBSTR bstrUserProcedure; + ::VSS_WRITERRESTORE_ENUM eWriterRestore; + bool bRebootRequired; + UINT iMappings; + Utils::ThrowIfFailed(pNative->GetRestoreMethod(&eMethod, &bstrService, &bstrUserProcedure, &eWriterRestore, &bRebootRequired, &iMappings)); + restoreMethod = VSS_RESTORE_METHOD(eMethod, bstrService, bstrUserProcedure, eWriterRestore, bRebootRequired, iMappings); + } + + void CVssExamineWriterMetadata::RefreshFileCounts() + { + pin_ptr pci = &cIncludeFiles; + pin_ptr pce = &cExcludeFiles; + pin_ptr pcc = &cComponents; + Utils::ThrowIfFailed(pNative->GetFileCounts(pci, pce, pcc)); + } + + Version^ CVssExamineWriterMetadata::Version::get() + { + SafeComPtr<::IVssExamineWriterMetadataEx2*> p2 = pNative; + DWORD maj, min; + Utils::ThrowIfFailed(((::IVssExamineWriterMetadataEx2*)p2)->GetVersion(&maj, &min)); + return gcnew System::Version(static_cast(maj), static_cast(min)); + } + + void CVssExamineWriterMetadata::GetIdentity(Guid% pidInstance, Guid% pidWriter, String^% pbstrWriterName, String^% pbstrInstanceName, Vanara::PInvoke::VssApi::VSS_USAGE_TYPE% pUsage, + Vanara::PInvoke::VssApi::VSS_SOURCE_TYPE% pSource) + { + ::VSS_ID inst, writer; + SafeBSTR name; + ::VSS_USAGE_TYPE use; + ::VSS_SOURCE_TYPE src; + Utils::ThrowIfFailed(pNative->GetIdentity(&inst, &writer, &name, &use, &src)); + pidInstance = Utils::FromGUID(inst); + pidWriter = Utils::FromGUID(writer); + pbstrInstanceName = name; + pUsage = static_cast(use); + pSource = static_cast(src); + } + + void CVssExamineWriterMetadata::GetRestoreMethod(Vanara::PInvoke::VssApi::VSS_RESTOREMETHOD_ENUM% pMethod, System::String^% pbstrService, System::String^% pbstrUserProcedure, + Vanara::PInvoke::VssApi::VSS_WRITERRESTORE_ENUM% pwriterRestore, bool% pbRebootRequired, UInt32% pcMappings) + { + RefreshRestoreMethod(); + pMethod = static_cast(restoreMethod.eMethod); + pbstrService = restoreMethod.bstrService; + pbstrUserProcedure = restoreMethod.bstrUserProcedure; + pwriterRestore = static_cast(restoreMethod.eWriterRestore); + pbRebootRequired = restoreMethod.bRebootRequired; + pcMappings = static_cast(restoreMethod.iMappings); + } + + void CVssExamineWriterMetadata::LoadFromXML(String^ bstrXML) + { + SafeString xml = bstrXML; + Utils::ThrowIfFailed(pNative->LoadFromXML(xml)); + } + + String^ CVssExamineWriterMetadata::SaveAsXML() + { + SafeBSTR bstr; + Utils::ThrowIfFailed(pNative->SaveAsXML(&bstr)); + return bstr; + } + + IVssWriterComponentsExt^ VssApi::CVssBackupComponents::GetWriterComponents(int i) + { + ::IVssWriterComponentsExt* p; + Utils::ThrowIfFailed(pNative->GetWriterComponents(i, &p)); + return gcnew CVssWriterComponents(p); + } + + IVssExamineWriterMetadata^ VssApi::CVssBackupComponents::GetWriterMetadata(int i) + { + ::IVssExamineWriterMetadata* p; + VSS_ID id; + Utils::ThrowIfFailed(pNative->GetWriterMetadata(i, &id, &p)); + return gcnew CVssExamineWriterMetadata(p); + } + + VssWriterStatus VssApi::CVssBackupComponents::GetWriterStatus(int i) + { + VSS_ID id, wri; + SafeBSTR swri, msg; + ::VSS_WRITER_STATE stat; + ::HRESULT hr, hrApp; + SafeComPtr<::IVssBackupComponentsEx3*> p = pNative; + Utils::ThrowIfFailed(p->GetWriterStatusEx(i, &id, &wri, &swri, &stat, &hr, &hrApp, &msg)); + VssWriterStatus ret{ Utils::FromGUID(id), Utils::FromGUID(wri), swri, static_cast(stat), (HRESULT)hr, (HRESULT)hrApp, msg }; + return ret; + } + +}}} \ No newline at end of file diff --git a/PInvoke/VssApi/VsBackup.h b/PInvoke/VssApi/VsBackup.h new file mode 100644 index 00000000..6fa4b091 --- /dev/null +++ b/PInvoke/VssApi/VsBackup.h @@ -0,0 +1,434 @@ +#pragma once +#include "pch.h" +#include "vswriter.h" +#include "CliLists.h" + +using namespace System; +using namespace Collections::Generic; +using namespace Runtime::InteropServices; + +namespace Vanara { + namespace PInvoke { + namespace VssApi { + ref class CVssExamineWriterMetadata; + + ref class CVssWMComponent : IVssWMComponent, BaseWrapper<::IVssWMComponent> + { + public: + CVssWMComponent(::IVssWMComponent* ptr) : BaseWrapper(ptr) {} + ~CVssWMComponent() { if (pInfo && pNative) { pin_ptr<::VSS_COMPONENTINFO> p = pInfo; pNative->FreeComponentInfo(p); } } + + virtual VSS_COMPONENTINFO GetComponentInfo(); + +#define DEFINE_WM_COMP_ROLIST(prop, itf, cfield, gfunc, cwrap) \ + private:\ + ListImplBase^ f##prop;\ + int Get##prop##Count() { RefreshInfo(); return pInfo->cfield; }\ + itf^ Get##prop(int i) { ::itf* p; Utils::ThrowIfFailed(pNative->gfunc(i, &p)); return gcnew cwrap(p); }\ + public:\ + property IReadOnlyList^ prop { virtual IReadOnlyList^ get() {\ + if (!f##prop) f##prop = gcnew ListImplBase(gcnew GetCount(this, &CVssWMComponent::Get##prop##Count), gcnew GetValue(this, &CVssWMComponent::Get##prop));\ + return f##prop; } } + + DEFINE_WM_COMP_ROLIST(DatabaseFiles, IVssWMFiledesc, cDatabases, GetDatabaseFile, CVssWMFiledesc) + DEFINE_WM_COMP_ROLIST(Files, IVssWMFiledesc, cFileCount, GetFile, CVssWMFiledesc) + DEFINE_WM_COMP_ROLIST(DatabaseLogFiles, IVssWMFiledesc, cLogFiles, GetDatabaseLogFile, CVssWMFiledesc) + DEFINE_WM_COMP_ROLIST(Dependencies, IVssWMDependency, cDependencies, GetDependency, CVssWMDependency) + + private: + ::VSS_COMPONENTINFO* pInfo; + void RefreshInfo() + { + pin_ptr<::VSS_COMPONENTINFO> p = pInfo; + if (pInfo != nullptr) + pNative->FreeComponentInfo(p); + Utils::ThrowIfFailed(pNative->GetComponentInfo((::PVSSCOMPONENTINFO*)&p)); + } + }; + + ref class CVssBackupComponents : IVssBackupComponents, BaseWrapper<::IVssBackupComponents> + { + public: + CVssBackupComponents(::IVssBackupComponents* ptr) : BaseWrapper(ptr) {} + + virtual void AbortBackup() { Utils::ThrowIfFailed(pNative->AbortBackup()); } + virtual void AddAlternativeLocationMapping(Guid writerId, VSS_COMPONENT_TYPE componentType, [System::Runtime::InteropServices::Optional] String^ wszLogicalPath, + String^ wszComponentName, String^ wszPath, String^ wszFilespec, Boolean bRecursive, String^ wszDestination) + { + Utils::ThrowIfFailed(pNative->AddAlternativeLocationMapping(SmartGuid(writerId), static_cast<::VSS_COMPONENT_TYPE>(componentType), + SafeWString(wszLogicalPath), SafeWString(wszComponentName), SafeWString(wszPath), SafeWString(wszFilespec), bRecursive, SafeWString(wszDestination))); + } + virtual void AddComponent(Guid instanceId, Guid writerId, VSS_COMPONENT_TYPE ct, [System::Runtime::InteropServices::Optional] String^ wszLogicalPath, String^ wszComponentName) + { + Utils::ThrowIfFailed(pNative->AddComponent(SmartGuid(instanceId), SmartGuid(writerId), static_cast<::VSS_COMPONENT_TYPE>(ct), + SafeWString(wszLogicalPath), SafeWString(wszComponentName))); + } + virtual void AddNewTarget(Guid writerId, VSS_COMPONENT_TYPE ct, [System::Runtime::InteropServices::Optional] String^ wszLogicalPath, String^ wszComponentName, String^ wszPath, + String^ wszFileName, Boolean bRecursive, String^ wszAlternatePath) + { + Utils::ThrowIfFailed(pNative->AddNewTarget(SmartGuid(writerId), static_cast<::VSS_COMPONENT_TYPE>(ct), SafeWString(wszLogicalPath), SafeWString(wszComponentName), + SafeWString(wszPath), SafeWString(wszFileName), bRecursive, SafeWString(wszAlternatePath))); + } + virtual void AddRestoreSubcomponent(Guid writerId, VSS_COMPONENT_TYPE componentType, [System::Runtime::InteropServices::Optional] String^ wszLogicalPath, + String^ wszComponentName, String^ wszSubComponentLogicalPath, String^ wszSubComponentName, Boolean bRepair) + { + Utils::ThrowIfFailed(pNative->AddRestoreSubcomponent(SmartGuid(writerId), static_cast<::VSS_COMPONENT_TYPE>(componentType), SafeWString(wszLogicalPath), SafeWString(wszComponentName), + SafeWString(wszSubComponentLogicalPath), SafeWString(wszSubComponentName), bRepair)); + } + virtual void AddSnapshotToRecoverySet(Guid snapshotId, [System::Runtime::InteropServices::Optional] UInt32 dwFlags, [System::Runtime::InteropServices::Optional] String^ pwszDestinationVolume) + { + SafeComPtr<::IVssBackupComponentsEx3*> p = pNative; + Utils::ThrowIfFailed(p->AddSnapshotToRecoverySet(SmartGuid(snapshotId), dwFlags, SafeWString(pwszDestinationVolume))); + } + virtual Guid AddToSnapshotSet(String^ pwszVolumeName, Guid ProviderId) + { + VSS_ID id; + Utils::ThrowIfFailed(pNative->AddToSnapshotSet(SafeWString(pwszVolumeName), SmartGuid(ProviderId), &id)); + return Utils::FromGUID(id); + } + virtual IVssAsync^ BackupComplete() + { + SafeComPtr<::IVssAsync*> pa; + Utils::ThrowIfFailed(pNative->BackupComplete(&pa)); + return mgd_cast(IVssAsync, pa); + } + virtual void BreakSnapshotSet(Guid SnapshotSetId) { Utils::ThrowIfFailed(pNative->BreakSnapshotSet(SmartGuid(SnapshotSetId))); } + virtual IVssAsync^ BreakSnapshotSetEx(Guid SnapshotSetID, VSS_HARDWARE_OPTIONS dwBreakFlags) + { + SafeComPtr<::IVssBackupComponentsEx2*> p = pNative; + SafeComPtr<::IVssAsync*> pa; + Utils::ThrowIfFailed(p->BreakSnapshotSetEx(SmartGuid(SnapshotSetID), static_cast<::VSS_HARDWARE_OPTIONS>(dwBreakFlags), &pa)); + return mgd_cast(IVssAsync, pa); + } + virtual void DeleteSnapshots(Guid SourceObjectId, VSS_OBJECT_TYPE eSourceObjectType, Boolean bForceDelete, [System::Runtime::InteropServices::Out] Int32% plDeletedSnapshots, [System::Runtime::InteropServices::Out] Guid% pNondeletedSnapshotID) + { + LONG dSnap; + GUID sId; + Utils::ThrowIfFailed(pNative->DeleteSnapshots(SmartGuid(SourceObjectId), static_cast<::VSS_OBJECT_TYPE>(eSourceObjectType), bForceDelete, &dSnap, &sId)); + plDeletedSnapshots = dSnap; + pNondeletedSnapshotID = Utils::FromGUID(sId); + } + virtual void DisableWriterClasses([In] array^ rgWriterClassId) + { + if (rgWriterClassId == nullptr || rgWriterClassId->Length == 0) + return; + VSS_ID* buf = Utils::ToGUIDArray(rgWriterClassId); + Utils::ThrowIfFailed(pNative->DisableWriterClasses(buf, rgWriterClassId->Length)); + delete buf; + } + virtual void DisableWriterInstances([In] array^ rgWriterInstanceId) + { + if (rgWriterInstanceId == nullptr || rgWriterInstanceId->Length == 0) + return; + VSS_ID* buf = Utils::ToGUIDArray(rgWriterInstanceId); + Utils::ThrowIfFailed(pNative->DisableWriterInstances(buf, rgWriterInstanceId->Length)); + delete buf; + } + virtual IVssAsync^ DoSnapshotSet() + { + SafeComPtr<::IVssAsync*> pa; + Utils::ThrowIfFailed(pNative->DoSnapshotSet(&pa)); + return mgd_cast(IVssAsync, pa); + } + virtual void EnableWriterClasses([In] array^ rgWriterClassId) + { + if (rgWriterClassId == nullptr || rgWriterClassId->Length == 0) + return; + VSS_ID* buf = Utils::ToGUIDArray(rgWriterClassId); + Utils::ThrowIfFailed(pNative->EnableWriterClasses(buf, rgWriterClassId->Length)); + delete buf; + } + virtual String^ ExposeSnapshot(Guid SnapshotId, [System::Runtime::InteropServices::Optional] String^ wszPathFromRoot, VSS_VOLUME_SNAPSHOT_ATTRIBUTES lAttributes, [System::Runtime::InteropServices::Optional] String^ wszExpose) + { + VSS_PWSZ exp; + Utils::ThrowIfFailed(pNative->ExposeSnapshot(SmartGuid(SnapshotId), SafeWString(wszPathFromRoot), static_cast<::VSS_VOLUME_SNAPSHOT_ATTRIBUTES>(lAttributes), SafeWString(wszExpose), &exp)); + String^ ret = Marshal::PtrToStringUni(IntPtr(exp)); + CoTaskMemFree(exp); + return ret; + } + virtual IVssAsync^ FastRecovery(Guid SnapshotSetID, [System::Runtime::InteropServices::Optional] UInt32 dwFastRecoveryFlags) + { + SafeComPtr<::IVssBackupComponentsEx2*> p = pNative; + SafeComPtr<::IVssAsync*> pa; + Utils::ThrowIfFailed(p->FastRecovery(SmartGuid(SnapshotSetID), dwFastRecoveryFlags, &pa)); + return mgd_cast(IVssAsync, pa); + } + virtual void FreeWriterMetadata() + { + Utils::ThrowIfFailed(pNative->FreeWriterMetadata()); + } + virtual void FreeWriterStatus() + { + Utils::ThrowIfFailed(pNative->FreeWriterStatus()); + } + virtual IVssAsync^ GatherWriterMetadata() + { + SafeComPtr<::IVssAsync*> pa; + Utils::ThrowIfFailed(pNative->GatherWriterMetadata(&pa)); + return mgd_cast(IVssAsync, pa); + } + virtual IVssAsync^ GatherWriterStatus() + { + SafeComPtr<::IVssAsync*> pa; + Utils::ThrowIfFailed(pNative->GatherWriterStatus(&pa)); + return mgd_cast(IVssAsync, pa); + } + virtual void GetRootAndLogicalPrefixPaths(String^ pwszFilePath, [System::Runtime::InteropServices::Out] String^% ppwszRootPath, [System::Runtime::InteropServices::Out] String^% ppwszLogicalPrefix, [System::Runtime::InteropServices::Optional] Boolean bNormalizeFQDNforRootPath) + { + SafeComPtr<::IVssBackupComponentsEx4*> p = pNative; + VSS_PWSZ rPath, lPref; + Utils::ThrowIfFailed(p->GetRootAndLogicalPrefixPaths(SafeWString(pwszFilePath), &rPath, &lPref, bNormalizeFQDNforRootPath)); + } + virtual Guid GetSessionId() + { + SafeComPtr<::IVssBackupComponentsEx3*> p = pNative; + VSS_ID id; + Utils::ThrowIfFailed(p->GetSessionId(&id)); + return Utils::FromGUID(id); + } + virtual VSS_SNAPSHOT_PROP GetSnapshotProperties(Guid SnapshotId) + { + ::VSS_SNAPSHOT_PROP prop; + Utils::ThrowIfFailed(pNative->GetSnapshotProperties(SmartGuid(SnapshotId), &prop)); + return Marshal::PtrToStructure(IntPtr(&prop)); + } + virtual IVssAsync^ ImportSnapshots() + { + SafeComPtr<::IVssAsync*> pa; + Utils::ThrowIfFailed(pNative->ImportSnapshots(&pa)); + return mgd_cast(IVssAsync, pa); + } + virtual void InitializeForBackup([System::Runtime::InteropServices::Optional] String^ bstrXML) + { + Utils::ThrowIfFailed(pNative->InitializeForBackup(SafeWString(bstrXML))); + } + virtual void InitializeForRestore([System::Runtime::InteropServices::Optional] String^ bstrXML) + { + Utils::ThrowIfFailed(pNative->InitializeForRestore(SafeWString(bstrXML))); + } + virtual Boolean IsVolumeSupported(Guid ProviderId, String^ pwszVolumeName) + { + ::BOOL b; + Utils::ThrowIfFailed(pNative->IsVolumeSupported(SmartGuid(ProviderId), SafeWString(pwszVolumeName), &b)); + return b; + } + virtual IVssAsync^ PostRestore() + { + SafeComPtr<::IVssAsync*> pa; + Utils::ThrowIfFailed(pNative->PostRestore(&pa)); + return mgd_cast(IVssAsync, pa); + } + virtual IVssAsync^ PreFastRecovery(Guid SnapshotSetID, [System::Runtime::InteropServices::Optional] UInt32 dwPreFastRecoveryFlags) + { + SafeComPtr<::IVssBackupComponentsEx2*> p = pNative; + SafeComPtr<::IVssAsync*> pa; + Utils::ThrowIfFailed(p->PreFastRecovery(SmartGuid(SnapshotSetID), dwPreFastRecoveryFlags, &pa)); + return mgd_cast(IVssAsync, pa); + } + virtual IVssAsync^ PrepareForBackup() + { + SafeComPtr<::IVssAsync*> pa; + Utils::ThrowIfFailed(pNative->PrepareForBackup(&pa)); + return mgd_cast(IVssAsync, pa); + } + virtual IVssAsync^ PreRestore() + { + SafeComPtr<::IVssAsync*> pa; + Utils::ThrowIfFailed(pNative->PreRestore(&pa)); + return mgd_cast(IVssAsync, pa); + } + virtual IVssEnumObject^ Query(Guid QueriedObjectId, VSS_OBJECT_TYPE eQueriedObjectType, VSS_OBJECT_TYPE eReturnedObjectsType) + { + SafeComPtr<::IVssEnumObject*> pa; + Utils::ThrowIfFailed(pNative->Query(SmartGuid(QueriedObjectId), static_cast<::VSS_OBJECT_TYPE>(eQueriedObjectType), static_cast<::VSS_OBJECT_TYPE>(eReturnedObjectsType), &pa)); + return mgd_cast(IVssEnumObject, pa); + } + virtual IVssAsync^ QueryRevertStatus(String^ pwszVolume) + { + SafeComPtr<::IVssAsync*> pa; + Utils::ThrowIfFailed(pNative->QueryRevertStatus(SafeWString(pwszVolume), &pa)); + return mgd_cast(IVssAsync, pa); + } + virtual IVssAsync^ RecoverSet(VSS_RECOVERY_OPTIONS dwFlags) + { + SafeComPtr<::IVssBackupComponentsEx3*> p = pNative; + SafeComPtr<::IVssAsync*> pa; + Utils::ThrowIfFailed(p->RecoverSet(static_cast<::VSS_RECOVERY_OPTIONS>(dwFlags), &pa)); + return mgd_cast(IVssAsync, pa); + } + virtual void RevertToSnapshot(Guid SnapshotId, Boolean bForceDismount) + { + Utils::ThrowIfFailed(pNative->RevertToSnapshot(SmartGuid(SnapshotId), bForceDismount)); + } + virtual String^ SaveAsXML() + { + SafeBSTR s; + Utils::ThrowIfFailed(pNative->SaveAsXML(&s)); + return s; + } + virtual void SetAdditionalRestores(Guid writerId, VSS_COMPONENT_TYPE ct, [System::Runtime::InteropServices::Optional] String^ wszLogicalPath, String^ wszComponentName, Boolean bAdditionalRestores) + { + Utils::ThrowIfFailed(pNative->SetAdditionalRestores(SmartGuid(writerId), static_cast<::VSS_COMPONENT_TYPE>(ct), SafeWString(wszLogicalPath), SafeWString(wszComponentName), bAdditionalRestores)); + } + virtual void SetAuthoritativeRestore(Guid writerId, VSS_COMPONENT_TYPE ct, [System::Runtime::InteropServices::Optional] String^ wszLogicalPath, String^ wszComponentName, Boolean bAuth) + { + SafeComPtr<::IVssBackupComponentsEx2*> p = pNative; + Utils::ThrowIfFailed(p->SetAuthoritativeRestore(SmartGuid(writerId), static_cast<::VSS_COMPONENT_TYPE>(ct), SafeWString(wszLogicalPath), SafeWString(wszComponentName), bAuth)); + } + virtual void SetBackupOptions(Guid writerId, VSS_COMPONENT_TYPE ct, [System::Runtime::InteropServices::Optional] String^ wszLogicalPath, String^ wszComponentName, String^ wszBackupOptions) + { + Utils::ThrowIfFailed(pNative->SetBackupOptions(SmartGuid(writerId), static_cast<::VSS_COMPONENT_TYPE>(ct), SafeWString(wszLogicalPath), SafeWString(wszComponentName), SafeWString(wszBackupOptions))); + } + virtual void SetBackupState(Boolean bSelectComponents, Boolean bBackupBootableSystemState, VSS_BACKUP_TYPE backupType, [System::Runtime::InteropServices::Optional] Boolean bPartialFileSupport) + { + Utils::ThrowIfFailed(pNative->SetBackupState(bSelectComponents, bBackupBootableSystemState, static_cast<::VSS_BACKUP_TYPE>(backupType), bPartialFileSupport)); + } + virtual void SetBackupSucceeded(Guid instanceId, Guid writerId, VSS_COMPONENT_TYPE ct, [System::Runtime::InteropServices::Optional] String^ wszLogicalPath, String^ wszComponentName, Boolean bSucceded) + { + Utils::ThrowIfFailed(pNative->SetBackupSucceeded(SmartGuid(instanceId), SmartGuid(writerId), static_cast<::VSS_COMPONENT_TYPE>(ct), SafeWString(wszLogicalPath), SafeWString(wszComponentName), bSucceded)); + } + virtual void SetContext(VSS_SNAPSHOT_CONTEXT lContext) + { + Utils::ThrowIfFailed(pNative->SetContext(static_cast<::VSS_SNAPSHOT_CONTEXT>(lContext))); + } + virtual void SetFileRestoreStatus(Guid writerId, VSS_COMPONENT_TYPE ct, [System::Runtime::InteropServices::Optional] String^ wszLogicalPath, String^ wszComponentName, VSS_FILE_RESTORE_STATUS status) + { + Utils::ThrowIfFailed(pNative->SetFileRestoreStatus(SmartGuid(writerId), static_cast<::VSS_COMPONENT_TYPE>(ct), SafeWString(wszLogicalPath), SafeWString(wszComponentName), static_cast<::VSS_FILE_RESTORE_STATUS>(status))); + } + virtual void SetPreviousBackupStamp(Guid writerId, VSS_COMPONENT_TYPE ct, [System::Runtime::InteropServices::Optional] String^ wszLogicalPath, String^ wszComponentName, String^ wszPreviousBackupStamp) + { + Utils::ThrowIfFailed(pNative->SetPreviousBackupStamp(SmartGuid(writerId), static_cast<::VSS_COMPONENT_TYPE>(ct), SafeWString(wszLogicalPath), SafeWString(wszComponentName), SafeWString(wszPreviousBackupStamp))); + } + virtual void SetRangesFilePath(Guid writerId, VSS_COMPONENT_TYPE ct, [System::Runtime::InteropServices::Optional] String^ wszLogicalPath, String^ wszComponentName, UInt32 iPartialFile, String^ wszRangesFile) + { + Utils::ThrowIfFailed(pNative->SetRangesFilePath(SmartGuid(writerId), static_cast<::VSS_COMPONENT_TYPE>(ct), SafeWString(wszLogicalPath), SafeWString(wszComponentName), iPartialFile, SafeWString(wszRangesFile))); + } + virtual void SetRestoreName(Guid writerId, VSS_COMPONENT_TYPE ct, [System::Runtime::InteropServices::Optional] String^ wszLogicalPath, String^ wszComponentName, String^ wszRestoreName) + { + SafeComPtr<::IVssBackupComponentsEx2*> p = pNative; + Utils::ThrowIfFailed(p->SetRestoreName(SmartGuid(writerId), static_cast<::VSS_COMPONENT_TYPE>(ct), SafeWString(wszLogicalPath), SafeWString(wszComponentName), SafeWString(wszRestoreName))); + } + virtual void SetRestoreOptions(Guid writerId, VSS_COMPONENT_TYPE ct, [System::Runtime::InteropServices::Optional] String^ wszLogicalPath, String^ wszComponentName, String^ wszRestoreOptions) + { + Utils::ThrowIfFailed(pNative->SetRestoreOptions(SmartGuid(writerId), static_cast<::VSS_COMPONENT_TYPE>(ct), SafeWString(wszLogicalPath), SafeWString(wszComponentName), SafeWString(wszRestoreOptions))); + } + virtual void SetRestoreState(VSS_RESTORE_TYPE restoreType) + { + Utils::ThrowIfFailed(pNative->SetRestoreState(static_cast<::VSS_RESTORE_TYPE>(restoreType))); + } + virtual void SetRollForward(Guid writerId, VSS_COMPONENT_TYPE ct, [System::Runtime::InteropServices::Optional] String^ wszLogicalPath, String^ wszComponentName, VSS_ROLLFORWARD_TYPE rollType, String^ wszRollForwardPoint) + { + SafeComPtr<::IVssBackupComponentsEx2*> p = pNative; + Utils::ThrowIfFailed(p->SetRollForward(SmartGuid(writerId), static_cast<::VSS_COMPONENT_TYPE>(ct), SafeWString(wszLogicalPath), SafeWString(wszComponentName), static_cast<::VSS_ROLLFORWARD_TYPE>(rollType), SafeWString(wszRollForwardPoint))); + } + virtual void SetSelectedForRestore(Guid writerId, VSS_COMPONENT_TYPE ct, [System::Runtime::InteropServices::Optional] String^ wszLogicalPath, String^ wszComponentName, Boolean bSelectedForRestore) + { + Utils::ThrowIfFailed(pNative->SetSelectedForRestore(SmartGuid(writerId), static_cast<::VSS_COMPONENT_TYPE>(ct), SafeWString(wszLogicalPath), SafeWString(wszComponentName), bSelectedForRestore)); + } + virtual void SetSelectedForRestoreEx(Guid writerId, VSS_COMPONENT_TYPE ct, [System::Runtime::InteropServices::Optional] String^ wszLogicalPath, String^ wszComponentName, Boolean bSelectedForRestore, [System::Runtime::InteropServices::Optional] Guid instanceId) + { + SafeComPtr<::IVssBackupComponentsEx*> p = pNative; + Utils::ThrowIfFailed(p->SetSelectedForRestoreEx(SmartGuid(writerId), static_cast<::VSS_COMPONENT_TYPE>(ct), SafeWString(wszLogicalPath), SafeWString(wszComponentName), bSelectedForRestore, SmartGuid(instanceId))); + } + virtual Guid StartSnapshotSet() + { + VSS_ID id; + Utils::ThrowIfFailed(pNative->StartSnapshotSet(&id)); + return Utils::FromGUID(id); + } + virtual void UnexposeSnapshot(Guid snapshotId) + { + SafeComPtr<::IVssBackupComponentsEx2*> p = pNative; + Utils::ThrowIfFailed(p->UnexposeSnapshot(SmartGuid(snapshotId))); + } + + private: + IVssWriterComponentsExt^ GetWriterComponents(int i); + IVssExamineWriterMetadata^ GetWriterMetadata(int i); + VssWriterStatus GetWriterStatus(int i); + +#define DEFINE_BC_ROLIST(prop, itf, ref) \ + private:\ + ListImplBase^ f##prop;\ + int Get##prop##Count() { UINT c; Utils::ThrowIfFailed(pNative->ref(&c)); return c; }\ + public:\ + property IReadOnlyList^ prop { virtual IReadOnlyList^ get() {\ + if (!f##prop) f##prop = gcnew ListImplBase(gcnew GetCount(this, &CVssBackupComponents::Get##prop##Count), gcnew GetValue(this, &CVssBackupComponents::Get##prop));\ + return f##prop; } } + + DEFINE_BC_ROLIST(WriterComponents, IVssWriterComponentsExt^, GetWriterComponentsCount) + DEFINE_BC_ROLIST(WriterMetadata, IVssExamineWriterMetadata^, GetWriterMetadataCount) + DEFINE_BC_ROLIST(WriterStatus, VssWriterStatus, GetWriterStatusCount) + }; + + value struct VSS_RESTORE_METHOD + { + public: + ::VSS_RESTOREMETHOD_ENUM eMethod; + String^ bstrService; + String^ bstrUserProcedure; + ::VSS_WRITERRESTORE_ENUM eWriterRestore; + bool bRebootRequired; + UINT iMappings; + + VSS_RESTORE_METHOD(::VSS_RESTOREMETHOD_ENUM method, String^ strService, String^ strUserProcedure, ::VSS_WRITERRESTORE_ENUM writerRestore, bool rebootRequired, UINT mappings) : + eMethod(method), bstrService(strService), bstrUserProcedure(strUserProcedure), eWriterRestore(writerRestore), bRebootRequired(rebootRequired), iMappings(mappings) {} + }; + + ref class CVssExamineWriterMetadata : IVssExamineWriterMetadata, BaseWrapper<::IVssExamineWriterMetadata> + { + private: + VSS_RESTORE_METHOD restoreMethod; + UINT cIncludeFiles, cExcludeFiles, cComponents; + ListImplBase^ fExcludeFromSnapshotFiles; + + int GetExcludeFromSnapshotFilesCount() { SafeComPtr<::IVssExamineWriterMetadataEx2*> p2 = pNative; UINT c; Utils::ThrowIfFailed(p2->GetExcludeFromSnapshotCount(&c)); return c; } + IVssWMFiledesc^ GetExcludeFromSnapshotFiles(int i) { SafeComPtr<::IVssExamineWriterMetadataEx2*> p2 = pNative; ::IVssWMFiledesc* p; Utils::ThrowIfFailed(p2->GetExcludeFromSnapshotFile(i, &p)); return gcnew CVssWMFiledesc(p); } + void RefreshRestoreMethod(); + void RefreshFileCounts(); + + public: + CVssExamineWriterMetadata(::IVssExamineWriterMetadata* ptr) : BaseWrapper(ptr) {} + +#define DEFINE_EWM_ROLIST(prop, itf, gfunc, cwrap, ref, cexp) \ + private:\ + ListImplBase^ f##prop;\ + int Get##prop##Count() { ref(); return cexp; }\ + itf^ Get##prop(int i) { ::itf* p; Utils::ThrowIfFailed(pNative->gfunc(i, &p)); return gcnew cwrap(p); }\ + public:\ + property IReadOnlyList^ prop { virtual IReadOnlyList^ get() {\ + if (!f##prop) f##prop = gcnew ListImplBase(gcnew GetCount(this, &CVssExamineWriterMetadata::Get##prop##Count), gcnew GetValue(this, &CVssExamineWriterMetadata::Get##prop));\ + return f##prop; } } + + DEFINE_EWM_ROLIST(AlternateLocationMappings, IVssWMFiledesc, GetAlternateLocationMapping, CVssWMFiledesc, RefreshRestoreMethod, restoreMethod.iMappings) + DEFINE_EWM_ROLIST(Components, IVssWMComponent, GetComponent, CVssWMComponent, RefreshFileCounts, cComponents) + DEFINE_EWM_ROLIST(ExcludeFiles, IVssWMFiledesc, GetExcludeFile, CVssWMFiledesc, RefreshFileCounts, cExcludeFiles) + // DEFINE_EWM_ROLIST(IncludeFiles, IVssWMFiledesc, GetIncludeFile, CVssWMFiledesc, RefreshFileCounts, cIncludeFiles); + + private: + + public: + DEFINE_WRAPPER_PROP(BackupSchema, VSS_BACKUP_SCHEMA, DWORD, GetBackupSchema); + + property IReadOnlyList^ ExcludeFromSnapshotFiles { virtual IReadOnlyList^ get() { + if (!fExcludeFromSnapshotFiles) + fExcludeFromSnapshotFiles = gcnew ListImplBase(gcnew GetCount(this, &CVssExamineWriterMetadata::GetExcludeFromSnapshotFilesCount), + gcnew GetValue(this, &CVssExamineWriterMetadata::GetExcludeFromSnapshotFiles)); + return fExcludeFromSnapshotFiles; + } } + + property Version^ Version { virtual System::Version^ get(); } + + virtual void GetIdentity(Guid% pidInstance, Guid% pidWriter, String^% pbstrWriterName, String^% pbstrInstanceName, VSS_USAGE_TYPE% pUsage, + VSS_SOURCE_TYPE% pSource); + + virtual void GetRestoreMethod(VSS_RESTOREMETHOD_ENUM% pMethod, System::String^% pbstrService, System::String^% pbstrUserProcedure, + VSS_WRITERRESTORE_ENUM% pwriterRestore, bool% pbRebootRequired, UInt32% pcMappings); + + virtual void LoadFromXML(String^ bstrXML); + + virtual String^ SaveAsXML(); + }; + } + } +} \ No newline at end of file diff --git a/PInvoke/VssApi/VsWriter.cpp b/PInvoke/VssApi/VsWriter.cpp new file mode 100644 index 00000000..db29d652 --- /dev/null +++ b/PInvoke/VssApi/VsWriter.cpp @@ -0,0 +1,151 @@ +#include "pch.h" +#include +#include "vswriter.h" +#include "CliLists.h" + +using namespace Vanara::PInvoke::VssApi; +using namespace System::Collections::Generic; + +#define DEFINE_COMP_ROLIST(prop, cFunc, iElem, gFunc, cElem) \ + IReadOnlyList^ CVssComponent::prop::get() {\ + UINT c;\ + Utils::ThrowIfFailed(pNative->cFunc(&c));\ + auto ret = gcnew List();\ + ::iElem* v;\ + for (UINT i = 0; i < c; i++) {\ + pNative->gFunc(i, &v);\ + ret->Add(gcnew cElem(v));\ + }\ + return ret;\ + } + +DEFINE_COMP_ROLIST(AlternateLocationMappings, GetAlternateLocationMappingCount, IVssWMFiledesc, GetAlternateLocationMapping, CVssWMFiledesc) + +DEFINE_COMP_ROLIST(NewTargets, GetNewTargetCount, IVssWMFiledesc, GetNewTarget, CVssWMFiledesc) + +VssDifferencedFile CVssComponent::GetDifferencedFilesItem(int i) +{ + SafeBSTR path, filespec, lsn; + ::BOOL recur; + FILETIME ft; + Utils::ThrowIfFailed(pNative->GetDifferencedFile(i, &path, &filespec, &recur, &lsn, &ft)); + VssDifferencedFile e; + e.Path = path; + e.FileSpec = filespec; + e.Recursive = recur; + ::Int64 nFT = static_cast<::Int64>(*(long long*)&ft); + e.LastModifyTime = DateTime::FromFileTime(nFT); + return e; +} + +void CVssComponent::AddDifferencedFile(VssDifferencedFile item) +{ + auto llft = item.LastModifyTime.ToFileTime(); + FILETIME ft = *(FILETIME*)&llft; + Utils::ThrowIfFailed(pNative->AddDifferencedFilesByLastModifyTime(SafeWString(item.Path), SafeWString(item.FileSpec), item.Recursive, ft)); +} + +IAppendOnlyList^ CVssComponent::DifferencedFiles::get() +{ + return gcnew AppendOnlyList( + gcnew GetCount(this, &CVssComponent::GetDifferencedFilesCount), + gcnew GetValue(this, &CVssComponent::GetDifferencedFilesItem), + gcnew AddValue(this, &CVssComponent::AddDifferencedFile)); +} + +VssDirectedTarget CVssComponent::GetDirectedTargetItem(int i) +{ + SafeBSTR spath, sfn, srng, dpath, dfn, drng; + Utils::ThrowIfFailed(pNative->GetDirectedTarget(i, &spath, &sfn, &srng, &dpath, &dfn, &drng)); + VssDirectedTarget e = { dfn, dpath, drng, sfn, spath, srng, }; + return e; +} + +void CVssComponent::AddDirectedTarget(VssDirectedTarget v) +{ + Utils::ThrowIfFailed(pNative->AddDirectedTarget(SafeWString(v.SourcePath), + SafeWString(v.SourceFilename), SafeWString(v.SourceRangeList), SafeWString(v.DestinationPath), + SafeWString(v.DestinationFilename), SafeWString(v.DestinationRangeList))); +} + +IAppendOnlyList^ CVssComponent::DirectedTargets::get() +{ + return gcnew AppendOnlyList( + gcnew GetCount(this, &CVssComponent::GetDirectedTargetCount), + gcnew GetValue(this, &CVssComponent::GetDirectedTargetItem), + gcnew AddValue(this, &CVssComponent::AddDirectedTarget)); +} + +VssPartialFile CVssComponent::GetPartialFileItem(int i) +{ + SafeBSTR path, fn, rng, meta; + Utils::ThrowIfFailed(pNative->GetPartialFile(i, &path, &fn, &rng, &meta)); + VssPartialFile e = { fn, meta, path, rng }; + return e; +} + +void CVssComponent::AddPartialFile(VssPartialFile v) +{ + Utils::ThrowIfFailed(pNative->AddPartialFile(SafeWString(v.Path), SafeWString(v.Filename), + SafeWString(v.Ranges), SafeWString(v.Metadata))); +} + +IAppendOnlyList^ CVssComponent::PartialFiles::get() +{ + return gcnew AppendOnlyList( + gcnew GetCount(this, &CVssComponent::GetPartialFileCount), + gcnew GetValue(this, &CVssComponent::GetPartialFileItem), + gcnew AddValue(this, &CVssComponent::AddPartialFile)); +} + +VssRestoreSubcomponent CVssComponent::GetRestoreSubcomponentsItem(int i) +{ + SafeBSTR path, n; + bool repair; + Utils::ThrowIfFailed(pNative->GetRestoreSubcomponent(i, &path, &n, &repair)); + VssRestoreSubcomponent e = { repair, n, path }; + return e; +} + +IReadOnlyList^ CVssComponent::RestoreSubcomponents::get() +{ + return gcnew ListImplBase( + gcnew GetCount(this, &CVssComponent::GetRestoreSubcomponentsCount), + gcnew GetValue(this, &CVssComponent::GetRestoreSubcomponentsItem)); +} + +void CVssComponent::GetFailure(Vanara::PInvoke::HRESULT% phr, Vanara::PInvoke::HRESULT% phrApplication, System::String^% pbstrApplicationMessage) +{ + SafeComPtr<::IVssComponentEx2*> p = pNative; + ::HRESULT hr, hrApp; + SafeBSTR msg; + DWORD d; + Utils::ThrowIfFailed(p->GetFailure(&hr, &hrApp, &msg, &d)); + phr = static_cast(hr); + phrApplication = static_cast(hrApp); + pbstrApplicationMessage = msg; +} + +void CVssComponent::GetRollForward(VSS_ROLLFORWARD_TYPE% pRollType, System::String^% pbstrPoint) +{ + SafeComPtr<::IVssComponentEx*> p = pNative; + ::VSS_ROLLFORWARD_TYPE type; + SafeBSTR pt; + Utils::ThrowIfFailed(p->GetRollForward(&type, &pt)); + pRollType = static_cast(type); + pbstrPoint = pt; +} + +void CVssComponent::SetFailure(Vanara::PInvoke::HRESULT hr, Vanara::PInvoke::HRESULT hrApplication, System::String^ wszApplicationMessage) +{ + SafeComPtr<::IVssComponentEx2*> p = pNative; + SafeString msg = wszApplicationMessage; + Utils::ThrowIfFailed(p->SetFailure(static_cast<::HRESULT>((Int32)hr), static_cast<::HRESULT>((Int32)hrApplication), msg, 0)); +} + +Vanara::PInvoke::VssApi::IVssComponent^ CVssWriterComponents::GetComponent(int i) +{ + SafeComPtr<::IVssComponent*> c; + Utils::ThrowIfFailed(pNative->GetComponent(i, &c)); + return (IVssComponent^)Marshal::GetObjectForIUnknown(IntPtr((::IVssComponent*)c)); +} \ No newline at end of file diff --git a/PInvoke/VssApi/VsWriter.h b/PInvoke/VssApi/VsWriter.h new file mode 100644 index 00000000..c42a077b --- /dev/null +++ b/PInvoke/VssApi/VsWriter.h @@ -0,0 +1,1105 @@ +#pragma once +#include "pch.h" +#include +#include "CliLists.h" + +using namespace System; +using namespace Collections::Generic; +using namespace Runtime::InteropServices; + +namespace Vanara { namespace PInvoke { namespace VssApi { + + ///// Denotes that no maximum space is specified in AddDiffArea or ChangeDiffAreaMaximumSize + //public const long VSS_ASSOC_NO_MAX_SPACE = -1; + + ///// If this constant is specified in ChangeDiffAreaMaximumSize then the association is removed + //public const long VSS_ASSOC_REMOVE = 0; + + ref class CVssWMFiledesc : IVssWMFiledesc, BaseWrapper<::IVssWMFiledesc> + { + public: + CVssWMFiledesc(::IVssWMFiledesc* ptr) : BaseWrapper(ptr) {} + + DEFINE_WRAPPER_STRING_PROP(AlternateLocation, GetAlternateLocation) + DEFINE_WRAPPER_PROP(BackupTypeMask, VSS_FILE_SPEC_BACKUP_TYPE, ::DWORD, GetBackupTypeMask) + DEFINE_WRAPPER_STRING_PROP(FileSpec, GetFilespec) + DEFINE_WRAPPER_STRING_PROP(Path, GetPath) + DEFINE_WRAPPER_PROP(Recursive, bool, bool, GetRecursive) + }; + + ref class CVssWMDependency : IVssWMDependency, BaseWrapper<::IVssWMDependency> + { + public: + CVssWMDependency(::IVssWMDependency* ptr) : BaseWrapper(ptr) {} + + DEFINE_WRAPPER_STRING_PROP(ComponentName, GetComponentName) + DEFINE_WRAPPER_STRING_PROP(LogicalPath, GetLogicalPath) + DEFINE_WRAPPER_PROPC(WriterId, Guid, _GUID, GetWriterId, Utils::FromGUID) + }; + + ref class CVssComponent : IVssComponent, BaseWrapper<::IVssComponent> + { + public: + CVssComponent(::IVssComponent* ptr) : BaseWrapper(ptr) {} + + DEFINE_WRAPPER_GS_PROP(RestoreTarget, VSS_RESTORE_TARGET, ::VSS_RESTORE_TARGET) + DEFINE_WRAPPER_PROP(AdditionalRestores, bool, bool, GetAdditionalRestores) + DEFINE_WRAPPER_PROP(BackupSucceeded, bool, bool, GetBackupSucceeded) + DEFINE_WRAPPER_PROP(ComponentType, VSS_COMPONENT_TYPE, ::VSS_COMPONENT_TYPE, GetComponentType) + DEFINE_WRAPPER_PROP(FileRestoreStatus, VSS_FILE_RESTORE_STATUS, ::VSS_FILE_RESTORE_STATUS, GetFileRestoreStatus) + DEFINE_WRAPPER_PROP(IsSelectedForRestore, bool, bool, IsSelectedForRestore) + DEFINE_WRAPPER_QI_PROP(AuthoritativeRestore, bool, bool, GetAuthoritativeRestore, ::IVssComponentEx) + DEFINE_WRAPPER_STRING_GS_PROP(BackupMetadata) + DEFINE_WRAPPER_STRING_GS_PROP(BackupStamp) + DEFINE_WRAPPER_STRING_GS_PROP(PostRestoreFailureMsg) + DEFINE_WRAPPER_STRING_GS_PROP(PreRestoreFailureMsg) + DEFINE_WRAPPER_STRING_GS_PROP(RestoreMetadata) + DEFINE_WRAPPER_STRING_PROP(BackupOptions, GetBackupOptions) + DEFINE_WRAPPER_STRING_PROP(ComponentName, GetComponentName) + DEFINE_WRAPPER_STRING_PROP(LogicalPath, GetLogicalPath) + DEFINE_WRAPPER_STRING_PROP(PreviousBackupStamp, GetPreviousBackupStamp) + DEFINE_WRAPPER_STRING_PROP(RestoreOptions, GetRestoreOptions) + DEFINE_WRAPPER_STRING_QI_GS_PROP(PostSnapshotFailureMsg, ::IVssComponentEx) + DEFINE_WRAPPER_STRING_QI_GS_PROP(PrepareForBackupFailureMsg, ::IVssComponentEx) + DEFINE_WRAPPER_STRING_QI_PROP(RestoreName, GetRestoreName, ::IVssComponentEx) + + property IReadOnlyList^ AlternateLocationMappings { virtual IReadOnlyList^ get(); } + property IAppendOnlyList^ DifferencedFiles { virtual IAppendOnlyList^ get(); } + property IAppendOnlyList^ DirectedTargets { virtual IAppendOnlyList^ get(); } + property IReadOnlyList^ NewTargets { virtual IReadOnlyList^ get(); } + property IAppendOnlyList^ PartialFiles { virtual IAppendOnlyList^ get(); } + property IReadOnlyList^ RestoreSubcomponents { virtual IReadOnlyList^ get(); } + + virtual void GetFailure(Vanara::PInvoke::HRESULT% phr, Vanara::PInvoke::HRESULT% phrApplication, System::String^% pbstrApplicationMessage); + virtual void GetRollForward(VSS_ROLLFORWARD_TYPE% pRollType, System::String^% pbstrPoint); + virtual void SetFailure(Vanara::PInvoke::HRESULT hr, Vanara::PInvoke::HRESULT hrApplication, System::String^ wszApplicationMessage); + private: + int GetDifferencedFilesCount() { UINT c; pNative->GetDifferencedFilesCount(&c); return c; } + int GetDirectedTargetCount() { UINT c; pNative->GetDirectedTargetCount(&c); return c; } + int GetPartialFileCount() { UINT c; pNative->GetPartialFileCount(&c); return c; } + int GetRestoreSubcomponentsCount() { UINT c; pNative->GetRestoreSubcomponentCount(&c); return c; } + VssDifferencedFile GetDifferencedFilesItem(int i); + VssDirectedTarget GetDirectedTargetItem(int i); + VssPartialFile GetPartialFileItem(int i); + VssRestoreSubcomponent GetRestoreSubcomponentsItem(int i); + void AddDifferencedFile(VssDifferencedFile); + void AddDirectedTarget(VssDirectedTarget); + void AddPartialFile(VssPartialFile); + }; + + ref class CVssCreateWriterMetadata : IVssCreateWriterMetadata, IVssCreateWriterMetadataEx, BaseClassWrapper<::IVssCreateWriterMetadata> + { + public: + CVssCreateWriterMetadata(::IVssCreateWriterMetadata* ptr) : BaseClassWrapper(ptr) {} + + virtual void AddAlternateLocationMapping(System::String^ wszSourcePath, System::String^ wszSourceFilespec, bool bRecursive, System::String^ wszDestination) + { + Utils::ThrowIfFailed(pNative->AddAlternateLocationMapping(SafeWString(wszSourcePath), SafeWString(wszSourceFilespec), bRecursive, SafeWString(wszDestination))); + } + + virtual void AddComponent(VSS_COMPONENT_TYPE ct, System::String^ wszLogicalPath, System::String^ wszComponentName, + System::String^ wszCaption, array^ pbIcon, bool bRestoreMetadata, bool bNotifyOnBackupComplete, bool bSelectable, + bool bSelectableForRestore, VSS_COMPONENT_FLAGS dwComponentFlags) + { + pin_ptr pIco = &pbIcon[0]; + Utils::ThrowIfFailed(pNative->AddComponent(static_cast<::VSS_COMPONENT_TYPE>(ct), SafeWString(wszLogicalPath), SafeWString(wszComponentName), + SafeWString(wszCaption), pIco, pbIcon->Length, bRestoreMetadata, bNotifyOnBackupComplete, bSelectable, bSelectableForRestore, (DWORD)dwComponentFlags)); + } + + virtual void AddComponentDependency(System::String^ wszForLogicalPath, System::String^ wszForComponentName, System::Guid onWriterId, + System::String^ wszOnLogicalPath, System::String^ wszOnComponentName) + { + Utils::ThrowIfFailed(pNative->AddComponentDependency(SafeWString(wszForLogicalPath), SafeWString(wszForComponentName), Utils::ToGUID(onWriterId), + SafeWString(wszOnLogicalPath), SafeWString(wszOnComponentName))); + } + + virtual void AddDatabaseFiles(System::String^ wszLogicalPath, System::String^ wszDatabaseName, System::String^ wszPath, System::String^ wszFilespec, + VSS_FILE_SPEC_BACKUP_TYPE dwBackupTypeMask) + { + Utils::ThrowIfFailed(pNative->AddDatabaseFiles(SafeWString(wszLogicalPath), SafeWString(wszDatabaseName), SafeWString(wszPath), SafeWString(wszFilespec), (DWORD)dwBackupTypeMask)); + } + + virtual void AddDatabaseLogFiles(System::String^ wszLogicalPath, System::String^ wszDatabaseName, System::String^ wszPath, System::String^ wszFilespec, + VSS_FILE_SPEC_BACKUP_TYPE dwBackupTypeMask) + { + Utils::ThrowIfFailed(pNative->AddDatabaseLogFiles(SafeWString(wszLogicalPath), SafeWString(wszDatabaseName), SafeWString(wszPath), SafeWString(wszFilespec), + static_cast(dwBackupTypeMask))); + } + + virtual void AddExcludeFiles(System::String^ wszPath, System::String^ wszFilespec, bool bRecursive) + { + Utils::ThrowIfFailed(pNative->AddExcludeFiles(SafeWString(wszPath), SafeWString(wszFilespec), bRecursive)); + } + + virtual void AddExcludeFilesFromSnapshot(System::String^ wszPath, System::String^ wszFilespec, bool bRecursive) + { + ::IVssCreateWriterMetadataEx* p = dynamic_cast<::IVssCreateWriterMetadataEx*>(pNative); + if (p) + Utils::ThrowIfFailed(p->AddExcludeFilesFromSnapshot(SafeWString(wszPath), SafeWString(wszFilespec), bRecursive)); + } + + virtual void AddFilesToFileGroup(System::String^ wszLogicalPath, System::String^ wszGroupName, System::String^ wszPath, System::String^ wszFilespec, + bool bRecursive, System::String^ wszAlternateLocation, VSS_FILE_SPEC_BACKUP_TYPE dwBackupTypeMask) + { + Utils::ThrowIfFailed(pNative->AddFilesToFileGroup(SafeWString(wszLogicalPath), SafeWString(wszGroupName), SafeWString(wszPath), + SafeWString(wszFilespec), bRecursive, SafeWString(wszAlternateLocation), (DWORD)dwBackupTypeMask)); + } + + virtual System::String^ SaveAsXML() + { + SafeBSTR xml; + Utils::ThrowIfFailed(pNative->SaveAsXML(&xml)); + return xml; + } + + virtual void SetBackupSchema(VSS_BACKUP_SCHEMA dwSchemaMask) + { + Utils::ThrowIfFailed(pNative->SetBackupSchema((DWORD)dwSchemaMask)); + } + + virtual void SetRestoreMethod(VSS_RESTOREMETHOD_ENUM method, System::String^ wszService, System::String^ wszUserProcedure, + VSS_WRITERRESTORE_ENUM writerRestore, bool bRebootRequired) + { + Utils::ThrowIfFailed(pNative->SetRestoreMethod(static_cast<::VSS_RESTOREMETHOD_ENUM>(method), SafeWString(wszService), SafeWString(wszUserProcedure), + static_cast<::VSS_WRITERRESTORE_ENUM>(writerRestore), bRebootRequired)); + } + + }; + + ref class CVssExpressWriter : IVssExpressWriter, BaseWrapper<::IVssExpressWriter> + { + public: + CVssExpressWriter(::IVssExpressWriter* ptr) : BaseWrapper(ptr) {} + + virtual IVssCreateExpressWriterMetadata^ CreateMetadata(Guid writerId, String^ writerName, VSS_USAGE_TYPE usageType, unsigned int versionMajor, unsigned int versionMinor) + { + SafeComPtr<::IVssCreateExpressWriterMetadata*> meta; + Utils::ThrowIfFailed(pNative->CreateMetadata(Utils::ToGUID(writerId), SafeWString(writerName), static_cast<::VSS_USAGE_TYPE>(usageType), (DWORD)versionMajor, (DWORD)versionMinor, 0, &meta)); + return (IVssCreateExpressWriterMetadata^)Marshal::GetObjectForIUnknown(IntPtr((::IVssCreateExpressWriterMetadata*)meta)); + } + + virtual void LoadMetadata(System::String^ metadata) { Utils::ThrowIfFailed(pNative->LoadMetadata(SafeWString(metadata), 0)); } + + virtual void Register() { Utils::ThrowIfFailed(pNative->Register()); } + + virtual void Unregister(System::Guid writerId) { Utils::ThrowIfFailed(pNative->Unregister(Utils::ToGUID(writerId))); } + }; + + ref class CVssWriterComponents : IVssWriterComponents, IVssWriterComponentsExt, BaseClassWrapper<::IVssWriterComponents> + { + public: + CVssWriterComponents(::IVssWriterComponents* ptr) : BaseClassWrapper(ptr) {} + CVssWriterComponents(::IVssWriterComponentsExt* ptr) : BaseClassWrapper(ptr) {} + + virtual property IReadOnlyList^ Components + { + IReadOnlyList^ get() + { + return gcnew ListImplBase(gcnew GetCount(this, &CVssWriterComponents::GetComponentsCount), + gcnew GetValue(this, &CVssWriterComponents::GetComponent)); + } + } + + virtual void GetWriterInfo(System::Guid% pidInstance, System::Guid% pidWriter) + { + VSS_ID inst, wri; + Utils::ThrowIfFailed(pNative->GetWriterInfo(&inst, &wri)); + pidInstance = Utils::FromGUID(inst); + pidWriter = Utils::FromGUID(wri); + } + private: + int GetComponentsCount() { UINT c; Utils::ThrowIfFailed(pNative->GetComponentCount(&c)); return c; } + IVssComponent^ GetComponent(int i); + }; + + interface class IVssWriter + { + public: + virtual Boolean OnIdentify(IN IVssCreateWriterMetadata^ pMetadata) = 0; + + virtual Boolean OnPrepareBackup(_In_ IVssWriterComponents^ pComponent) = 0; + + // callback for prepare snapsot event + virtual Boolean OnPrepareSnapshot() = 0; + + // callback for freeze event + virtual Boolean OnFreeze() = 0; + + // callback for thaw event + virtual Boolean OnThaw() = 0; + + // callback if current sequence is aborted + virtual Boolean OnAbort() = 0; + + // callback on backup complete event + virtual Boolean OnBackupComplete(_In_ IVssWriterComponents^ pComponent) = 0; + + // callback indicating that the backup process has either completed or has shut down + virtual Boolean OnBackupShutdown(_In_ Guid SnapshotSetId) = 0; + + // callback on pre-restore event + virtual Boolean OnPreRestore(_In_ IVssWriterComponents^ pComponent) = 0; + + // callback on post-restore event + virtual Boolean OnPostRestore(_In_ IVssWriterComponents^ pComponent) = 0; + + // callback on post snapshot event + virtual Boolean OnPostSnapshot(_In_ IVssWriterComponents^ pComponent) = 0; + + // callback on back off I/O volume event + virtual Boolean OnBackOffIOOnVolume(_In_ String^ wszVolumeName, _In_ Guid snapshotId, _In_ Guid providerId) = 0; + + // callback on Continue I/O on volume event + virtual Boolean OnContinueIOOnVolume(_In_ String^ wszVolumeName, _In_ Guid snapshotId, _In_ Guid providerId) = 0; + + virtual Boolean OnVSSShutdown() = 0; + + virtual Boolean OnVSSApplicationStartup() = 0; + + virtual Boolean OnIdentifyEx(_In_ IVssCreateWriterMetadataEx^ pMetadata) = 0; + }; + + class CVssWriterImpl : public ::CVssWriterEx2 + { + private: + gcroot host; + public: + CVssWriterImpl(IVssWriter^ h) : host(h) {} + + bool STDMETHODCALLTYPE OnIdentify(IN ::IVssCreateWriterMetadata* pMetadata) + { + return host->OnIdentify(gcnew CVssCreateWriterMetadata(pMetadata)); + } + + bool STDMETHODCALLTYPE OnPrepareBackup(_In_ ::IVssWriterComponents* pComponent) + { + return host->OnPrepareBackup((IVssWriterComponents^)Marshal::GetObjectForIUnknown(IntPtr((void*)pComponent))); + } + + bool STDMETHODCALLTYPE OnPrepareSnapshot() + { + return host->OnPrepareSnapshot(); + } + + bool STDMETHODCALLTYPE OnFreeze() + { + return host->OnFreeze(); + } + + bool STDMETHODCALLTYPE OnThaw() + { + return host->OnThaw(); + } + + bool STDMETHODCALLTYPE OnAbort() + { + return host->OnAbort(); + } + + bool STDMETHODCALLTYPE OnBackupComplete(_In_ ::IVssWriterComponents* pComponent) + { + return host->OnBackupComplete((IVssWriterComponents^)Marshal::GetObjectForIUnknown(IntPtr((void*)pComponent))); + } + + bool STDMETHODCALLTYPE OnBackupShutdown(_In_ VSS_ID SnapshotSetId) + { + return host->OnBackupShutdown(Utils::FromGUID(SnapshotSetId)); + } + + bool STDMETHODCALLTYPE OnPreRestore(_In_ ::IVssWriterComponents* pComponent) + { + return host->OnPreRestore((IVssWriterComponents^)Marshal::GetObjectForIUnknown(IntPtr((void*)pComponent))); + } + + bool STDMETHODCALLTYPE OnPostRestore(_In_ ::IVssWriterComponents* pComponent) + { + return host->OnPostRestore((IVssWriterComponents^)Marshal::GetObjectForIUnknown(IntPtr((void*)pComponent))); + } + + bool STDMETHODCALLTYPE OnPostSnapshot(_In_ ::IVssWriterComponents* pComponent) + { + return host->OnPostSnapshot((IVssWriterComponents^)Marshal::GetObjectForIUnknown(IntPtr((void*)pComponent))); + } + + bool STDMETHODCALLTYPE OnBackOffIOOnVolume(_In_ VSS_PWSZ wszVolumeName, _In_ VSS_ID snapshotId, _In_ VSS_ID providerId) + { + return host->OnBackOffIOOnVolume(SafeBSTR(wszVolumeName), Utils::FromGUID(snapshotId), Utils::FromGUID(providerId)); + } + + bool STDMETHODCALLTYPE OnContinueIOOnVolume(_In_ VSS_PWSZ wszVolumeName, _In_ VSS_ID snapshotId, _In_ VSS_ID providerId) + { + return host->OnContinueIOOnVolume(SafeBSTR(wszVolumeName), Utils::FromGUID(snapshotId), Utils::FromGUID(providerId)); + } + + bool STDMETHODCALLTYPE OnVSSShutdown() + { + return host->OnVSSShutdown(); + } + + bool STDMETHODCALLTYPE OnVSSApplicationStartup() + { + return host->OnVSSApplicationStartup(); + } + + bool STDMETHODCALLTYPE OnIdentifyEx(_In_::IVssCreateWriterMetadataEx* pMetadata) + { + return host->OnIdentifyEx(gcnew CVssCreateWriterMetadata(pMetadata)); + } + }; + + public ref class CVssWriter : public IVssWriter + { + private: + CVssWriterImpl* pNative; + + protected: + // Constructors & Destructors + STDMETHODCALLTYPE CVssWriter() : pNative(new CVssWriterImpl(this)) {} + + virtual STDMETHODCALLTYPE ~CVssWriter() + { + if (pNative != NULL) + { + delete pNative; + pNative = NULL; + } + } + + public: + + /// Returns the writer's session identifier. + /// A pointer to a variable that receives the session identifier. + /// + /// + /// The session identifier is an opaque value that uniquely identifies a backup or restore session. It is used to distinguish the + /// current session among multiple parallel backup or restore sessions. + /// + /// + /// As a best practice, writers and requesters should include the session ID in all diagnostics messages used for event logging and tracing. + /// + /// + /// If a writer's event handler (such as CVssWriter::OnFreeze) calls this method, it must do so in the same thread that called the + /// event handler. For more information, see Writer Event Handling. + /// + /// + void GetSessionId([Out] Guid% idSession) + { + VSS_ID id; + Utils::ThrowIfFailed(pNative->GetSessionId(&id)); + idSession = Utils::FromGUID(id); + } + + /// + /// Initializes a CVssWriter object and allows a writer application to interact with VSS. + /// Initialize is a public method implemented by the CVssWriter base class. + /// + /// The globally unique identifier (GUID) of the writer class. + /// + /// A null-terminated wide character string that contains the name of the writer. This string is not localized. + /// + /// A VSS_USAGE_TYPE enumeration value that indicates how the data managed by the writer is used on the host system. + /// A VSS_SOURCE_TYPE enumeration value that indicates the type of data managed by the writer. + /// + /// + /// A VSS_APPLICATION_LEVEL enumeration value that indicates the application level at which the writer receives a Freeze event notification. + /// + /// The default value for this parameter is VSS_APP_FRONT_END. + /// + /// + /// + /// The maximum permitted time, in milliseconds, between a writer's receipt of a Freeze event notification and the receipt of a + /// matching Thaw event notification from VSS. After the time-out expires, the writer's CVssWriter::OnAbort method is called automatically. + /// + /// The default value for this parameter is 60000. + /// + /// + /// A VSS_ALTERNATE_WRITER_STATE enumeration value that indicates whether the writer has an associated alternate writer. + /// + /// The default value for this parameter is VSS_AWS_NO_ALTERNATE_WRITER. The caller should not override this default value. This + /// parameter is reserved for future use. + /// + /// + /// + /// Set this parameter to true if I/O throttling methods are enabled, or false otherwise. + /// + /// The default value for this parameter is false. The caller should not override this default value. This parameter is + /// reserved for future use. + /// + /// + /// + /// A null-terminated wide character string that contains the writer instance name. + /// + /// The default value for this parameter is NULL. If the writer has multiple instances and requires restore events, this + /// parameter is required and cannot be NULL. For details, see the following Remarks section. + /// + /// + /// Windows Server 2003 and Windows XP: Before Windows Server 2003 with SP1, this parameter is reserved for system use, and + /// the caller should not override the default value. + /// + /// + /// + /// + /// VSS assigns a unique writer instance ID to each instance of a writer application. If more than one instance is present on the + /// system at the same time (for example, if multiple SQL servers are running on a system), each writer is uniquely identified by + /// the combination of its writer class ID and its writer instance ID. + /// + /// + /// The wszWriterInstanceName parameter allows a multi-instance writer to specify a persistent name for each writer instance + /// as a human-readable string. This name must be unique across all instances of the writer on the system. If a writer has multiple + /// instances and requires restore events, it must specify a non- NULL string for this parameter. VSS uses the instance name + /// to correctly restore multi-instance writers. + /// + /// + void Initialize(Guid WriterId, String^ wszWriterName, VSS_USAGE_TYPE ut, VSS_SOURCE_TYPE st, VSS_APPLICATION_LEVEL nLevel, + UInt32 dwTimeoutFreeze, VSS_ALTERNATE_WRITER_STATE aws, [Optional] bool bIOThrottlingOnly, [Optional] String^ wszWriterInstanceName) + { + if (pNative != NULL) + throw gcnew InvalidOperationException("Initialize has already been called."); + Utils::ThrowIfFailed(pNative->Initialize(SmartGuid(WriterId), SafeWString(wszWriterName), (::VSS_USAGE_TYPE)ut, (::VSS_SOURCE_TYPE)st, + (::VSS_APPLICATION_LEVEL)nLevel, dwTimeoutFreeze, (::VSS_ALTERNATE_WRITER_STATE)aws, bIOThrottlingOnly, SafeWString(wszWriterInstanceName))); + } + + /// + /// + /// Initializes a CVssWriterEx object and allows a writer application to interact with VSS. Unlike the Initialize method, the + /// InitializeEx method allows the caller to specify writer version information. + /// + /// InitializeEx is a public method implemented by the CVssWriterEx base class. + /// Writers must call Initialize or InitializeEx, but not both. + /// + /// The globally unique identifier (GUID) of the writer class. + /// + /// A null-terminated wide character string that contains the name of the writer. This string is not localized. + /// + /// The major version of the writer application. For more information, see the Remarks section. + /// The minor version of the writer application. For more information, see the Remarks section. + /// + /// A VSS_USAGE_TYPE enumeration value that indicates how the data that is managed by the writer is used on the host system. + /// + /// A VSS_SOURCE_TYPE enumeration value that indicates the type of data that is managed by the writer. + /// + /// + /// A VSS_APPLICATION_LEVEL enumeration value that indicates the application level at which the writer receives a Freeze event notification. + /// + /// The default value for this parameter is VSS_APP_FRONT_END. + /// + /// + /// + /// The maximum permitted time, in milliseconds, between the writer's receipt of a Freeze event notification and its receipt of a + /// matching Thaw event notification from VSS. After the time-out expires, the writer's OnAbort method is called automatically. + /// + /// The default value for this parameter is 60000. + /// + /// + /// A VSS_ALTERNATE_WRITER_STATE enumeration value that indicates whether the writer has an associated alternate writer. + /// + /// The default value for this parameter is VSS_AWS_NO_ALTERNATE_WRITER. The caller should not override this default value. This + /// parameter is reserved for future use. + /// + /// + /// + /// Set this parameter to true if I/O throttling methods are enabled, or false otherwise. + /// + /// The default value for this parameter is false. The caller should not override this default value. This parameter is + /// reserved for future use. + /// + /// + /// + /// A null-terminated wide character string that contains the writer instance name. + /// + /// The default value for this parameter is NULL. If the writer has multiple instances and requires restore events, this + /// parameter is required and cannot be NULL. For more information, see the following Remarks section. + /// + /// + /// + /// + /// The InitializeEx method is identical to the Initialize method except for the dwMajorVersion and + /// dwMinorVersion parameters. If the writer uses Initialize instead of InitializeEx, the writer version will + /// be reported as 0.0 (major version = 0, minor version = 0) by the IVssExamineWriterMetadataEx2::GetVersion method. + /// + /// + /// The dwMajorVersion and dwMinorVersion parameters are used to specify the writer major and minor version numbers + /// according to the following VSS conventions: + /// + /// + /// + /// + /// If the writer has changed since Windows XP or is new for Windows Vista, it should specify 1.0 or higher for its version number. + /// + /// + /// + /// + /// A writer's minor version number should be incremented by one whenever a released version of the writer contains minor changes + /// that affect the writer's interaction with requesters. For example, a correction to a file specification in a writer QFE or + /// service pack would justify incrementing the minor version number. However, a change between beta or release candidate versions + /// of a writer would not justify the changing of the minor version number. + /// + /// + /// + /// + /// A writer's major version number should be incremented by one whenever a released version of the writer contains a significant + /// change. For example, if data that is backed up with a new version of a writer cannot be restored using the previous version of + /// the writer, the new writer's major version number should be incremented. + /// + /// + /// + /// Whenever the major version number is incremented, the minor version number should be reset to zero. + /// + /// + /// If a writer does not specify a version number, VSS will assign a default version number of 0.0. + /// + /// VSS assigns a unique writer instance ID to each instance of a writer application. If more than one instance is present on the + /// system at the same time (for example, if multiple SQL servers are running on a system), each writer is uniquely identified by + /// the combination of its writer class ID and its writer instance ID. + /// + /// + /// The wszWriterInstanceName parameter allows a multi-instance writer to specify a persistent name for each writer instance + /// as a human-readable string. This name must be unique across all instances of the writer on the system. If a writer has multiple + /// instances and requires restore events, it must specify a non- NULL string for this parameter. VSS uses the instance name + /// to correctly restore multi-instance writers. + /// + /// + void InitializeEx(Guid WriterId, String^ wszWriterName, UInt32 dwMajorVersion, UInt32 dwMinorVersion, VSS_USAGE_TYPE ut, + VSS_SOURCE_TYPE st, VSS_APPLICATION_LEVEL nLevel, UInt32 dwTimeoutFreeze, VSS_ALTERNATE_WRITER_STATE aws, + [Optional] bool bIOThrottlingOnly, [Optional] String^ wszWriterInstanceName) + { + if (pNative != NULL) + throw gcnew InvalidOperationException("Initialize has already been called."); + Utils::ThrowIfFailed(pNative->InitializeEx(SmartGuid(WriterId), SafeWString(wszWriterName), dwMajorVersion, dwMinorVersion, (::VSS_USAGE_TYPE)ut, (::VSS_SOURCE_TYPE)st, + (::VSS_APPLICATION_LEVEL)nLevel, dwTimeoutFreeze, (::VSS_ALTERNATE_WRITER_STATE)aws, bIOThrottlingOnly, SafeWString(wszWriterInstanceName))); + } + + ///// + ///// Not supported. + ///// This method is reserved for future use. + ///// + ///// This parameter is reserved for future use. + ///// This parameter is reserved for future use. + //// https://docs.microsoft.com/en-us/windows/win32/api/vswriter/nf-vswriter-cvsswriter-installalternatewriter + //// HRESULT InstallAlternateWriter( VSS_ID writerId, CLSID persistentWriterClassId ); + //void InstallAlternateWriter(Guid writerId, Guid persistentWriterClassId) + //{ + // Utils::ThrowIfFailed(pNative->InstallAlternateWriter(SmartGuid(writerId), SmartGuid(persistentWriterClassId))); + //} + + /// Determines whether the writer is shutting down. + /// Returns true if the writer is shutting down, or false otherwise. + /// + /// + /// The writer implementation should call this method periodically during long-running events where the writer is performing a large + /// amount of processing or looping. If this method returns true during the event, the writer should do the following: + /// + /// + /// + /// Log an error to the Application Event Log event. This is optional, but recommended. + /// + /// + /// Call SetWriterFailure or SetWriterFailureEx, passing a non-retryable error code for the hr or hrWriter parameter. + /// + /// + /// + Boolean IsWriterShuttingDown() + { + return pNative->IsWriterShuttingDown(); + } + + /// + /// The OnIdentify method is called by a writer following receipt of an Identify event. + /// + /// OnIdentify is a virtual method. It is implemented by the CVssWriter base class, but can be overridden by derived classes. + /// + /// + /// A pointer to an IVssCreateWriterMetadata object used to construct the writer's metadata. + /// + /// As implemented by the base class, OnIdentify always returns true. + /// + /// Any other implementation of this method must return true except in the case of a fatal error. If a fatal error occurs, + /// the method should return false. + /// + /// + /// In all cases when a failure occurs, including nonfatal errors, the method should write a detailed entry to the event log to + /// report the exact reason for the failure. + /// + /// + /// + /// + /// The default implementation of this method by the CVssWriter base class returns true without performing any other operation. + /// + /// Writers should never throw an exception from this method or any other CVssWriter(Ex)::On Xxx callback method. + /// + /// Writers should never call the CVssWriter::SetWriterFailure method from the OnIdentify or CVssWriterEx::OnIdentifyEx method. + /// + /// + /// If this method calls the CVssWriterEx2::GetSessionId method, it must do so in the same thread that called this method. For more + /// information, see Writer Event Handling. + /// + /// + /// In response to an Identify event generated by another application, a writer uses the OnIdentify handler to create a + /// Writer Metadata Document containing information about the components it manages using the IVssCreateWriterMetadata interface. + /// + /// + /// The application that generated the Identify event then retrieves the Writer Metadata Document and examines the writer's + /// component information using the IVssExamineWriterMetadata interface. + /// + /// + /// An Identify event is required before the events that make up a backup or restore sequence. Therefore, OnIdentify is + /// perhaps most typically invoked to handle an Identify event in response to a requester's call to + /// IVssBackupComponents::GatherWriterMetadata as part of a backup or restore operation. + /// + /// + /// However, an Identify event is not itself part of the sequence of events that makes up a backup or restore and the VSS service + /// does not prevent its generation, even while a backup or restore sequence is in progress. For instance, VSS management + /// applications use the Identify event to determine and display the state of the writers on the system. + /// + /// This being the case, writers should never use their implementation of OnIdentify in the following ways: + /// + /// + /// As the beginning of their handling of a backup or restore + /// + /// + /// To set or maintain information about the writer's state + /// + /// + /// See Writer Event Handling for more information on writer interactions with events. + /// The life cycle of the IVssCreateWriterMetadata object passed into OnIdentify is managed by the VSS infrastructure. + /// + virtual Boolean OnIdentify(IN IVssCreateWriterMetadata^ pMetadata) + { + UNREFERENCED_PARAMETER(pMetadata); + return true; + } + + /// + /// Returns a pointer to an IVssCreateWriterMetadataEx object. + /// OnIdentifyEx is a virtual method. It is implemented by the CVssWriterEx base class, but can be overridden by derived classes. + /// + /// A pointer to an IVssCreateWriterMetadataEx object. + /// + /// As implemented by the base class, OnIdentifyEx always returns true. + /// Any other implementation of this method must return true except in the case of a fatal error. If a fatal error occurs, the method should return false. + /// In all cases when a failure occurs, including nonfatal errors, the method should write a detailed entry to the event log to report the exact reason for the failure. + /// + /// + /// The OnIdentifyEx method is identical to the OnIdentify method, except that it returns an IVssCreateWriterMetadataEx interface pointer instead of an IVssCreateWriterMetadata interface pointer in the pMetadata parameter. A writer can override OnIdentify or OnIdentifyEx, but not both. + /// Writers should never throw an exception from this method or any other CVssWriter(Ex)::OnXxx callback method. + /// Writers should never call the CVssWriter::SetWriterFailure method from the OnIdentify or OnIdentifyEx method. + /// If this method calls the CVssWriterEx2::GetSessionId method, it must do so in the same thread that called this method. For more information, see Writer Event Handling. + /// In response to an Identify event that is generated by another application, a writer calls OnIdentifyEx to create a Writer Metadata Document that contains information about the components it manages using the IVssCreateWriterMetadataEx interface. + /// The application that generated the Identify event then retrieves the Writer Metadata Document and examines the writer's component information using the IVssExamineWriterMetadata interface. + /// An Identify event is required before the events that make up a backup or restore sequence. Therefore, OnIdentifyEx is typically called to handle an Identify event in response to a requester's call to IVssBackupComponents::GatherWriterMetadata as part of a backup or restore operation. + /// However, an Identify event by itself is not part of the sequence of events that make up a backup or restore sequence, and the VSS service does not prevent Identify events from being generated, even while a backup or restore sequence is in progress. For example, VSS management applications use the Identify event to determine and display the state of the writers on the system. + /// For this reason, writers should never use their implementation of OnIdentifyEx in any of the following ways: + /// + /// + /// As the beginning of their handling of a backup or restore sequence + /// + /// + /// To set or maintain information about the writer's state + /// + /// + /// For more information about writer interactions with events, see Writer Event Handling. + /// During the PrepareForBackup, PrepareForSnapshot, and PostSnapshot events, a writer can use the GetIdentifyInformation method to get the metadata that the writer's OnIdentifyEx method previously reported. + /// The life cycle of the IVssCreateWriterMetadataEx object that the pMetadata parameter points to is managed by the VSS infrastructure. + /// + virtual Boolean OnIdentifyEx(_In_ IVssCreateWriterMetadataEx^ pMetadata) + { + UNREFERENCED_PARAMETER(pMetadata); + return false; + } + + /// + /// The OnPrepareBackup method is called by a writer following a PrepareForBackup event. This method is used to configure a writer's state and its components in preparation for a backup operation. + /// OnPrepareBackup is a virtual method. It is implemented by the CVssWriter base class, but can be overridden by derived classes. + /// + /// Pointer to an instantiation of an IVssWriterComponents object containing the contents of the Writer Metadata Document. The value of this parameter may be NULL if the requester does not support components (if CVssWriter::AreComponentsSelected returns false). + /// + /// As implemented by the base class, OnPrepareBackup always returns true. + /// Any other implementation of this method must return true except in the case of a fatal error. If a fatal error occurs, the method must call the CVssWriter::SetWriterFailure method to provide a description of the failure before returning false. If a nonfatal error occurs, the method should still call SetWriterFailure but return true. If the error is caused by a transient problem, the method should specify VSS_E_WRITERERROR_RETRYABLE in the call to SetWriterFailure. + /// In all cases when a failure occurs, the method should write an event to the event log to report the exact reason for the failure. + /// + /// + /// The default implementation of this method by the CVssWriter base class returns true without performing any other operation. + /// OnPrepareBackup provides a writer an opportunity to more finely select what will be backed up. + /// Handling the PrepareForBackup event is the last opportunity for a writer to get access to metadata contained in the Backup Components Document prior to the shadow copy's creation. + /// Therefore, OnPrepareBackup provides an opportunity for the writer to make any final additions or updates to stored component information (using the IVssComponent interface). In particular, writer-specific metadata can be updated by IVssComponent::SetBackupMetadata or IVssComponent::SetRestoreMetadata. + /// In addition, while handling the PrepareForSnapshot event provides another opportunity in the life cycle of a VSS backup operation to perform time-consuming operations (such as synchronizing data across multiple sites), OnPrepareBackup provides a chance for the writer to start such an operation asynchronously. Tasks like these must be completed prior to the return of CVssWriter::OnPrepareSnapshot. + /// Writers should never throw an exception from this method or any other CVssWriter(Ex)::OnXxx callback method. + /// A requester generates a PrepareForBackup event, triggering a call to OnPrepareBackup, by calling IVssBackupComponents::PrepareForBackup. + /// If this method calls the CVssWriterEx2::GetSessionId, CVssWriter::SetWriterFailure, or CVssWriterEx2::SetWriterFailureEx method, it must do so in the same thread that called this method. For more information, see Writer Event Handling. + /// + virtual Boolean OnPrepareBackup(_In_ IVssWriterComponents^ pComponent) + { + UNREFERENCED_PARAMETER(pComponent); + return true; + } + + /// + /// The OnPrepareSnapshot method is called by a writer to handle a PrepareForSnapshot event. It is used to perform operations needed to prepare a writer to participate in the shadow copy or to veto a shadow copy. + /// OnPrepareSnapshot is a pure virtual method. It is not implemented by the CVssWriter base class, and must be implemented by derived classes. + /// + /// + /// The implementation of this method must return true except in the case of a fatal error. If a fatal error occurs, the method must call the CVssWriter::SetWriterFailure method to provide a description of the failure before returning false. If a nonfatal error occurs, the method should still call SetWriterFailure but return true. If the error is caused by a transient problem, the method should specify VSS_E_WRITERERROR_RETRYABLE in the call to SetWriterFailure. + /// In all cases when a failure occurs, the method should write an event to the event log to report the exact reason for the failure. + /// + /// + /// The OnPrepareSnapshot method performs operations that are required prior to any shadow copy freeze. + /// The time-out window for handling a PrepareForSnapshot event is typically longer than that for handling a Freeze event. Therefore, developers can use OnPrepareSnapshot to handle more time-consuming operations. A typical use might be for the writer to explicitly checkpoint its data. + /// Writers should never throw an exception from this method or any other CVssWriter(Ex)::OnXxx callback method. + /// If this method calls the CVssWriterEx2::GetSessionId, CVssWriter::SetWriterFailure, or CVssWriterEx2::SetWriterFailureEx method, it must do so in the same thread that called this method. For more information, see Writer Event Handling. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/vswriter/nf-vswriter-cvsswriter-onpreparesnapshot + // Platform::Boolean OnPrepareSnapshot(); + virtual Boolean OnPrepareSnapshot() = 0; + + /// + /// The OnFreeze method is called by a writer on receipt of a Freeze event at the start of a shadow copy freeze. A writer uses this method to perform operations needed to participate in the freeze or to veto the freeze. + /// OnFreeze is a pure virtual method. It is not implemented by the CVssWriter base class, and must be implemented by derived classes. + /// + /// + /// The implementation of this method must return true except in the case of a fatal error. If a fatal error occurs, the method must call the CVssWriter::SetWriterFailure method to provide a description of the failure before returning false. If a nonfatal error occurs, the method should still call SetWriterFailure but return true. If the error is caused by a transient problem, the method should specify VSS_E_WRITERERROR_RETRYABLE in the call to SetWriterFailure. + /// In all cases when a failure occurs, the method should write an event to the event log to report the exact reason for the failure. + /// + /// + /// In this method, the writer application should put itself into a well-defined state that is compatible with the VSS operation. + /// In this method, the writer should complete final preparations to support the creation of a shadow copy. Once the shadow copy is created, the writer will receive the Thaw event and can continue normal operations. + /// By default, the time-out window between Freeze and Thaw events is 60 seconds. That is, if a Thaw event is not received with the time-out window, an Abort event will be generated. Writers can change the time-out window at initialization time by setting the dwTimeoutFreeze argument to CVssWriter::Initialize. + /// How a writer prepares for a shadow copy is highly dependent on the application that hosts it. Some applications can afford to hold all writes and keep the data in an absolute consistent state for this period. Other applications, like many databases, cannot stop work during this period but can take actions, such as checkpointing their state, which may reduce the recovery time for a shadow copy created during this window. + /// If the writer cannot put itself into a well-defined state for the Freeze, the following happens: + /// + /// + /// OnFreeze should return false, vetoing the shadow copy. + /// + /// + /// The writer calls CVssWriter::SetWriterFailure to provide a description of the failure. + /// + /// + /// An Abort event will be generated upon OnFreeze return of false + /// + /// + /// Writers should never throw an exception from this method or any other CVssWriter(Ex)::OnXxx callback method. + /// The time-out window for handling the Freeze event is typically relatively short as compared to that for handling the PrepareForSnapshot event. Therefore, developers should avoid lengthy operations in this method. A typical use might be to suspend logging by the writer. + /// It is recommended that all time-consuming operations be handled by CVssWriter::OnPrepareSnapshot. + /// Either CVssWriter::OnThaw or CVssWriter::OnAbort will be called after this method. + /// If this method calls the CVssWriterEx2::GetSessionId, CVssWriter::SetWriterFailure, or CVssWriterEx2::SetWriterFailureEx method, it must do so in the same thread that called this method. For more information, see Writer Event Handling. + /// + virtual Boolean OnFreeze() = 0; + + /// + /// The OnThaw method is called by a writer following a Thaw event. + /// OnThaw is a pure virtual method. It is not implemented by the CVssWriter base class, and must be implemented by derived classes. + /// + /// + /// The implementation of this method must return true except in the case of a fatal error. If a fatal error occurs, the method must call the CVssWriter::SetWriterFailure method to provide a description of the failure before returning false. If a nonfatal error occurs, the method should still call SetWriterFailure but return true. If the error is caused by a transient problem, the method should specify VSS_E_WRITERERROR_RETRYABLE in the call to SetWriterFailure. + /// In all cases when a failure occurs, the method should write an event to the event log to report the exact reason for the failure. + /// + /// + /// This method is called at the end of a shadow copy freeze when writers can begin to modify data on disk again. + /// OnThaw is used to return the writer to normal operation, typically reversing actions taken during CVssWriter::OnPrepareSnapshot and CVssWriter::OnFreeze. + /// Final updates by the writer to the backup components metadata and cleanup (such as removing temporary files) are typically reserved for CVssWriter::OnPostSnapshot. + /// Writers should never throw an exception from this method or any other CVssWriter(Ex)::OnXxx callback method. + /// If this method calls the CVssWriterEx2::GetSessionId, CVssWriter::SetWriterFailure, or CVssWriterEx2::SetWriterFailureEx method, it must do so in the same thread that called this method. For more information, see Writer Event Handling. + /// + virtual Boolean OnThaw() = 0; + + /// + /// The OnAbort method is called by a writer following an Abort event issued by VSS indicating that a shadow copy operation has terminated prematurely. The writer uses this method to clean up from its attempt to participate in that operation. + /// OnAbort is a pure virtual method. It is not implemented by the CVssWriter base class, and must be implemented by derived classes. + /// + /// + /// The implementation of this method should return true except in the case of a fatal error. If a fatal error occurs, the method must call the CVssWriter::SetWriterFailure method to provide a description of the failure before returning false. If a nonfatal error occurs, the method should still call SetWriterFailure but return true. If the error is caused by a transient problem, the method should specify VSS_E_WRITERERROR_RETRYABLE in the call to SetWriterFailure. + /// In all cases when a failure occurs, the method should write an event to the event log to report the exact reason for the failure. + /// + /// + /// In this method, the writer should free all temporary system resources it created when preparing to participate with a VSS operation. + /// The writer will not receive further event notifications related to the VSS operation it was participating in after CVssWriter::OnAbort has been executed. + /// This method will not be called if the writer has called CVssWriter::OnPostSnapshot (that is, received notification of the end of a shadow copy). + /// An Abort event is generated when: + /// + /// + /// A writer's Freeze and Thaw event handlers (CVssWriter::OnFreeze and CVssWriter::OnThaw) return false, or cannot complete in the time window specified in CVssWriter::Initialize. + /// + /// + /// A requester explicitly generates an Abort event by calling IVssBackupComponents::AbortBackup. + /// + /// + /// There is any failure of the provider or VSS during the creation of a shadow copy following the PrepareForSnapshot event. + /// + /// + /// Writers should never throw an exception from this method or any other CVssWriter(Ex)::OnXxx callback method. + /// If this method calls the CVssWriterEx2::GetSessionId, CVssWriter::SetWriterFailure, or CVssWriterEx2::SetWriterFailureEx method, it must do so in the same thread that called this method. For more information, see Writer Event Handling. + /// + virtual Boolean OnAbort() = 0; + + /// + /// The OnBackupComplete method is called by a writer following a BackupComplete event. It is used to perform operations considered necessary following a backup. These operations cannot, however, modify the Backup Components Document. + /// OnBackupComplete is a virtual method. It is implemented by the CVssWriter base class, but can be overridden by derived classes. + /// + /// A pointer to an IVssWriterComponents object passed in by VSS to provide the method with access to the writer's component information. The value of this parameter may be NULL if the requester does not support components (if CVssWriter::AreComponentsSelected returns false). + /// + /// As implemented by the base class, OnBackupComplete always returns true. + /// Any other implementation of this method should return true except in the case of a fatal error. If a fatal error occurs, the method must call the CVssWriter::SetWriterFailure method to provide a description of the failure before returning false. If a nonfatal error occurs, the method should still call SetWriterFailure but return true. If the error is caused by a transient problem, the method should specify VSS_E_WRITERERROR_RETRYABLE in the call to SetWriterFailure. + /// In all cases when a failure occurs, the method should write an event to the event log to report the exact reason for the failure. + /// + /// + /// The default implementation of this method by CVssWriter base class returns true without performing any other operation. + /// If special operations are to be performed by the writer at the end of a backup, the default implementation can be overridden. + /// With the generation of a BackupComplete event, a requester's Backup Components Document becomes a read-only document. Therefore, attempts to modify the document through the interface (for instance, calling IVssComponent::SetBackupMetadata) will fail in user implementations of OnBackupComplete. + /// A successful backup application will generate a BackupComplete event when all data has been saved to backup media. + /// However, there is no guarantee of the writer receiving a BackupComplete event notification, because these require the backup application to either successfully complete the backup or fail gracefully. + /// A BackupComplete event could fail to be generated should the backup application be terminated by the system or manually prior to the completion of the backup (for instance, if the backup operation hung and had to be shut down). + /// A writer should maintain state information so that it can track whether a BackupComplete event was sent for a given shadow copy set. + /// This information can be used by a writer's BackupShutdown event handler (CVssWriter::OnBackupShutdown), which will be called when a backup application actually terminates and its IVssBackupComponents is released, to perform cleanup operations should there be no call to OnBackupComplete. + /// Writers should never throw an exception from this method or any other CVssWriter(Ex)::OnXxx callback method. + /// If this method calls the CVssWriterEx2::GetSessionId, CVssWriter::SetWriterFailure, or CVssWriterEx2::SetWriterFailureEx method, it must do so in the same thread that called this method. For more information, see Writer Event Handling. + /// + virtual Boolean OnBackupComplete(_In_ IVssWriterComponents^ pComponent) + { + UNREFERENCED_PARAMETER(pComponent); + return true; + } + + /// + /// The OnBackupShutdown method is called by a writer following a BackupShutdown event. It is used to perform operations considered necessary when a backup application shuts down, particularly in the case of a crash of the backup application. + /// OnBackupShutdown is a virtual method. It is implemented by the CVssWriter base class, but can be overridden by derived classes. + /// + /// Identifier for the shadow copy set involved in the backup operation. + /// + /// As implemented by the base class, OnBackupShutdown always returns true + /// Any other implementation of this method should return true except in the case of a fatal error. If a fatal error occurs, the method must call the CVssWriter::SetWriterFailure method to provide a description of the failure before returning false. If a nonfatal error occurs, the method should still call SetWriterFailure but return true. If the error is caused by a transient problem, the method should specify VSS_E_WRITERERROR_RETRYABLE in the call to SetWriterFailure. + /// In all cases when a failure occurs, the method should write an event to the event log to report the exact reason for the failure. + /// + /// + /// The default implementation of this method by the CVssWriter base class returns true without performing any other operation. + /// If special operations are to be performed by the writer when a backup application shuts down, the default implementation can be overridden. + /// If no shadow copy has been successfully performed, the value of the shadow copy set identifier (SnapshotSetId) will be NULL. + /// A BackupShutdown event will be generated whenever a backup application actually terminates and its IVssBackupComponents is released. + /// The BackupComplete event requires the backup application to either successfully complete the backup or fail gracefully; this may not be the case if the backup application is terminated by the system or terminated manually prior to the completion of the backup (for instance, if the backup operation hung and had to be shut down). + /// Because of this, a BackupShutdown event is a more robust signal of the end of a backup application than the BackupComplete event. + /// A writer should maintain state information so that it can track whether a BackupComplete event was sent for a given shadow copy set. + /// Any writer-specific implementation of OnBackupShutdown should check whether a BackupComplete event was handled. It should ensure that all necessary writer cleanup operations following a backup (successful or otherwise) are preformed. + /// Writers should never throw an exception from this method or any other CVssWriter(Ex)::OnXxx callback method. + /// If this method calls the CVssWriterEx2::GetSessionId, CVssWriter::SetWriterFailure, or CVssWriterEx2::SetWriterFailureEx method, it must do so in the same thread that called this method. For more information, see Writer Event Handling. + /// + virtual Boolean OnBackupShutdown(_In_ Guid SnapshotSetId) + { + UNREFERENCED_PARAMETER(SnapshotSetId); + return true; + } + + /// + /// The OnPreRestore method is called by a writer following a PreRestore event. This method is used to put the writer in a state to support the restore—for instance, taking database services offline—and to make modifications in the Backup Components Document of the requester that is restoring files (such as setting the restore target to override the original restore method). + /// OnPreRestore is a virtual method. It is implemented by the CVssWriter base class, but can be overridden by derived classes. + /// + /// Pointer to an instantiation of an IVssWriterComponents object containing those components associated with the current writer in the requester's Backup Components Document. + /// + /// As implemented by the base class, OnPreRestore always returns true. + /// Any other implementation of this method must return true except in the case of a fatal error. If a fatal error occurs, the method must call the CVssWriter::SetWriterFailure method to provide a description of the failure before returning false. If a nonfatal error occurs, the method should still call SetWriterFailure but return true. If the error is caused by a transient problem, the method should specify VSS_E_WRITERERROR_RETRYABLE in the call to SetWriterFailure. + /// In all cases when a failure occurs, the method should write an event to the event log to report the exact reason for the failure. + /// + /// + /// The PreRestore event occurs before backed-up data is actually being restored. This is an opportunity for the writer to determine what is being restored. + /// The default implementation of this method by the CVssWriter base class returns true without performing any other operation. + /// This method enables the writer to determine what is being restored, to retrieve stored private metadata in the stored Backup Components Document, and to update that data. + /// Writers should never throw an exception from this method or any other CVssWriter(Ex)::OnXxx callback method. + /// If this method calls the CVssWriterEx2::GetSessionId, CVssWriter::SetWriterFailure, or CVssWriterEx2::SetWriterFailureEx method, it must do so in the same thread that called this method. For more information, see Writer Event Handling. + /// + virtual Boolean OnPreRestore(_In_ IVssWriterComponents^ pComponent) + { + UNREFERENCED_PARAMETER(pComponent); + return true; + } + + /// + /// The OnPostRestore method is called by a writer following a PostRestore event. It is used to perform operations considered necessary after files are restored to disk by a requester. These operations cannot, however, modify the Backup Components Document. + /// OnPostRestore is a virtual method. It is implemented by the CVssWriter base class, but can be overridden by derived classes. + /// + /// A pointer to an IVssWriterComponents object passed in by VSS to provide the method with access to the writer's component information. The value of this parameter may be NULL if the requester does not support components (if CVssWriter::AreComponentsSelected returns false). + /// + /// As implemented by the base class, OnPostRestore always returns true. + /// Any other implementation of this method must return true except in the case of a fatal error. If a fatal error occurs, the method must call the CVssWriter::SetWriterFailure method to provide a description of the failure before returning false. If a nonfatal error occurs, the method should still call SetWriterFailure but return true. If the error is caused by a transient problem, the method should specify VSS_E_WRITERERROR_RETRYABLE in the call to SetWriterFailure. + /// In all cases when a failure occurs, the method should write an event to the event log to report the exact reason for the failure. + /// + /// + /// The default implementation of this method by the CVssWriter base class returns true without performing any other operation. + /// If necessary, a writer should remove any temporary files and release any system resources that it needed for its participation in the restore. + /// Writers should never throw an exception from this method or any other CVssWriter(Ex)::OnXxx callback method. + /// With the generation of a PostRestore event, a requester's Backup Components Document becomes a read-only document. Therefore, attempts to modify the document through the interface (for instance, calling IVssComponent::SetRestoreMetadata) will fail in user implementations of OnPostRestore. + /// If this method calls the CVssWriterEx2::GetSessionId, CVssWriter::SetWriterFailure, or CVssWriterEx2::SetWriterFailureEx method, it must do so in the same thread that called this method. For more information, see Writer Event Handling. + /// + virtual Boolean OnPostRestore(_In_ IVssWriterComponents^ pComponent) + { + UNREFERENCED_PARAMETER(pComponent); + return true; + } + + /// + /// The OnPostSnapshot method is called by a writer following a PostSnapshot event. + /// OnPostSnapshot is a virtual method. It is implemented by the CVssWriter base class but can be overridden by derived classes. + /// + /// A pointer to an IVssWriterComponents object passed in by VSS to provide the method with access to the writer's component information. The value of this parameter may be NULL if the requester does not support components (if CVssWriter::AreComponentsSelected returns false). + /// + /// As implemented by the base class, OnPostSnapshot always returns true. + /// Any other implementation of this method must return true except in the case of a fatal error. If a fatal error occurs, the method must call the CVssWriter::SetWriterFailure method to provide a description of the failure before returning false. If a nonfatal error occurs, the method should still call SetWriterFailure but return true. If the error is caused by a transient problem, the method should specify VSS_E_WRITERERROR_RETRYABLE in the call to SetWriterFailure. + /// In all cases when a failure occurs, the method should write an event to the event log to report the exact reason for the failure. + /// + /// + /// The default implementation of this method by the CVssWriter base class returns true without performing any other operation. + /// CVssWriter::OnPostSnapshot is typically used to process any final updates by the writer to the backup components metadata and clean up (such as removing temporary files). + /// If an incremental or differential backup is being performed, the writer may call IVssComponent::GetPreviousBackupStamp and IVssComponent::SetBackupStamp. For more information, see Writer Role in Backing Up Complex Stores. Another method that can be called at this time is IVssComponent::AddDifferencedFilesByLastModifyTime. + /// Most of the work needed to return the writer to normal operation (reversing the actions of CVssWriter::OnPrepareSnapshot and CVssWriter::OnFreeze) is typically performed in CVssWriter::OnThaw, not in OnPostSnapshot. + /// Writers should never throw an exception from this method or any other CVssWriter(Ex)::OnXxx callback method. + /// If the shadow copy has the VSS_VOLSNAP_ATTR_AUTORECOVER flag set in the context, the writer should perform any recovery required (for example, rolling back any incomplete transactions) so that the component will be usable on a read-only copy for data mining (without adding load to the live server) or restore purposes (for example, to restore selected items from a database). + /// To retrieve the volume name of the shadow copy of a volume, perform the following steps: + /// + /// + /// Call the CVssWriter::GetCurrentVolumeCount method to query the number of volumes in the shadow copy set. + /// + /// + /// Call the CVssWriter::GetCurrentVolumeArray method to enumerate the original names of the volumes in the shadow copy set. + /// + /// + /// Call the CVssWriter::GetSnapshotDeviceName to retrieve the name of the shadow copy volume. + /// + /// + /// If this method calls the CVssWriterEx2::GetSessionId, CVssWriter::SetWriterFailure, or CVssWriterEx2::SetWriterFailureEx method, it must do so in the same thread that called this method. For more information, see Writer Event Handling. + /// + virtual Boolean OnPostSnapshot(_In_ IVssWriterComponents^ pComponent) + { + UNREFERENCED_PARAMETER(pComponent); + return true; + } + + /// + /// Not supported. + /// This method is reserved for future use. + /// + /// This parameter is reserved for future use. + /// This parameter is reserved for future use. + /// This parameter is reserved for future use. + /// This method does not return a value. + virtual Boolean OnBackOffIOOnVolume(_In_ String^ wszVolumeName, _In_ Guid snapshotId, _In_ Guid providerId) + { + UNREFERENCED_PARAMETER(wszVolumeName); + UNREFERENCED_PARAMETER(snapshotId); + UNREFERENCED_PARAMETER(providerId); + + return true; + } + + /// + /// Not supported. + /// This method is reserved for future use. + /// + /// This parameter is reserved for future use. + /// This parameter is reserved for future use. + /// This parameter is reserved for future use. + /// This method does not return a value. + virtual Boolean OnContinueIOOnVolume(_In_ String^ wszVolumeName, _In_ Guid snapshotId, _In_ Guid providerId) + { + UNREFERENCED_PARAMETER(wszVolumeName); + UNREFERENCED_PARAMETER(snapshotId); + UNREFERENCED_PARAMETER(providerId); + + return true; + } + + /// + /// Not supported. + /// This method is reserved for future use. + /// + /// This method does not return a value. + virtual Boolean OnVSSShutdown() + { + return true; + } + + /// + /// Not supported. + /// This method is reserved for future use. + /// + /// This method does not return a value. + virtual Boolean OnVSSApplicationStartup() + { + return true; + } + + /// Sets extended error information to indicate that the writer has encountered a problem with participating in a VSS operation. + /// + /// The error code to be returned to the requester. + /// The following are the error codes that this method can set. + /// + /// + /// Value + /// Meaning + /// + /// + /// S_OK + /// The writer was successful. + /// + /// + /// VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT + /// The shadow copy contains only a subset of the volumes needed by the writer to correctly back up the application component. + /// + /// + /// VSS_E_WRITERERROR_OUTOFRESOURCES + /// The writer ran out of memory or other system resources. The recommended way to handle this error code is to wait ten minutes and then repeat the operation, up to three times. + /// + /// + /// VSS_E_WRITERERROR_TIMEOUT + /// The writer operation failed because of a time-out between the Freeze and Thaw events. The recommended way to handle this error code is to wait ten minutes and then repeat the operation, up to three times. + /// + /// + /// VSS_E_WRITERERROR_RETRYABLE + /// The writer failed due to an error that would likely not occur if the entire backup, restore, or shadow copy creation process was restarted. The recommended way to handle this error code is to wait ten minutes and then repeat the operation, up to three times. + /// + /// + /// VSS_E_WRITERERROR_NONRETRYABLE + /// The writer operation failed because of an error that might recur if another shadow copy is created. For more information, see Event and Error Handling Under VSS. + /// + /// + /// VSS_E_WRITERERROR_PARTIAL_FAILURE + /// The writer is reporting one or more component-level errors. To report the errors, the writer must use the IVssComponentEx2::SetFailure method. + /// + /// + /// + /// An additional error code to be returned to the requester. This parameter is optional. + /// A string containing an error message for the requester to display to the end user. The writer is responsible for localizing this string if necessary before using it in this method. This parameter is optional and can be NULL or an empty string. + /// + /// This method cannot be called from CVssWriter::OnIdentify or CVssWriterEx::OnIdentifyEx. + /// To report component-level errors, writers should use the IVssComponentEx2::SetFailure method. + /// If a writer's event handler (such as CVssWriter::OnFreeze) calls this method, it must do so in the same thread that called the event handler. For more information, see Writer Event Handling. + /// + void SetWriterFailureEx(_In_ HRESULT hrWriter, _In_ HRESULT hrApplication, [Optional] _In_ String^ wszApplicationMessage) + { + Utils::ThrowIfFailed(pNative->SetWriterFailureEx((UInt32)hrWriter, (UInt32)hrApplication, SafeWString(wszApplicationMessage))); + } + + /// + /// The Subscribe method subscribes the writer with VSS. + /// Subscribe is a public method implemented by the base class. + /// + /// + /// A bit mask (or bitwise OR) of VSS_SUBSCRIBE_MASK values indicating the events that VSS should notify the writer about. + /// + /// The default value for this argument is (VSS_SM_BACKUP_EVENTS_FLAG | VSS_SM_RESTORE_EVENTS_FLAG). Currently, the caller should + /// not override the default value. + /// + /// This parameter is reserved for future use. + /// + void Subscribe(VSS_SUBSCRIBE_MASK dwEventFlags) + { + Utils::ThrowIfFailed(pNative->Subscribe((DWORD)dwEventFlags)); + } + + /// + /// The Unsubscribe method unsubscribes the writer with VSS. + /// Unsubscribe is a public method implemented by the CVssWriter base class. + /// + void Unsubscribe() + { + Utils::ThrowIfFailed(pNative->Unsubscribe()); + } + + }; + +}}} diff --git a/PInvoke/VssApi/VssApi.cpp b/PInvoke/VssApi/VssApi.cpp new file mode 100644 index 00000000..a541a9f9 --- /dev/null +++ b/PInvoke/VssApi/VssApi.cpp @@ -0,0 +1,4 @@ +#include "pch.h" + +#include "VssApi.h" + diff --git a/PInvoke/VssApi/VssApi.h b/PInvoke/VssApi/VssApi.h new file mode 100644 index 00000000..3f59c932 --- /dev/null +++ b/PInvoke/VssApi/VssApi.h @@ -0,0 +1,2 @@ +#pragma once + diff --git a/PInvoke/VssApi/VssApi.vcxproj b/PInvoke/VssApi/VssApi.vcxproj new file mode 100644 index 00000000..6e8657b0 --- /dev/null +++ b/PInvoke/VssApi/VssApi.vcxproj @@ -0,0 +1,176 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4} + NetCoreCProj + VssApi + 10.0 + net5.0 + Vanara.PInvoke.VssApi + + + + DynamicLibrary + true + v142 + NetCore + Unicode + + + DynamicLibrary + false + v142 + NetCore + Unicode + + + DynamicLibrary + true + v142 + NetCore + Unicode + + + DynamicLibrary + false + v142 + NetCore + Unicode + + + + + + + + + + + + + + + + + + + + + Vanara.PInvoke.VssApi + + + + Use + pch.h + Level3 + WIN32;_DEBUG;%(PreprocessorDefinitions) + + + vssapi.lib + + + + + Use + pch.h + Level3 + _DEBUG;%(PreprocessorDefinitions) + + + + + + + + Use + pch.h + Level3 + WIN32;NDEBUG;%(PreprocessorDefinitions) + + + + + + + + Use + pch.h + Level3 + NDEBUG;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + ..\..\..\..\GitHubRepos\Vanara\PInvoke\VssApi\bin\Debug\net5.0\Vanara.Core.dll + false + false + + + ..\..\..\..\GitHubRepos\Vanara\PInvoke\VssApi\bin\Debug\net5.0\Vanara.PInvoke.Shared.dll + false + false + + + ..\..\..\..\GitHubRepos\Vanara\PInvoke\VssApi\bin\Debug\net5.0\Vanara.PInvoke.VssApi.dll + false + false + + + + + + \ No newline at end of file diff --git a/PInvoke/VssApi/VssApi.vcxproj.filters b/PInvoke/VssApi/VssApi.vcxproj.filters new file mode 100644 index 00000000..29eff3ea --- /dev/null +++ b/PInvoke/VssApi/VssApi.vcxproj.filters @@ -0,0 +1,87 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Resource Files + + + + + Resource Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/PInvoke/VssApi/VssFactory.cpp b/PInvoke/VssApi/VssFactory.cpp new file mode 100644 index 00000000..348e7916 --- /dev/null +++ b/PInvoke/VssApi/VssFactory.cpp @@ -0,0 +1,34 @@ +#include "pch.h" +#include "VssFactory.h" + +using namespace System; +using namespace Runtime::InteropServices; + +namespace Vanara { namespace PInvoke { namespace VssApi { + + HRESULT Vanara::PInvoke::VssApi::VssFactory::CreateVssBackupComponents(Vanara::PInvoke::VssApi::IVssBackupComponents^% ppBackup) + { + SafeComPtr<::IVssBackupComponents*> pBC; + auto hr = ::CreateVssBackupComponents(&pBC); + ppBackup = hr >= 0 ? gcnew Vanara::PInvoke::VssApi::CVssBackupComponents(pBC) : nullptr; + return HRESULT(hr); + } + + HRESULT Vanara::PInvoke::VssApi::VssFactory::CreateVssExamineWriterMetadata(String^ bstrXML, Vanara::PInvoke::VssApi::IVssExamineWriterMetadata^% ppMetadata) + { + SafeBSTR bstr = (BSTR)Marshal::StringToBSTR(bstrXML).ToPointer(); + SafeComPtr<::IVssExamineWriterMetadata*> pMeta; + auto hr = ::CreateVssExamineWriterMetadata(bstr, &pMeta); + ppMetadata = hr >= 0 ? gcnew Vanara::PInvoke::VssApi::CVssExamineWriterMetadata(pMeta) : nullptr; + return HRESULT(hr); + } + + HRESULT Vanara::PInvoke::VssApi::VssFactory::CreateVssExpressWriter(Vanara::PInvoke::VssApi::IVssExpressWriter^% ppWriter) + { + SafeComPtr<::IVssExpressWriter*> pWriter; + auto hr = ::CreateVssExpressWriter(&pWriter); + ppWriter = hr >= 0 ? gcnew Vanara::PInvoke::VssApi::CVssExpressWriter(pWriter) : nullptr; + return HRESULT(hr); + } + +}}} diff --git a/PInvoke/VssApi/VssFactory.h b/PInvoke/VssApi/VssFactory.h new file mode 100644 index 00000000..93ce1ca8 --- /dev/null +++ b/PInvoke/VssApi/VssFactory.h @@ -0,0 +1,160 @@ +#pragma once +#include "pch.h" +#include "vswriter.h" +#include "vsbackup.h" + +using namespace System; +using namespace Runtime::InteropServices; + +namespace Vanara { namespace PInvoke { namespace VssApi { + + public ref class VssFactory sealed + { + public: + /// The CreateVssExamineWriterMetadata function creates an IVssExamineWriterMetadata object. + /// + /// An XML string containing a Writer Metadata Document with which to initialize the returned IVssExamineWriterMetadata object. + /// + /// A variable that receives an IVssExamineWriterMetadata interface pointer to the object. + /// + /// The return values listed here are in addition to the normal COM HRESULTs that may be returned at any time from the function. + /// + /// + /// Value + /// Meaning + /// + /// + /// S_OK + /// Successfully returned a pointer to an IVssExamineWriterMetadata interface. + /// + /// + /// E_ACCESSDENIED + /// The caller does not have sufficient backup privileges or is not an administrator. + /// + /// + /// E_INVALIDARG + /// One of the parameters is not valid. + /// + /// + /// E_OUTOFMEMORY + /// Out of memory or other system resources. + /// + /// + /// VSS_E_INVALID_XML_DOCUMENT + /// + /// The XML document passed in the bstrXML parameter is not valid—that is, either it is not a correctly formed XML string or it does + /// not match the schema. + /// + /// + /// + /// VSS_E_UNEXPECTED + /// + /// Unexpected error. The error code is logged in the error log file. For more information, see Event and Error Handling Under VSS. + /// Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This value is not supported until Windows Server 2008 R2 + /// and Windows 7. E_UNEXPECTED is used instead. + /// + /// + /// + /// + /// + /// + /// To save a copy of a writer’s Writer Metadata Document into an XML string to pass in the bstrXML parameter, use the + /// IVssExamineWriterMetadata::SaveAsXML method. + /// + /// + /// To retrieve the latest version of a writer’s Writer Metadata Document, use the IVssBackupComponents::GetWriterMetadata method. + /// + /// + /// To load a writer metadata document into an existing IVssExamineWriterMetadata object, use the + /// IVssExamineWriterMetadata::LoadFromXML method. + /// + /// Users should not attempt to modify the contents of the Writer Metadata Document. + /// + /// The calling application is responsible for calling IUnknown::Release to release the resources held by the + /// IVssExamineWriterMetadata object when the object is no longer needed. + /// + /// + [PInvokeData("vsbackup.h", MSDNShortId = "NF:vsbackup.CreateVssExamineWriterMetadata")] + static HRESULT CreateVssExamineWriterMetadata(String^ bstrXML, [Runtime::InteropServices::Out] Vanara::PInvoke::VssApi::IVssExamineWriterMetadata^% ppMetadata); + + /// Creates an IVssExpressWriter interface object and returns a pointer to it. + /// Doubly indirect pointer to the newly created IVssExpressWriter object. + /// + /// + /// The return values listed here are in addition to the normal COM HRESULT values that may be returned at any time from the function. + /// + /// + /// + /// Value + /// Meaning + /// + /// + /// S_OK + /// Successfully returned a pointer to an IVssExpressWriter interface. + /// + /// + /// E_ACCESSDENIED + /// The caller does not have sufficient privileges. + /// + /// + /// E_INVALIDARG + /// One of the parameters is not valid. + /// + /// + /// + // https://docs.microsoft.com/en-us/windows/win32/api/vswriter/nf-vswriter-createvssexpresswriter HRESULT CreateVssExpressWriter( + // [out] IVssExpressWriter **ppWriter ); + [PInvokeData("vswriter.h", MSDNShortId = "NF:vswriter.CreateVssExpressWriter")] + static HRESULT CreateVssExpressWriter([Runtime::InteropServices::Out] Vanara::PInvoke::VssApi::IVssExpressWriter^% ppWriter); + + /// + /// + /// The CreateVssBackupComponents function creates an IVssBackupComponents interface object and returns a pointer to it. + /// + /// + /// Doubly indirect pointer to the created IVssBackupComponents interface object. + /// + /// + /// The return values listed here are in addition to the normal COM HRESULT s that may be returned at any time from the function. + /// + /// + /// + /// Value + /// Meaning + /// + /// + /// S_OK + /// Successfully returned a pointer to an IVssBackupComponents interface. + /// + /// + /// E_ACCESSDENIED + /// The caller does not have sufficient backup privileges or is not an administrator. + /// + /// + /// E_INVALIDARG + /// One of the parameters is not valid. + /// + /// + /// E_OUTOFMEMORY + /// Out of memory or other system resources. + /// + /// + /// VSS_E_UNEXPECTED + /// + /// Unexpected error. The error code is logged in the error log file. For more information, see Event and Error Handling Under VSS. + /// Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This value is not supported until Windows Server 2008 R2 + /// and Windows 7. E_UNEXPECTED is used instead. + /// + /// + /// + /// + /// + /// The calling application is responsible for calling IUnknown::Release to release the resources held by the returned + /// IVssBackupComponents when it is no longer needed. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/vsbackup/nf-vsbackup-createvssbackupcomponents HRESULT + // CreateVssBackupComponents( [out] IVssBackupComponents **ppBackup); + [PInvokeData("vsbackup.h", MSDNShortId = "NF:vsbackup.CreateVssBackupComponents")] + static HRESULT CreateVssBackupComponents([Runtime::InteropServices::Out] Vanara::PInvoke::VssApi::IVssBackupComponents^% ppBackup); + }; +}}} diff --git a/PInvoke/VssApi/app.ico b/PInvoke/VssApi/app.ico new file mode 100644 index 00000000..789d7ccb Binary files /dev/null and b/PInvoke/VssApi/app.ico differ diff --git a/PInvoke/VssApi/app.rc b/PInvoke/VssApi/app.rc new file mode 100644 index 00000000..eab43064 Binary files /dev/null and b/PInvoke/VssApi/app.rc differ diff --git a/PInvoke/VssApi/pch.cpp b/PInvoke/VssApi/pch.cpp new file mode 100644 index 00000000..64b7eef6 --- /dev/null +++ b/PInvoke/VssApi/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: source file corresponding to the pre-compiled header + +#include "pch.h" + +// When you are using pre-compiled headers, this source file is necessary for compilation to succeed. diff --git a/PInvoke/VssApi/pch.h b/PInvoke/VssApi/pch.h new file mode 100644 index 00000000..7cec420e --- /dev/null +++ b/PInvoke/VssApi/pch.h @@ -0,0 +1,23 @@ +// pch.h: This is a precompiled header file. +// Files listed below are compiled only once, improving build performance for future builds. +// This also affects IntelliSense performance, including code completion and many code browsing features. +// However, files listed here are ALL re-compiled if any one of them is updated between builds. +// Do not add files here that you will be updating frequently as this negates the performance advantage. + +#ifndef PCH_H +#define PCH_H + +// add headers that you want to pre-compile here +#define WINVER 0x0502 +#define _AFXDLL +#include +#include +#include +#include +#include +#include "SafePtr.h" +#include "BaseWrapper.h" +#include "Utils.h" +#include "Macros.h" + +#endif //PCH_H diff --git a/PInvoke/VssApi/Vanara.PInvoke.VssApi.csproj b/PInvoke/VssApiMgd/Vanara.PInvoke.VssApiMgd.csproj similarity index 100% rename from PInvoke/VssApi/Vanara.PInvoke.VssApi.csproj rename to PInvoke/VssApiMgd/Vanara.PInvoke.VssApiMgd.csproj diff --git a/PInvoke/VssApi/vdslun.cs b/PInvoke/VssApiMgd/vdslun.cs similarity index 100% rename from PInvoke/VssApi/vdslun.cs rename to PInvoke/VssApiMgd/vdslun.cs diff --git a/PInvoke/VssApi/vsadmin.cs b/PInvoke/VssApiMgd/vsadmin.cs similarity index 100% rename from PInvoke/VssApi/vsadmin.cs rename to PInvoke/VssApiMgd/vsadmin.cs diff --git a/PInvoke/VssApi/vsbackup.cs b/PInvoke/VssApiMgd/vsbackup.cs similarity index 100% rename from PInvoke/VssApi/vsbackup.cs rename to PInvoke/VssApiMgd/vsbackup.cs diff --git a/PInvoke/VssApi/vsmgmt.cs b/PInvoke/VssApiMgd/vsmgmt.cs similarity index 100% rename from PInvoke/VssApi/vsmgmt.cs rename to PInvoke/VssApiMgd/vsmgmt.cs diff --git a/PInvoke/VssApi/vsprov.cs b/PInvoke/VssApiMgd/vsprov.cs similarity index 100% rename from PInvoke/VssApi/vsprov.cs rename to PInvoke/VssApiMgd/vsprov.cs diff --git a/PInvoke/VssApi/vss.cs b/PInvoke/VssApiMgd/vss.cs similarity index 100% rename from PInvoke/VssApi/vss.cs rename to PInvoke/VssApiMgd/vss.cs diff --git a/PInvoke/VssApi/vswriter.cs b/PInvoke/VssApiMgd/vswriter.cs similarity index 100% rename from PInvoke/VssApi/vswriter.cs rename to PInvoke/VssApiMgd/vswriter.cs diff --git a/Vanara.sln b/Vanara.sln index 628f6b75..bd11bebf 100644 --- a/Vanara.sln +++ b/Vanara.sln @@ -85,63 +85,63 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnitTests", "UnitTests", "{ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core", "UnitTests\Core\Core.csproj", "{8EDF4429-251A-416D-BB68-93F227191BCF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Security", "UnitTests\Security\Security.csproj", "{31F68B09-2933-45A1-B86B-9F6D647ED2D9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Security", "UnitTests\Security\Security.csproj", "{31F68B09-2933-45A1-B86B-9F6D647ED2D9}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System", "UnitTests\System\System.csproj", "{9AEC2C7E-09D3-41C7-BDA7-4A7BAAA3441E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Windows.Forms", "UnitTests\Windows.Forms\Windows.Forms.csproj", "{C1FFE607-1D85-49F8-9421-6B21AB778816}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Windows.Forms", "UnitTests\Windows.Forms\Windows.Forms.csproj", "{C1FFE607-1D85-49F8-9421-6B21AB778816}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Windows.Shell", "UnitTests\Windows.Shell\Windows.Shell.csproj", "{2616C074-DF6C-47D4-BE82-6768885ACAC9}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PInvoke", "PInvoke", "{385CAD2D-0A5E-4F80-927B-D5499D126B90}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AclUI", "UnitTests\PInvoke\AclUI\AclUI.csproj", "{81A79BCD-C322-4742-842E-F70344FAD01D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AclUI", "UnitTests\PInvoke\AclUI\AclUI.csproj", "{81A79BCD-C322-4742-842E-F70344FAD01D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComCtl32", "UnitTests\PInvoke\ComCtl32\ComCtl32.csproj", "{FC54780C-E523-450E-BC74-1F900A652A2C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComCtl32", "UnitTests\PInvoke\ComCtl32\ComCtl32.csproj", "{FC54780C-E523-450E-BC74-1F900A652A2C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CredUI", "UnitTests\PInvoke\CredUI\CredUI.csproj", "{D26F23F2-35E8-4253-BCEF-56F113C93B02}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CredUI", "UnitTests\PInvoke\CredUI\CredUI.csproj", "{D26F23F2-35E8-4253-BCEF-56F113C93B02}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cryptography", "UnitTests\PInvoke\Cryptography\Cryptography.csproj", "{D2F143F6-25E8-4B00-A260-B3E3AA46960F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cryptography", "UnitTests\PInvoke\Cryptography\Cryptography.csproj", "{D2F143F6-25E8-4B00-A260-B3E3AA46960F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DwmApi", "UnitTests\PInvoke\DwmApi\DwmApi.csproj", "{495E0181-1513-423C-8056-A5EE400FA066}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DwmApi", "UnitTests\PInvoke\DwmApi\DwmApi.csproj", "{495E0181-1513-423C-8056-A5EE400FA066}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gdi32", "UnitTests\PInvoke\Gdi32\Gdi32.csproj", "{A1A941E2-CF51-4582-B8B3-5CBC8905CA8D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Gdi32", "UnitTests\PInvoke\Gdi32\Gdi32.csproj", "{A1A941E2-CF51-4582-B8B3-5CBC8905CA8D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IpHlpApi", "UnitTests\PInvoke\IpHlpApi\IpHlpApi.csproj", "{FB4E72CC-FF45-4A75-84FB-D220E0C06698}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IpHlpApi", "UnitTests\PInvoke\IpHlpApi\IpHlpApi.csproj", "{FB4E72CC-FF45-4A75-84FB-D220E0C06698}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kernel32", "UnitTests\PInvoke\Kernel32\Kernel32.csproj", "{EF6CA228-59F6-495B-8F59-372690E68650}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mpr", "UnitTests\PInvoke\Mpr\Mpr.csproj", "{A300ACD4-2E77-4649-B773-2DD55CDB9573}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mpr", "UnitTests\PInvoke\Mpr\Mpr.csproj", "{A300ACD4-2E77-4649-B773-2DD55CDB9573}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetApi32", "UnitTests\PInvoke\NetApi32\NetApi32.csproj", "{2043D4AA-5286-491F-A334-A3CC7A08DB56}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetApi32", "UnitTests\PInvoke\NetApi32\NetApi32.csproj", "{2043D4AA-5286-491F-A334-A3CC7A08DB56}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetListMgr", "UnitTests\PInvoke\NetListMgr\NetListMgr.csproj", "{969234E4-6C92-4DAD-9AB9-25E618906643}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetListMgr", "UnitTests\PInvoke\NetListMgr\NetListMgr.csproj", "{969234E4-6C92-4DAD-9AB9-25E618906643}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NtDll", "UnitTests\PInvoke\NtDll\NtDll.csproj", "{6DD8BB87-AFBB-4E20-87CA-82967D01EF2D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NtDll", "UnitTests\PInvoke\NtDll\NtDll.csproj", "{6DD8BB87-AFBB-4E20-87CA-82967D01EF2D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NTDSApi", "UnitTests\PInvoke\NTDSApi\NTDSApi.csproj", "{D7E06BE2-1BAC-4016-8228-FAA091ED4831}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NTDSApi", "UnitTests\PInvoke\NTDSApi\NTDSApi.csproj", "{D7E06BE2-1BAC-4016-8228-FAA091ED4831}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ole", "UnitTests\PInvoke\Ole\Ole.csproj", "{BB78D331-8903-40CE-90C4-B0E77D7B20FB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowrProf", "UnitTests\PInvoke\PowrProf\PowrProf.csproj", "{BAD9E08F-4001-4294-804D-7421012DAA3D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowrProf", "UnitTests\PInvoke\PowrProf\PowrProf.csproj", "{BAD9E08F-4001-4294-804D-7421012DAA3D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Security", "UnitTests\PInvoke\Security\Security.csproj", "{C580868E-D913-454C-BF9B-CAFE3BD28DF0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Security", "UnitTests\PInvoke\Security\Security.csproj", "{C580868E-D913-454C-BF9B-CAFE3BD28DF0}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shared", "UnitTests\PInvoke\Shared\Shared.csproj", "{6F668E05-8141-48B8-9031-326C79745AF4}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shell32", "UnitTests\PInvoke\Shell32\Shell32.csproj", "{40E5CA4E-527F-4F79-875D-2342D1136FDD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TaskSchd", "UnitTests\PInvoke\TaskSchd\TaskSchd.csproj", "{85157400-A6FF-41E7-B650-4952ECBC28AD}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TaskSchd", "UnitTests\PInvoke\TaskSchd\TaskSchd.csproj", "{85157400-A6FF-41E7-B650-4952ECBC28AD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "User32", "UnitTests\PInvoke\User32\User32.csproj", "{60A80A72-67BD-4CC2-95DA-0F6D3553A221}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "User32", "UnitTests\PInvoke\User32\User32.csproj", "{60A80A72-67BD-4CC2-95DA-0F6D3553A221}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UxTheme", "UnitTests\PInvoke\UxTheme\UxTheme.csproj", "{EFAFBD16-A9FB-4656-896D-AD434B778EF0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UxTheme", "UnitTests\PInvoke\UxTheme\UxTheme.csproj", "{EFAFBD16-A9FB-4656-896D-AD434B778EF0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtDisk", "UnitTests\PInvoke\VirtDisk\VirtDisk.csproj", "{6947F255-E176-409C-9788-9C02A68C9D3B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtDisk", "UnitTests\PInvoke\VirtDisk\VirtDisk.csproj", "{6947F255-E176-409C-9788-9C02A68C9D3B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinINet", "UnitTests\PInvoke\WinINet\WinINet.csproj", "{A4BF5AA2-4D73-4BE7-ABB4-3DC089CFA77A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinINet", "UnitTests\PInvoke\WinINet\WinINet.csproj", "{A4BF5AA2-4D73-4BE7-ABB4-3DC089CFA77A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ws2_32", "UnitTests\PInvoke\Ws2_32\Ws2_32.csproj", "{15DC485D-B379-4087-97A7-981ADB4D48F9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ws2_32", "UnitTests\PInvoke\Ws2_32\Ws2_32.csproj", "{15DC485D-B379-4087-97A7-981ADB4D48F9}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.Accessibility", "PInvoke\Accessibility\Vanara.PInvoke.Accessibility.csproj", "{D5BD6ECE-B285-4CE8-ABFC-964AB1DEA464}" EndProject @@ -155,27 +155,27 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.Wer", "PInvo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.KtmW32", "PInvoke\KtmW32\Vanara.PInvoke.KtmW32.csproj", "{C325C0A4-B8CF-442B-B393-C65FC9174045}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KtmW32", "UnitTests\PInvoke\KtmW32\KtmW32.csproj", "{8BC51B6B-77FA-4571-8E1C-EA75ED4DCD56}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KtmW32", "UnitTests\PInvoke\KtmW32\KtmW32.csproj", "{8BC51B6B-77FA-4571-8E1C-EA75ED4DCD56}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.Pdh", "PInvoke\Pdh\Vanara.PInvoke.Pdh.csproj", "{C1D9429F-A8BD-4094-ABE3-32581FC4614F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pdh", "UnitTests\PInvoke\Pdh\Pdh.csproj", "{15189584-3BD8-47DB-8B65-F58482063585}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pdh", "UnitTests\PInvoke\Pdh\Pdh.csproj", "{15189584-3BD8-47DB-8B65-F58482063585}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.BITS", "BITS\Vanara.BITS.csproj", "{C7ACE187-CB36-4CEA-AE0C-651669237427}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.VirtualDisk", "VirtualDisk\Vanara.VirtualDisk.csproj", "{D4E36942-7492-46B9-985B-F99D8F5A35AB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BITS", "UnitTests\BITS\BITS.csproj", "{5558B8E3-FF1C-401F-978E-E91D1E78B898}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BITS", "UnitTests\BITS\BITS.csproj", "{5558B8E3-FF1C-401F-978E-E91D1E78B898}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtualDisk", "UnitTests\VirtualDisk\VirtualDisk.csproj", "{687F9162-8CA0-4277-B868-4E7F2EC614F8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtualDisk", "UnitTests\VirtualDisk\VirtualDisk.csproj", "{687F9162-8CA0-4277-B868-4E7F2EC614F8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExplorerBrowserDemo", "UnitTests\ExplorerBrowser\ExplorerBrowserDemo.csproj", "{2AACFF7E-F4B1-44F6-92C6-20ACBB647A4D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExplorerBrowserDemo", "UnitTests\ExplorerBrowser\ExplorerBrowserDemo.csproj", "{2AACFF7E-F4B1-44F6-92C6-20ACBB647A4D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Windows.Forms.App", "UnitTests\Windows.Forms.App\Windows.Forms.App.csproj", "{9520EC8B-9C63-47E6-A7BD-1CCF9BBB5BFA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Windows.Forms.App", "UnitTests\Windows.Forms.App\Windows.Forms.App.csproj", "{9520EC8B-9C63-47E6-A7BD-1CCF9BBB5BFA}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.Printing", "PInvoke\Printing\Vanara.PInvoke.Printing.csproj", "{D3E1F2B8-D475-4922-B334-919795B858CB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Printing", "UnitTests\PInvoke\Printing\Printing.csproj", "{D2A4FD48-FCED-4E45-BBA0-C2D5CC536428}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Printing", "UnitTests\PInvoke\Printing\Printing.csproj", "{D2A4FD48-FCED-4E45-BBA0-C2D5CC536428}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.UrlMon", "PInvoke\UrlMon\Vanara.PInvoke.UrlMon.csproj", "{1A232558-F25A-4D9B-99DE-76F1B4E41F22}" EndProject @@ -183,7 +183,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.Opc", "PInvo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.UserEnv", "PInvoke\UserEnv\Vanara.PInvoke.UserEnv.csproj", "{2F4AF0C8-483B-4F0E-89F7-EB9AC32385B3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserEnv", "UnitTests\PInvoke\UserEnv\UserEnv.csproj", "{FFF69906-9EEC-4D01-879F-CE96DE2FFC6A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UserEnv", "UnitTests\PInvoke\UserEnv\UserEnv.csproj", "{FFF69906-9EEC-4D01-879F-CE96DE2FFC6A}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{067384DF-120D-485D-B2BF-D6D6089937B8}" ProjectSection(SolutionItems) = preProject @@ -195,45 +195,45 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Vanara.Library.nuspec = Vanara.Library.nuspec EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Opc", "UnitTests\PInvoke\Opc\Opc.csproj", "{9783BAFF-8388-44FA-882B-A92142CC20F5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Opc", "UnitTests\PInvoke\Opc\Opc.csproj", "{9783BAFF-8388-44FA-882B-A92142CC20F5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UrlMon", "UnitTests\PInvoke\UrlMon\UrlMon.csproj", "{2D9E5288-94AA-486A-B89D-0569AE2284F1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UrlMon", "UnitTests\PInvoke\UrlMon\UrlMon.csproj", "{2D9E5288-94AA-486A-B89D-0569AE2284F1}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.WcmApi", "PInvoke\WcmApi\Vanara.PInvoke.WcmApi.csproj", "{7508C4E0-D14B-45DF-B644-9236B0B83607}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.WlanApi", "PInvoke\WlanApi\Vanara.PInvoke.WlanApi.csproj", "{141B6B19-6F07-4644-B72D-B189E49030BF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WlanApi", "UnitTests\PInvoke\WlanApi\WlanApi.csproj", "{F8E02C7E-99E9-4C99-B63D-E678BC43C734}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WlanApi", "UnitTests\PInvoke\WlanApi\WlanApi.csproj", "{F8E02C7E-99E9-4C99-B63D-E678BC43C734}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WcmApi", "UnitTests\PInvoke\WcmApi\WcmApi.csproj", "{35B95D64-CC7E-48B4-B104-4886411531AC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WcmApi", "UnitTests\PInvoke\WcmApi\WcmApi.csproj", "{35B95D64-CC7E-48B4-B104-4886411531AC}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.DnsApi", "PInvoke\DnsApi\Vanara.PInvoke.DnsApi.csproj", "{15023E19-86A7-40C7-838E-21EEB15A63AF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DnsApi", "UnitTests\PInvoke\DnsApi\DnsApi.csproj", "{5B4ADAFE-DCCC-40BC-9A9E-8086E57E8B49}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DnsApi", "UnitTests\PInvoke\DnsApi\DnsApi.csproj", "{5B4ADAFE-DCCC-40BC-9A9E-8086E57E8B49}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.CldApi", "PInvoke\CldApi\Vanara.PInvoke.CldApi.csproj", "{DDFCBC19-B6CE-4DD4-A1BB-96EE86C54D93}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CldApi", "UnitTests\PInvoke\CldApi\CldApi.csproj", "{CCEE0CAA-27BF-43B3-8609-2279BEDA3F61}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CldApi", "UnitTests\PInvoke\CldApi\CldApi.csproj", "{CCEE0CAA-27BF-43B3-8609-2279BEDA3F61}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.ProjectedFSLib", "PInvoke\ProjectedFSLib\Vanara.PInvoke.ProjectedFSLib.csproj", "{30F2727D-0B8E-4364-8F0E-9EEB4CD9CB0E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.Graphics", "PInvoke\Graphics\Vanara.PInvoke.Graphics.csproj", "{FAF09C42-66CA-4765-910A-2A9A2EF399D0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Graphics", "UnitTests\PInvoke\Graphics\Graphics.csproj", "{AD003766-998F-4969-8632-A9CD0E3A21F8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Graphics", "UnitTests\PInvoke\Graphics\Graphics.csproj", "{AD003766-998F-4969-8632-A9CD0E3A21F8}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoreConsoleApp", "UnitTests\CoreConsoleApp\CoreConsoleApp.csproj", "{3E14800D-4E2D-43A0-8C15-B64C6F4469CA}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.Magnification", "PInvoke\Magnification\Vanara.PInvoke.Magnification.csproj", "{93EFCE73-4A4D-40A3-882E-6A4A20C40816}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Magnification", "UnitTests\PInvoke\Magnification\Magnification.csproj", "{E753F3A4-2A0B-49E2-9611-4F35534B5F72}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Magnification", "UnitTests\PInvoke\Magnification\Magnification.csproj", "{E753F3A4-2A0B-49E2-9611-4F35534B5F72}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.DbgHelp", "PInvoke\DbgHelp\Vanara.PInvoke.DbgHelp.csproj", "{69604ECE-B123-4328-BEC3-996CCF22DB90}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DbgHelp", "UnitTests\PInvoke\DbgHelp\DbgHelp.csproj", "{F2C94926-224F-43AB-B351-C20C9B2D8656}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DbgHelp", "UnitTests\PInvoke\DbgHelp\DbgHelp.csproj", "{F2C94926-224F-43AB-B351-C20C9B2D8656}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.P2P", "PInvoke\P2P\Vanara.PInvoke.P2P.csproj", "{200D7E57-452A-4A43-A96D-386F7C49E7BA}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "P2P", "UnitTests\PInvoke\P2P\P2P.csproj", "{BBA10B94-658F-4BD7-A3DD-AA39CDF9A68D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "P2P", "UnitTests\PInvoke\P2P\P2P.csproj", "{BBA10B94-658F-4BD7-A3DD-AA39CDF9A68D}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.PeerDist", "PInvoke\PeerDist\Vanara.PInvoke.PeerDist.csproj", "{3108565B-2F79-447B-9386-42203CD949A5}" EndProject @@ -241,13 +241,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.Drt", "PInvo EndProject Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "Vanara.PInvoke.FirewallApi", "PInvoke\FirewallApi\Vanara.PInvoke.FirewallApi.vbproj", "{E74C1A09-1051-4616-8693-B69A6A95AD03}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FirewallApi", "UnitTests\PInvoke\FirewallApi\FirewallApi.csproj", "{6A9599A6-89D5-4072-8DA1-A13E37023613}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FirewallApi", "UnitTests\PInvoke\FirewallApi\FirewallApi.csproj", "{6A9599A6-89D5-4072-8DA1-A13E37023613}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BITS", "UnitTests\PInvoke\BITS\BITS.csproj", "{95E98514-A4D0-4ACD-8BE0-35D7BD185C71}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BITS", "UnitTests\PInvoke\BITS\BITS.csproj", "{95E98514-A4D0-4ACD-8BE0-35D7BD185C71}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cabinet", "UnitTests\PInvoke\Cabinet\Cabinet.csproj", "{CD8A5176-6EEC-4739-9748-A45D3FDECFA0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cabinet", "UnitTests\PInvoke\Cabinet\Cabinet.csproj", "{CD8A5176-6EEC-4739-9748-A45D3FDECFA0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShlwApi", "UnitTests\PInvoke\ShlwApi\ShlwApi.csproj", "{80E10D65-5B7C-4BC8-8000-2B5BC9A21874}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShlwApi", "UnitTests\PInvoke\ShlwApi\ShlwApi.csproj", "{80E10D65-5B7C-4BC8-8000-2B5BC9A21874}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build Files", "Build Files", "{27FA62A4-C1EE-461D-9F5B-287C0A848B88}" ProjectSection(SolutionItems) = preProject @@ -255,23 +255,23 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build Files", "Build Files" UnitTests\Directory.Build.targets = UnitTests\Directory.Build.targets EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.Dhcp", "PInvoke\Dhcp\Vanara.PInvoke.Dhcp.csproj", "{CB2EAE48-7503-459F-BD63-69FAE9740A20}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.Dhcp", "PInvoke\Dhcp\Vanara.PInvoke.Dhcp.csproj", "{CB2EAE48-7503-459F-BD63-69FAE9740A20}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dhcp", "UnitTests\PInvoke\Dhcp\Dhcp.csproj", "{94D2C3ED-2101-439C-AAAA-452883A493B4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dhcp", "UnitTests\PInvoke\Dhcp\Dhcp.csproj", "{94D2C3ED-2101-439C-AAAA-452883A493B4}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.Rpc", "PInvoke\Rpc\Vanara.PInvoke.Rpc.csproj", "{4108A2DD-AD00-44D0-B926-405D65E630A3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.WTSApi32", "PInvoke\WTSApi32\Vanara.PInvoke.WTSApi32.csproj", "{CEBC8DBE-0A4F-4A71-BEB5-8A5B28F89352}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.WTSApi32", "PInvoke\WTSApi32\Vanara.PInvoke.WTSApi32.csproj", "{CEBC8DBE-0A4F-4A71-BEB5-8A5B28F89352}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WTSApi32", "UnitTests\PInvoke\WTSApi32\WTSApi32.csproj", "{A231F6BB-C9C0-4CB2-A9CB-892AD4F9D836}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WTSApi32", "UnitTests\PInvoke\WTSApi32\WTSApi32.csproj", "{A231F6BB-C9C0-4CB2-A9CB-892AD4F9D836}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.OleDlg", "PInvoke\OleDlg\Vanara.PInvoke.OleDlg.csproj", "{52DB113A-CE55-437C-B6DF-6A4CA1B3F965}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.OleDlg", "PInvoke\OleDlg\Vanara.PInvoke.OleDlg.csproj", "{52DB113A-CE55-437C-B6DF-6A4CA1B3F965}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.ComDlg32", "PInvoke\ComDlg32\Vanara.PInvoke.ComDlg32.csproj", "{8452C9E4-39CB-431F-BBD6-EF3E64675BB1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OleDlg", "UnitTests\PInvoke\OleDlg\OleDlg.csproj", "{76740A8B-28F1-41C8-A724-F2E3F56AA75A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OleDlg", "UnitTests\PInvoke\OleDlg\OleDlg.csproj", "{76740A8B-28F1-41C8-A724-F2E3F56AA75A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComDlg32", "UnitTests\PInvoke\ComDlg32\ComDlg32.csproj", "{1E29742F-1DAB-4186-B058-262BD7BC7FEC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComDlg32", "UnitTests\PInvoke\ComDlg32\ComDlg32.csproj", "{1E29742F-1DAB-4186-B058-262BD7BC7FEC}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.NewDev", "PInvoke\NewDev\Vanara.PInvoke.NewDev.csproj", "{1D581A26-F2BF-4E12-8C32-C1C838044ECE}" EndProject @@ -279,41 +279,41 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.SetupAPI", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetupAPI", "UnitTests\PInvoke\SetupAPI\SetupAPI.csproj", "{B1F98DFA-7FC7-4728-B4C2-A2B3E163EF79}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.Msi", "PInvoke\Msi\Vanara.PInvoke.Msi.csproj", "{CC8EB859-0940-4D91-B165-3B028A1B7B5D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.Msi", "PInvoke\Msi\Vanara.PInvoke.Msi.csproj", "{CC8EB859-0940-4D91-B165-3B028A1B7B5D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Msi", "UnitTests\PInvoke\Msi\Msi.csproj", "{E7242839-78DE-4AFE-8AF7-E9DDCE06E18C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Msi", "UnitTests\PInvoke\Msi\Msi.csproj", "{E7242839-78DE-4AFE-8AF7-E9DDCE06E18C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.SHCore", "PInvoke\SHCore\Vanara.PInvoke.SHCore.csproj", "{F1417ADE-A8D3-432F-8F43-EF626DF4A3C9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.SHCore", "PInvoke\SHCore\Vanara.PInvoke.SHCore.csproj", "{F1417ADE-A8D3-432F-8F43-EF626DF4A3C9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.WsmSvc", "PInvoke\WsmSvc\Vanara.PInvoke.WsmSvc.csproj", "{1D1A06C8-57E8-4754-8383-BBFB3C98F49F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.WsmSvc", "PInvoke\WsmSvc\Vanara.PInvoke.WsmSvc.csproj", "{1D1A06C8-57E8-4754-8383-BBFB3C98F49F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WsmSvc", "UnitTests\PInvoke\WsmSvc\WsmSvc.csproj", "{28175EF4-C5CA-48EB-AD8D-1B0608AD4389}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WsmSvc", "UnitTests\PInvoke\WsmSvc\WsmSvc.csproj", "{28175EF4-C5CA-48EB-AD8D-1B0608AD4389}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.IScsiDsc", "PInvoke\IScsiDsc\Vanara.PInvoke.IScsiDsc.csproj", "{C407D019-7D53-4C6A-B27A-5468F2430F10}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.IScsiDsc", "PInvoke\IScsiDsc\Vanara.PInvoke.IScsiDsc.csproj", "{C407D019-7D53-4C6A-B27A-5468F2430F10}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.Version", "PInvoke\Version\Vanara.PInvoke.Version.csproj", "{460964A8-894C-45A1-AFA5-EF2DA3FC436D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.Version", "PInvoke\Version\Vanara.PInvoke.Version.csproj", "{460964A8-894C-45A1-AFA5-EF2DA3FC436D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Version", "UnitTests\PInvoke\Version\Version.csproj", "{6C2D8577-ECEF-4E07-B4D7-CBFFD7BB6F53}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Version", "UnitTests\PInvoke\Version\Version.csproj", "{6C2D8577-ECEF-4E07-B4D7-CBFFD7BB6F53}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.RstrtMgr", "PInvoke\RstrtMgr\Vanara.PInvoke.RstrtMgr.csproj", "{6FFDB484-24E0-4338-B816-D9975AF35853}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.RstrtMgr", "PInvoke\RstrtMgr\Vanara.PInvoke.RstrtMgr.csproj", "{6FFDB484-24E0-4338-B816-D9975AF35853}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.FunDisc", "PInvoke\FunDisc\Vanara.PInvoke.FunDisc.csproj", "{D0CD8393-BE38-4B9D-911F-C372293EF62D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.FunDisc", "PInvoke\FunDisc\Vanara.PInvoke.FunDisc.csproj", "{D0CD8393-BE38-4B9D-911F-C372293EF62D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.WcnApi", "PInvoke\WcnApi\Vanara.PInvoke.WcnApi.csproj", "{55952C51-B68B-432E-A168-4ADD569B9274}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.WcnApi", "PInvoke\WcnApi\Vanara.PInvoke.WcnApi.csproj", "{55952C51-B68B-432E-A168-4ADD569B9274}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.IMAPI", "PInvoke\IMAPI\Vanara.PInvoke.IMAPI.csproj", "{17EFDD95-3E52-44C1-80D9-48031E3F6B3F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.IMAPI", "PInvoke\IMAPI\Vanara.PInvoke.IMAPI.csproj", "{17EFDD95-3E52-44C1-80D9-48031E3F6B3F}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.CfgMgr32", "PInvoke\CfgMgr32\Vanara.PInvoke.CfgMgr32.csproj", "{2ECB955C-F05D-4FD7-BCC7-449A494CA66B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.TextServicesFramework", "PInvoke\TextServicesFramework\Vanara.PInvoke.TextServicesFramework.csproj", "{17DE6265-EE0F-42E5-AE1A-7ACCDD8A45E8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.TextServicesFramework", "PInvoke\TextServicesFramework\Vanara.PInvoke.TextServicesFramework.csproj", "{17DE6265-EE0F-42E5-AE1A-7ACCDD8A45E8}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CfgMgr32", "UnitTests\PInvoke\CfgMgr32\CfgMgr32.csproj", "{6F4649D2-CB4E-463A-A5DE-CCC3B0DBD07A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.Lz32", "PInvoke\Lz32\Vanara.PInvoke.Lz32.csproj", "{553081F3-A380-44B4-94ED-E8CE510F3E96}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.Lz32", "PInvoke\Lz32\Vanara.PInvoke.Lz32.csproj", "{553081F3-A380-44B4-94ED-E8CE510F3E96}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.Multimedia", "PInvoke\Multimedia\Vanara.PInvoke.Multimedia.csproj", "{A7936B0B-A16B-42A5-A6DA-5D00FA98EEDD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Multimedia", "UnitTests\PInvoke\Multimedia\Multimedia.csproj", "{A9F11EBE-C1CE-40C3-A611-B444652215A0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Multimedia", "UnitTests\PInvoke\Multimedia\Multimedia.csproj", "{A9F11EBE-C1CE-40C3-A611-B444652215A0}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.WinBio", "PInvoke\WinBio\Vanara.PInvoke.WinBio.csproj", "{C786E4D5-B2DD-453A-82E7-5DD8374A0A2A}" EndProject @@ -323,19 +323,21 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.CimFs", "PIn EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CimFs", "UnitTests\PInvoke\CimFs\CimFs.csproj", "{5DBC32A2-1FF0-41F6-9D6B-CE701F599BE0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.FhSvcCtl", "PInvoke\FhSvcCtl\Vanara.PInvoke.FhSvcCtl.csproj", "{B419C1F3-AB66-40B9-9693-817CD061F7EF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.FhSvcCtl", "PInvoke\FhSvcCtl\Vanara.PInvoke.FhSvcCtl.csproj", "{B419C1F3-AB66-40B9-9693-817CD061F7EF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FhSvcCtl", "UnitTests\PInvoke\FhSvcCtl\FhSvcCtl.csproj", "{089EA815-567E-4430-BEB4-4E18FD0B1473}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FhSvcCtl", "UnitTests\PInvoke\FhSvcCtl\FhSvcCtl.csproj", "{089EA815-567E-4430-BEB4-4E18FD0B1473}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.EnhancedStorage", "PInvoke\EnhancedStorage\Vanara.PInvoke.EnhancedStorage.csproj", "{1D842CC7-BECA-4011-A7FB-98773CFF8CD0}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.PortableDeviceApi", "PInvoke\PortableDeviceApi\Vanara.PInvoke.PortableDeviceApi.csproj", "{7DA64CE7-F149-46CD-AC2A-AA8DBA1CDB39}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PortableDeviceApi", "UnitTests\PInvoke\PortableDeviceApi\PortableDeviceApi.csproj", "{0E4D9AB7-1881-49F6-B307-D1681A0703FD}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PortableDeviceApi", "UnitTests\PInvoke\PortableDeviceApi\PortableDeviceApi.csproj", "{0E4D9AB7-1881-49F6-B307-D1681A0703FD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnhancedStorage", "UnitTests\PInvoke\EnhancedStorage\EnhancedStorage.csproj", "{A205BA61-E2C4-41C5-B7CE-9EB5940C7076}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EnhancedStorage", "UnitTests\PInvoke\EnhancedStorage\EnhancedStorage.csproj", "{A205BA61-E2C4-41C5-B7CE-9EB5940C7076}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.VssApi", "PInvoke\VssApi\Vanara.PInvoke.VssApi.csproj", "{A29388B1-0F2F-4551-BDB8-272E0865D96C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.VssApiMgd", "PInvoke\VssApiMgd\Vanara.PInvoke.VssApiMgd.csproj", "{39AEDD51-C627-41B9-96D3-44F481ED4E7C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Vanara.PInvoke.VssApi", "PInvoke\VssApi\VssApi.vcxproj", "{11EF8FFF-25DE-4ADB-A951-FA10A421FFE4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -2038,24 +2040,40 @@ Global {A205BA61-E2C4-41C5-B7CE-9EB5940C7076}.Release|Any CPU.ActiveCfg = Release|Any CPU {A205BA61-E2C4-41C5-B7CE-9EB5940C7076}.Release|x64.ActiveCfg = Release|Any CPU {A205BA61-E2C4-41C5-B7CE-9EB5940C7076}.Release|x86.ActiveCfg = Release|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.Debug|x64.ActiveCfg = Debug|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.Debug|x64.Build.0 = Debug|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.Debug|x86.ActiveCfg = Debug|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.Debug|x86.Build.0 = Debug|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.DebugNoTests|Any CPU.ActiveCfg = Debug|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.DebugNoTests|Any CPU.Build.0 = Debug|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.DebugNoTests|x64.ActiveCfg = Debug|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.DebugNoTests|x64.Build.0 = Debug|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.DebugNoTests|x86.ActiveCfg = Debug|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.DebugNoTests|x86.Build.0 = Debug|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.Release|Any CPU.Build.0 = Release|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.Release|x64.ActiveCfg = Release|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.Release|x64.Build.0 = Release|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.Release|x86.ActiveCfg = Release|Any CPU - {A29388B1-0F2F-4551-BDB8-272E0865D96C}.Release|x86.Build.0 = Release|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.Debug|x64.ActiveCfg = Debug|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.Debug|x64.Build.0 = Debug|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.Debug|x86.ActiveCfg = Debug|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.Debug|x86.Build.0 = Debug|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.DebugNoTests|Any CPU.ActiveCfg = Debug|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.DebugNoTests|Any CPU.Build.0 = Debug|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.DebugNoTests|x64.ActiveCfg = Debug|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.DebugNoTests|x64.Build.0 = Debug|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.DebugNoTests|x86.ActiveCfg = Debug|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.DebugNoTests|x86.Build.0 = Debug|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.Release|Any CPU.Build.0 = Release|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.Release|x64.ActiveCfg = Release|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.Release|x64.Build.0 = Release|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.Release|x86.ActiveCfg = Release|Any CPU + {39AEDD51-C627-41B9-96D3-44F481ED4E7C}.Release|x86.Build.0 = Release|Any CPU + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4}.Debug|x64.ActiveCfg = Debug|x64 + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4}.Debug|x64.Build.0 = Debug|x64 + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4}.Debug|x86.ActiveCfg = Debug|Win32 + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4}.Debug|x86.Build.0 = Debug|Win32 + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4}.DebugNoTests|Any CPU.ActiveCfg = Debug|Win32 + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4}.DebugNoTests|Any CPU.Build.0 = Debug|Win32 + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4}.DebugNoTests|x64.ActiveCfg = Debug|x64 + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4}.DebugNoTests|x64.Build.0 = Debug|x64 + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4}.DebugNoTests|x86.ActiveCfg = Debug|Win32 + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4}.DebugNoTests|x86.Build.0 = Debug|Win32 + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4}.Release|Any CPU.ActiveCfg = Release|Win32 + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4}.Release|x64.ActiveCfg = Release|x64 + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4}.Release|x64.Build.0 = Release|x64 + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4}.Release|x86.ActiveCfg = Release|Win32 + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2205,7 +2223,8 @@ Global {7DA64CE7-F149-46CD-AC2A-AA8DBA1CDB39} = {212ABBD0-B724-4CFA-9D6D-E3891547FA90} {0E4D9AB7-1881-49F6-B307-D1681A0703FD} = {385CAD2D-0A5E-4F80-927B-D5499D126B90} {A205BA61-E2C4-41C5-B7CE-9EB5940C7076} = {385CAD2D-0A5E-4F80-927B-D5499D126B90} - {A29388B1-0F2F-4551-BDB8-272E0865D96C} = {212ABBD0-B724-4CFA-9D6D-E3891547FA90} + {39AEDD51-C627-41B9-96D3-44F481ED4E7C} = {212ABBD0-B724-4CFA-9D6D-E3891547FA90} + {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4} = {212ABBD0-B724-4CFA-9D6D-E3891547FA90} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {543FAC75-2AF1-4EF1-9609-B242B63FEED4}