From 2eddeabf2cffe89b41cb28cd4ed4c0df559c8323 Mon Sep 17 00:00:00 2001 From: dahall Date: Mon, 27 Dec 2021 09:20:57 -0700 Subject: [PATCH] More updates and unit tests for VSS (still not ready) --- PInvoke/VssApi/VsWriter.h | 6 +-- PInvoke/VssApiMgd/Vanara.PInvoke.VssApiMgd.csproj | 1 + PInvoke/VssApiMgd/vsmgmt.cs | 37 +++++++++---- UnitTests/PInvoke/VssApi/VssApi.csproj | 9 ++++ UnitTests/PInvoke/VssApi/VssApiTests.cs | 63 +++++++++++++++++++++++ Vanara.sln | 19 +++++++ 6 files changed, 122 insertions(+), 13 deletions(-) create mode 100644 UnitTests/PInvoke/VssApi/VssApi.csproj create mode 100644 UnitTests/PInvoke/VssApi/VssApiTests.cs diff --git a/PInvoke/VssApi/VsWriter.h b/PInvoke/VssApi/VsWriter.h index 09421bd3..bc8d2926 100644 --- a/PInvoke/VssApi/VsWriter.h +++ b/PInvoke/VssApi/VsWriter.h @@ -376,7 +376,7 @@ namespace Vanara { namespace PInvoke { namespace VssApi { /// // https://docs.microsoft.com/en-us/windows/win32/api/vswriter/nl-vswriter-cvsswriter [PInvokeData("vswriter.h", MSDNShortId = "NL:vswriter.CVssWriter")] - public ref class CVssWriter : public IVssWriter + public ref class CVssWriter abstract : public IVssWriter { private: CVssWriterImpl* pNative; @@ -385,7 +385,7 @@ namespace Vanara { namespace PInvoke { namespace VssApi { /// CVssWriter is the constructor of the CVssWriter class object. /// None // https://docs.microsoft.com/en-us/windows/win32/api/vswriter/nf-vswriter-cvsswriter-cvsswriter - STDMETHODCALLTYPE CVssWriter() : pNative(new CVssWriterImpl(this)) {} + CVssWriter() : pNative(new CVssWriterImpl(this)) {} /// /// ~CVssWriter is the destructor of the CVssWriter class object. @@ -394,7 +394,7 @@ namespace Vanara { namespace PInvoke { namespace VssApi { /// None // https://docs.microsoft.com/en-us/windows/win32/api/vswriter/nf-vswriter-cvsswriter--cvsswriter // void ~CVssWriter(); - virtual STDMETHODCALLTYPE ~CVssWriter() + virtual ~CVssWriter() { if (pNative != NULL) { diff --git a/PInvoke/VssApiMgd/Vanara.PInvoke.VssApiMgd.csproj b/PInvoke/VssApiMgd/Vanara.PInvoke.VssApiMgd.csproj index 1dcd79f9..07180add 100644 --- a/PInvoke/VssApiMgd/Vanara.PInvoke.VssApiMgd.csproj +++ b/PInvoke/VssApiMgd/Vanara.PInvoke.VssApiMgd.csproj @@ -12,6 +12,7 @@ pinvoke;vanara;net-extensions;interop;VSS;VssApi;volume shadow copy service True false + Currently implements: Functions diff --git a/PInvoke/VssApiMgd/vsmgmt.cs b/PInvoke/VssApiMgd/vsmgmt.cs index e6853f98..e743803b 100644 --- a/PInvoke/VssApiMgd/vsmgmt.cs +++ b/PInvoke/VssApiMgd/vsmgmt.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Runtime.InteropServices; using Vanara.Collections; @@ -726,7 +727,7 @@ namespace Vanara.PInvoke.VssApi /// The Next method returns the specified number of objects from the specified list of enumerated objects. /// The number of elements to be read from the list of enumerated objects into the rgelt buffer. /// - /// The address of a caller-allocated buffer that receives celtVSS_MGMT_OBJECT_PROP structures that contain the returned objects. + /// The address of a caller-allocated buffer that receives celt VSS_MGMT_OBJECT_PROP structures that contain the returned objects. /// This parameter is required and cannot be NULL. /// /// The number of elements that were returned in the rgelt buffer. @@ -929,7 +930,7 @@ namespace Vanara.PInvoke.VssApi // VSS_MGMT_OBJECT_TYPE Type; VSS_MGMT_OBJECT_UNION Obj; } VSS_MGMT_OBJECT_PROP, *PVSS_MGMT_OBJECT_PROP; [PInvokeData("vsmgmt.h", MSDNShortId = "NS:vsmgmt._VSS_MGMT_OBJECT_PROP")] [StructLayout(LayoutKind.Sequential)] - public struct VSS_MGMT_OBJECT_PROP + public class VSS_MGMT_OBJECT_PROP : IDisposable { /// Object type. For more information, see VSS_MGMT_OBJECT_TYPE. public VSS_MGMT_OBJECT_TYPE Type; @@ -945,26 +946,41 @@ namespace Vanara.PInvoke.VssApi /// /// public VSS_MGMT_OBJECT_UNION Obj; + + /// Frees the allocated memory for the strings in this structure. + public void Dispose() + { + Marshal.FreeCoTaskMem((IntPtr)Obj.szOne); + Marshal.FreeCoTaskMem((IntPtr)Obj.szTwo); + Obj.szOne = Obj.szTwo = IntPtr.Zero; + } } /// /// The VSS_MGMT_OBJECT_UNION specifies the union of object types that can be defined by the VSS_MGMT_OBJECT_PROP structure (section 2.2.3.6). /// [PInvokeData("vsmgmt.h", MSDNShortId = "NS:vsmgmt._VSS_MGMT_OBJECT_PROP")] - [StructLayout(LayoutKind.Explicit)] + [StructLayout(LayoutKind.Sequential)] public struct VSS_MGMT_OBJECT_UNION { + internal InteropServices.StrPtrUni szOne; + + internal InteropServices.StrPtrUni szTwo; + + internal long lOne; + + internal long lTwo; + + internal long lThree; + /// The structure specifies an original volume object as a VSS_VOLUME_PROP structure (section 2.2.3.7). - [FieldOffset(0)] - public VSS_VOLUME_PROP Vol; + public VSS_VOLUME_PROP Vol => new() { m_pwszVolumeName = szOne, m_pwszVolumeDisplayName = szTwo }; /// The structure specifies a shadow copy storage volume as a VSS_DIFF_VOLUME_PROP structure. - [FieldOffset(0)] - public VSS_DIFF_VOLUME_PROP DiffVol; + public VSS_DIFF_VOLUME_PROP DiffVol => new() { m_pwszVolumeName = szOne, m_pwszVolumeDisplayName = szTwo, m_llVolumeFreeSpace = lOne, m_llVolumeTotalSpace = lTwo }; /// The structure specifies a shadow copy storage object as a VSS_DIFF_AREA_PROP. - [FieldOffset(0)] - public VSS_DIFF_AREA_PROP DiffArea; + public VSS_DIFF_AREA_PROP DiffArea => new() { m_pwszVolumeName = szOne, m_pwszDiffAreaVolumeName = szTwo, m_llMaximumDiffSpace = lOne, m_llAllocatedDiffSpace = lTwo, m_llUsedDiffSpace = lThree }; } /// The VSS_VOLUME_PROP structure contains the properties of a shadow copy source volume. @@ -1023,7 +1039,8 @@ namespace Vanara.PInvoke.VssApi /// Enumerates the instances provided by an . /// The instance. /// A sequence of structures. - public static IEnumerable Enumerate(this IVssEnumMgmtObject emo) => new IEnumFromCom(emo.Next, emo.Reset); + public static IEnumerable Enumerate(this IVssEnumMgmtObject emo) => + new IEnumFromCom(emo.Next, emo.Reset, () => new VSS_MGMT_OBJECT_PROP()); /// The GetProviderMgmtInterface method returns an interface to further configure the system provider. /// The instance. diff --git a/UnitTests/PInvoke/VssApi/VssApi.csproj b/UnitTests/PInvoke/VssApi/VssApi.csproj new file mode 100644 index 00000000..f7a019cd --- /dev/null +++ b/UnitTests/PInvoke/VssApi/VssApi.csproj @@ -0,0 +1,9 @@ + + + UnitTest.PInvoke.VssApi + + + + + + \ No newline at end of file diff --git a/UnitTests/PInvoke/VssApi/VssApiTests.cs b/UnitTests/PInvoke/VssApi/VssApiTests.cs new file mode 100644 index 00000000..c7a4a533 --- /dev/null +++ b/UnitTests/PInvoke/VssApi/VssApiTests.cs @@ -0,0 +1,63 @@ +using NUnit.Framework; +using NUnit.Framework.Internal; +using System; +using System.Linq; +using System.Runtime.InteropServices; +using Vanara.PInvoke; +using Vanara.PInvoke.VssApi; +using static Vanara.PInvoke.Kernel32; + +namespace Vanara.PInvoke.Tests +{ + [TestFixture] + public class VssApiTests + { + static readonly Guid ProviderId = new("{b5946137-7b9f-4925-af80-51abd60b20d5}"); + string[] vols; + + [OneTimeSetUp] + public void _Setup() + { + vols = EnumVolumes().ToArray(); + } + + [OneTimeTearDown] + public void _TearDown() + { + } + + [Test] + public void QueryDiffAreasForVolumeTest() + { + Assert.That(vols, Has.Length.GreaterThan(0)); + + IVssSnapshotMgmt imgr = new(); + var diffmgr = imgr.GetProviderMgmtInterface(ProviderId); + foreach (var vol in vols) + { + TestContext.WriteLine($"Volume: {vol}"); + var enumMgr = diffmgr.QueryDiffAreasForVolume(vol); + foreach (var prop in enumMgr.Enumerate()) + { + switch (prop.Type) + { + case VSS_MGMT_OBJECT_TYPE.VSS_MGMT_OBJECT_UNKNOWN: + TestContext.WriteLine(" Unknown"); + break; + case VSS_MGMT_OBJECT_TYPE.VSS_MGMT_OBJECT_VOLUME: + TestContext.WriteLine($" Volume: {prop.Obj.Vol.m_pwszVolumeDisplayName} ({prop.Obj.Vol.m_pwszVolumeName})"); + break; + case VSS_MGMT_OBJECT_TYPE.VSS_MGMT_OBJECT_DIFF_VOLUME: + TestContext.WriteLine($" DiffVol: {prop.Obj.DiffVol.m_pwszVolumeDisplayName} ({prop.Obj.DiffVol.m_pwszVolumeName}) {prop.Obj.DiffVol.m_llVolumeTotalSpace}:{prop.Obj.DiffVol.m_llVolumeFreeSpace}"); + break; + case VSS_MGMT_OBJECT_TYPE.VSS_MGMT_OBJECT_DIFF_AREA: + TestContext.WriteLine($" DiffAera: {prop.Obj.DiffArea.m_pwszDiffAreaVolumeName} ({prop.Obj.DiffArea.m_pwszVolumeName}) {prop.Obj.DiffArea.m_llMaximumDiffSpace}:{prop.Obj.DiffArea.m_llAllocatedDiffSpace}:{prop.Obj.DiffArea.m_llUsedDiffSpace}"); + break; + default: + break; + } + } + } + } + } +} \ No newline at end of file diff --git a/Vanara.sln b/Vanara.sln index f3b3f99c..29197df9 100644 --- a/Vanara.sln +++ b/Vanara.sln @@ -342,6 +342,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Vanara.PInvoke.VssApi", "PI {39AEDD51-C627-41B9-96D3-44F481ED4E7C} = {39AEDD51-C627-41B9-96D3-44F481ED4E7C} EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VssApi", "UnitTests\PInvoke\VssApi\VssApi.csproj", "{B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -2077,6 +2079,22 @@ Global {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 + {B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682}.Debug|x64.ActiveCfg = Debug|Any CPU + {B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682}.Debug|x64.Build.0 = Debug|Any CPU + {B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682}.Debug|x86.ActiveCfg = Debug|Any CPU + {B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682}.Debug|x86.Build.0 = Debug|Any CPU + {B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682}.DebugNoTests|Any CPU.ActiveCfg = Debug|Any CPU + {B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682}.DebugNoTests|x64.ActiveCfg = Debug|Any CPU + {B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682}.DebugNoTests|x64.Build.0 = Debug|Any CPU + {B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682}.DebugNoTests|x86.ActiveCfg = Debug|Any CPU + {B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682}.DebugNoTests|x86.Build.0 = Debug|Any CPU + {B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682}.Release|x64.ActiveCfg = Release|Any CPU + {B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682}.Release|x64.Build.0 = Release|Any CPU + {B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682}.Release|x86.ActiveCfg = Release|Any CPU + {B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2228,6 +2246,7 @@ Global {A205BA61-E2C4-41C5-B7CE-9EB5940C7076} = {385CAD2D-0A5E-4F80-927B-D5499D126B90} {39AEDD51-C627-41B9-96D3-44F481ED4E7C} = {212ABBD0-B724-4CFA-9D6D-E3891547FA90} {11EF8FFF-25DE-4ADB-A951-FA10A421FFE4} = {212ABBD0-B724-4CFA-9D6D-E3891547FA90} + {B62EE3FD-4AA8-4A99-AAB3-3A4022AEB682} = {385CAD2D-0A5E-4F80-927B-D5499D126B90} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {543FAC75-2AF1-4EF1-9609-B242B63FEED4}