[OT] Volume Shadow Copy on XP,...

Hi,

sorry for asking this kind of Question, but asking it on other communities like codeproject and similar places did not lead to a solution, not even a single answer that could be of help.

A week ago, i asked a question about RegSaveKeyEx and got very good answers on the issue that lead to a very quick solution. After some coding (at that moment the RegSaveKeyEx problem was already solved) i came to Volume Sahdow Copy Service and experimented a little on it, mostly with its client applications. But the funny thing was that a few days later i had to find a way to copy a locked file that is held by a process (i dont have source access to the process) implementing a proprietary database. I was asked to write some code periodically backing up the file. At first i thought i could open that file for read access and copy its content in a simple and fast way, but the process holds exclusive nonsharing lock on the database file, so i had to find another way to solve this. Then i decided to use Volume Shadow Copy and this worked very well on Vista and Windows 7. One of my colleagues told me that it also runs on Windows 8. Since i am mostly coding in C# and try to avoid C and C++ as often as i can (its really painless to crosscompile for different platforms if you fully stay on .NET classes and/or “well marshalled” pinvokes), i wrote a service application in C#. To access Volume Shadowy Copy i had to port the IVSBackupComponents Interface and all VSS API exports to C# and all the structs. All worked fine and i was able to snapshot the volume holding the file, creating a temporary snapshot, copy, the file and delete the snapshot. I did that all first on my Windows 7 development system and then i moved to Vista and with slight modifications (mainly memory allocation and pointer stuff) it then also worked perfectly on Vista. Now i had to target Windows XP, because we still have lots of XP clients running the process. There it was: The Interface did not work on Windows XP! At first i thought it was some implementation detail and the interface layout had to be changed and i had to use another interface to be able to use the service. After looking at the header files for the VSS SDK it was clear that the layout of the interface was slightly different for xp, so i wrote another Interface implementation for the XP system, but then i faced another problem. The XP class has no GUID for the interface, but i need a valid GUID to access the Interface on the Backup functions from my C# code. Another thing was, that the exports from vssapi.dll differ in some way. Vista,7/8 do have a “CreateVssBackupComponentsInternal” export and XP has a “?CreateVssBackupComponents@@YGJPAPAVIVssBackupComponents@@@Z” which at first should not be a big thing to call. But the problem is, that the XP variant expects a Interface with a unknown guid. The original VSS SDK headers for xp do not have a uuid attribute for the class, but do inherit from IUnknown and calling the XP function with the Vista Interface implementation returns E_NOTIMPLEMENTED and the CLR Runtime tells me that a QueryInterface on the Interface faild and the calllee returned that it does not implement that interface. So i need a valid guid on the interface implementation to be able to pass it to the XP export,…but WHAT is the guid of that IVSSBackupComponents interface for XP???

This is what it is looking for Vista+:
class __declspec(uuid(“665c1d5f-c218-414d-a05d-7fef5f9d5c86”)) IVssBackupComponents : public IUnknown
{
public:

This is what it looks for XP:
class IVssBackupComponents : public IUnknown
{
public:

The XP class looks like a ordinary C++ class to me, deriving from IUnknown. If this is the case, then it would be clear why the call fails, but why does the XP export return me a E_NOINTERFACE and the CLR runtime tells me that i use a wrong interface and that the guid is not valid for some reason. Do i miss something here and how can i solve this? I dont want to write a pinvoke dll exporting the interface from C/C++ in a C# friendly way to my service. It would be best to be able to access all from one service with no external component. Here is the VSS SDK located:

http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=23490

Any help would be great,…

TIA

K.

xxxxx@arcor.de wrote:

…To access Volume Shadowy Copy i had to port the IVSBackupComponents Interface and all VSS API exports to C# and all the structs. … There it was: The Interface did not work on Windows XP! At first i thought it was some implementation detail and the interface layout had to be changed and i had to use another interface to be able to use the service. After looking at the header files for the VSS SDK it was clear that the layout of the interface was slightly different for xp, so i wrote another Interface implementation for the XP system, but then i faced another problem. The XP class has no GUID for the interface, but i need a valid GUID to access the Interface on the Backup functions from my C# code.

The GUID is the same. Microsoft has a cast-in-stone policy that the
GUID for an interface never changes once created.

However, they also have a cast-in-stone policy that an interface’s
layout never changes once released. I’m surprised to hear that you need
a different structure layout for XP. What are the differences?

Another thing was, that the exports from vssapi.dll differ in some way. Vista,7/8 do have a “CreateVssBackupComponentsInternal” export and XP has a “?CreateVssBackupComponents@@YGJPAPAVIVssBackupComponents@@@Z” which at first should not be a big thing to call.

Interesting – that’s a bug. Someone left out an extern “C” declaration
when they created the DLL. Still, that’s easy to work around.

But the problem is, that the XP variant expects a Interface with a unknown guid.

No, it doesn’t. It expects an interface pointer. Once you have the
interface pointer, you don’t need a GUID any more. The only purpose for
an interface GUID is so you can hand it to QueryInterface for some other
object and get an interface pointer back.

The original VSS SDK headers for xp do not have a uuid attribute for the class, but do inherit from IUnknown and calling the XP function with the Vista Interface implementation returns E_NOTIMPLEMENTED and the CLR Runtime tells me that a QueryInterface on the Interface faild and the calllee returned that it does not implement that interface.

What interface were you querying for? And who were you querying?

So i need a valid guid on the interface implementation to be able to pass it to the XP export,…but WHAT is the guid of that IVSSBackupComponents interface for XP???

This is what it is looking for Vista+:
class __declspec(uuid(“665c1d5f-c218-414d-a05d-7fef5f9d5c86”)) IVssBackupComponents : public IUnknown
{
public:

This is what it looks for XP:
class IVssBackupComponents : public IUnknown
{
public:

The XP class looks like a ordinary C++ class to me, deriving from IUnknown.

Right, exactly the same as EVERY COM object. In terms of usage and
implementation, those two class declarations are exactly the same. The
only thing the __declspec does is allow you to use the __uuidof
extension to get the CLSID. All COM objects derive from IUnknown.

If this is the case, then it would be clear why the call fails, but why does the XP export return me a E_NOINTERFACE and the CLR runtime tells me that i use a wrong interface and that the guid is not valid for some reason.

Which call failed? CreateBackupComponents RETURNS an interface pointer
to you. You don’t give it one. You pass it a pointer to a pointer, and
it fills that in with the interface.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Hi Tim,

thanks for your answer.

The GUID is the same. Microsoft has a cast-in-stone policy that the GUID for an interface never
changes once created.

However, they also have a cast-in-stone policy that an interface’s layout never changes once
released. I’m surprised to hear that you need a different structure layout for XP. What are the
differences?

Yes, this is in “general” true, valid for all COM interfaces and related stuff to follow the “contract” between COM clients and servers, but this CANT be in this case, because the Interface differs between the two headers in methods it exposed, the function count it exposed and the vTable order the methods are invoked. You can also read in the SDK somewhere that the VSS implementation in the XP interface is just a subset of the functionality you will have in newer version of the operating systems. If they really use the same GUID (i still dont think so), this would be a big break in their policy! Let me show you that with the C# translation i made from the interfaces. Ill post the links here, so one can download it if he/she needs that and not to bloat that post. Notice that most of the methods from the interface are just stubs and not implemented with their parameters. The lack of the parameters (even using different methio names) is not relevant for the vTable slots as long as the “position” of the called method is correct. I named one XP other Vista, you can name them whatever you want. You can even see that even the IVssAsync-Interface has a different GUID in XP includes (got from header)s:

http://www.zeidler-artroom.de/misc/IVSSBackupComponents.cs

Interesting – that’s a bug. Someone left out an extern “C” declaration when they
created the DLL. Still, that’s easy to work around.

Yes, its no big deal to call that, you simply use the C++ name decoration mangled whatever name you have exported from the library. I am not really sure if this is a bug, because all exports look like C++ or classes of c++. Either they did that on purpose or they really left that out, but thats what all exporst look like:

?xxxxx@CVssWriter@@IBG_NXZ
?CreateVssBackupComponents@@YGJPAPAVIVssBackupComponents@@@Z
?CreateVssExamineWriterMetadata@@YGJPAGPAPAVIVssExamineWriterMetadata@@@Z
?CreateVssSnapshotSetDescription@@YGJU_GUID@@JPAPAVIVssSnapshotSetDescription@@@Z
?xxxxx@CVssWriter@@IBG?AW4_VSS_BACKUP_TYPE@@XZ

No, it doesn’t. It expects an interface pointer. Once you have the interface pointer,
you don’t need a GUID any more. The only purpose for an interface GUID is so you can
hand it to QueryInterface for some other object and get an interface pointer back.

Sorry for mixing up all the terms, happens if you have to think cross platform and language :frowning:

Sure, it needs a pointer to that structure.

What interface were you querying for? And who were you querying?

Not me is it who complains, its is the CreateVssBackupComponents that resturns the HRESULT telling me that a QueryInterface failed with that structure. If i pass the structures pointer to CreateVssBackupComponents on Vista, seven or eight,…everything is fine, works perfect. Doing the same with the modified XP variant (also probe the vista+ interface), it fails with E_NOINTERFACE.

Here are the pinvokes:

[DllImport(“VssApi.dll”,
EntryPoint = “?CreateVssBackupComponents@@YGJPAPAVIVssBackupComponents@@@Z”)]
public static extern HRESULT CreateVssBackupComponentsXP(
[Out] out IVssBackupComponentsXP ppBackup);

[DllImport(“VssApi.dll”,
EntryPoint = “CreateVssBackupComponentsInternal”)]
public static extern HRESULT CreateVssBackupComponentsVista(
[Out] out IVssBackupComponentsVista ppBackup);

Right, exactly the same as EVERY COM object. In terms of usage and implementation,
those two class declarations are exactly the same.

Unfortunately not, have a look at the SDK headers, they differ in method count and position on the vTable. look at the sixth method of IVSSbackupComponets. There starts the difference and some others either are missing or added on next versions.

The only thing the __declspec does is allow you to use the __uuidof extension to get >the CLSID. All COM objects derive from IUnknown.

Which call failed? CreateBackupComponents RETURNS an interface pointer to you. You
don’t give it one. You pass it a pointer to a pointer, and it fills that in with the
interface.

Of course, thats true, sorry for mxing up all that, my fault. At some point you just only want to pass something to the function and want it to work, you dont care anymore whether its in or out parameter :frowning: The function returns a HRESULT (datatype of System.Int32 on .NET) and “outs” a doubly indirect pointer to the horror or IVSSBackupComponents hell of interface.

I am not sure what to think about all that, because it is all suspicious to me: Same Interface name with no uuid, another with, then different methods, different parameters,…again same Interface name. Then you have a method with a default parameter, another interface with same name (different guid) with no default parameter for the same function. I know this sounds strange and unbeleivable, but see for yourself by downloading the SDK. Either this is a big design flaw or i am missing someting fundamental here,…

best

K.

xxxxx@arcor.de wrote:

> What interface were you querying for? And who were you querying?
Not me is it who complains, its is the CreateVssBackupComponents that resturns the HRESULT telling me that a QueryInterface failed with that structure.

It’s hard to understand that. If you disassemble that routine, you’ll
see that it doesn’t do a QueryInterface. It checks for a NULL pointer,
it checks that you have backup operator permissions, then it calls
CreateInstance on its internal CVssBackupComponents class.

The CVssBackupComponents QueryInterface handler seems to implement two
interfaces: {00020400-0000-0000-c000-000000000046}which is IDispatch,
and {ed4a8b9d-3377-4884-a493-74897ca57e68} which seems to be
IVssWriterCallback.

> Right, exactly the same as EVERY COM object. In terms of usage and implementation,
> those two class declarations are exactly the same.
Unfortunately not, have a look at the SDK headers, they differ in method count and position on the vTable. look at the sixth method of IVSSbackupComponets. There starts the difference and some others either are missing or added on next versions.

Yes, what I meant to say here is that the __declspec() does not change
the structure in any way. It is strictly a compile-time thing.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Hi Tim,

thanks for you effort.

It’s hard to understand that. If you disassemble that routine, you’ll see that it doesn’t do a
QueryInterface. It checks for a NULL pointer, it checks that you have backup operator permissions,
then it calls CreateInstance on its internal CVssBackupComponents class.

Yes, looking at vssapi.dll in XP shows a call to __bool __stdcall IsProcessBackupOperator()->HasPrivilege()->IsProcessAdministrator()->ATL::CComObject->CreateInstance() and and and,…but finally i get a E_NOINTERFACE,…

Here is what i get on my original german xp:

Das COM-Objekt des Typs “System.__ComObject” kann nicht in den Schnittstellentyp “IVssBackupComponentsXP” umgewandelt werden. Dieser Vorgang konnte nicht durchgef?hrt werden, da der QueryInterface-Aufruf an die COM-Komponente f?r die Schnittstelle mit der IID “{A4B0621E-CA3F-34A1-AD56-E9C4A2F56E8D}” aufgrund des folgenden Fehlers nicht durchgef?hrt werden konnte: Schnittstelle nicht unterst?tzt (Ausnahme von HRESULT: 0x80004002 (E_NOINTERFACE)).

>Yes, what I meant to say here is that the__declspec() does not change the structure in any way. It
>is strictly a compile-time thing.

Yes a extension attribute for a type or function assigning storage class information in compile time…

I dont know what exactly the A4B0621E-CA3F-34A1-AD56-E9C4A2F56E8D IDD guid stands for. The error tells that it could not finish the task because QueryInterface on the COM Component with the IID A4B0621E-CA3F-34A1-AD56-E9C4A2F56E8D could not be commited due to error : Interface not supported (Exception of type HRESULT: 0x80004002 (E_NOINTERFACE)

The System.__ComObject is a generic object for a com interface that can be marshalled into a interface of a explicit strong type,…

K.

xxxxx@arcor.de wrote:

Here is what i get on my original german xp:

Das COM-Objekt des Typs “System.__ComObject” kann nicht in den Schnittstellentyp “IVssBackupComponentsXP” umgewandelt werden. Dieser Vorgang konnte nicht durchgef?hrt werden, da der QueryInterface-Aufruf an die COM-Komponente f?r die Schnittstelle mit der IID “{A4B0621E-CA3F-34A1-AD56-E9C4A2F56E8D}” aufgrund des folgenden Fehlers nicht durchgef?hrt werden konnte: Schnittstelle nicht unterst?tzt (Ausnahme von HRESULT: 0x80004002 (E_NOINTERFACE)).

Is it possible the E_NOINTERFACE is coming from the marshalling code?
Perhaps the CLR treats everything as an IUnknown and is trying to query
for the IVssBackupComponentsXP IID that it doesn’t understand.

I dont know what exactly the A4B0621E-CA3F-34A1-AD56-E9C4A2F56E8D IDD
guid stands for.

Neither does Google, and that’s unusual. It’s not present anywhere in
the SDK or the WDK.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

> The GUID is the same. Microsoft has a cast-in-stone policy that the

GUID for an interface never changes once created.

IVssBackupComponents interface violated the “interface does not change” policy between XP and 2003.

Don’t remember off-head whether the GUID have changed, though.

However, they also have a cast-in-stone policy that an interface’s
layout never changes once released. I’m surprised to hear that you need
a different structure layout for XP. What are the differences?

Lots of.

Yes, this interface really violated this policy.

CreateVssBackupComponents@@YGJPAPAVIVssBackupComponents@@@Z" which at first
should not be a big thing to call.

when they created the DLL. Still, that’s easy to work around.

Exactly, and yes, this C++ function is the big thing to call.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

>you have a method with a default parameter, another interface with same name (different guid) with

no default parameter for the same function

COM does not know what default parameters are. Only OA knows, and this interface is not OA one.

Also, I would not be surprised if QueryInterface is not implemented on this interface at all.

Just call this C++ function, it will return you the correct interface pointer. Call its methods. Nothing else.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Hi Tim and Maxim,

Is it possible the E_NOINTERFACE is coming from the marshalling code?

Thats possible, i am not exactly aware WHAT in detail the CLR uses to get a pointer to an interface, but i guess this would be the reason here after investiagting a little.

Neither does Google, and that’s unusual. It’s not present anywhere in the SDK or the WDK.

I bet you only found my questions i was asking on some communities,…and got NO answers,…

IVssBackupComponents interface violated the “interface does not change” policy
between XP and 2003.

Yes, it did,… :frowning:

Exactly, and yes, this C++ function is the big thing to call.

Now it is a BIG thing,…

Also, I would not be surprised if QueryInterface is not implemented on this interface at all.

The Interface is derived from IUnknown and hence it should implement that,…but whatever,…

Just call this C++ function, it will return you the correct interface pointer. Call its methods. Nothing
else.

If you can tell me HOW this can be done from C#/CLR without using a wrapper dll, ill be a happy guy! If this is not a extern c, some c style exported or com visible binary, i am out of ideas. AFAIK this cant be done without a wrapper around that interface. If i remember right, the CLR has a atrribute for pinvokes named CallingConvention.ThisCall. Maybe this is an direction i can go,…

If i find a non external library solution solution, ill post it here,…

K.

I managed to get a valid pointer pointer to the data using this:

//must be freed manually later
IntPtr ptrClassBuffer = Marshal.AllocHGlobal(
IntPtr.Size);

HRESULT hr = CreateVssBackupComponentsXP(
ptrClassBuffer); //returns S_OK

[DllImport(“VssApi.dll”,
EntryPoint = “?CreateVssBackupComponents@@YGJPAPAVIVssBackupComponents@@@Z”)]
public static extern HRESULT CreateVssBackupComponentsXP(
[In,Out] IntPtr ppBackup);

I hope i can use Marshal.GetIUnknownForObject() and Marshal.Release() on the data. Now i will try to access the members using Marshal.ReadIntPtr() and trying to callculate the offset to the functions and invoking them by a dynamic delegate and Marshal.GetDelegateForFunctionPointer(). If this works (i am not sure), this would be a great solution and i can write a generic way and class to invoke the functions with their slots/positions in memory if i have the base to the pointer of the class or vTable if its a COM interface,…

Hi,

well, i found a way to make this work. Its a little tricky, but works fine and is .NET only without any external libraries or code. Special thanks go to wj32 from “Process Hacker” for showing me the right direction how this can be made using .NET only and the great “unsafe” context in C#, where you can do almost anything in C# that you can normaly do with C. Important to know is that all functions and classes MUST use the “unsafe” keyword, so that we can use pointer arithmetic. This is not full (and far from perfect, its a first working draft) code, but shows how this can be done in general. Here is a link to code fragments that shows how it has been implemented:

http://www.zeidler-artroom.de/misc/UsingVSSAPIonXPWithPinvoke.cs

best

K.

> If you can tell me HOW this can be done from C#/CLR without using a wrapper dll

Probably no ways.

What is your timeframe to solve this problem set by your management? talk to them and say that VSS is violating the COM basic laws (which it does) and so, without a wrapper DLL, the task is probably unsolvable.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Hi Maxim,

have a look at the code on the link i published. I solved it, even without a wrapper dll! The solution is a little tricky, but works perfect and is C# only and can (though i did it in unsafe context) also be done without unsafe context! Shows a generic way to solve situations like that,…

http://www.zeidler-artroom.de/misc/UsingVSSAPIonXPWithPinvoke.cs

Best

Kerem