Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Volume Shadow Copy Service (VSS) sample in C?

Tags:

c

windows-xp

I been trying to read the documentation for the API functions of Volume Shadow Copy Service, for the purpose of copying files that are currently locked (being used) under Windows XP.

Unfortunately I don't seem to get nowhere. Anybody happen to have a code sample of how to interact with the API, for copying such files?

Thanks, Doori Bar

like image 686
Doori Bar Avatar asked May 26 '10 09:05

Doori Bar


1 Answers

I've had similar troubles, after a lot of hit-and-trials I've managed to get somewhere... here's a code snippet which may help:

#include <stdio.h>

#include <windows.h>
#include <winbase.h>

#include <Vss.h>
#include <VsWriter.h>
#include <VsBackup.h>


int main()
{
    int retCode = 0;
    int i=0;
    HRESULT hr;
    IVssEnumObject *pIEnumSnapshots;
    IVssBackupComponents *ab;
    VSS_OBJECT_PROP Prop;
    VSS_SNAPSHOT_PROP& Snap = Prop.Obj.Snap;
    WCHAR existingFilePath[MAX_PATH] = TEXT("\\temp\\PrinterList.txt");
    WCHAR newFileLocation[MAX_PATH] = TEXT("c:\\Users\\PrinterList.txt");
    TCHAR existingFileLocation[MAX_PATH];

    if (CoInitialize(NULL) != S_OK)
    {
        printf("CoInitialize failed!\n");
        return 1;
    }

    hr = CreateVssBackupComponents(&ab);
    if(hr != S_OK)
    {
        printf("Failed at CreateVssBackupComponents Stage");
        return 1;
    }

    hr = ab->InitializeForBackup();
    if(hr != S_OK)
    {
        printf("Failed at InitializeForBackup Stage");
        return 1;
    }

    hr = ab->SetContext(VSS_CTX_ALL);
    if(hr != S_OK)
    {
        printf("Failed at SetContext Stage");
        return 1;
    }

    hr = ab->Query(GUID_NULL,VSS_OBJECT_NONE, VSS_OBJECT_SNAPSHOT, &pIEnumSnapshots);
    if(hr != S_OK){
        printf("Failed at Query Stage");
        return 1;
    }

    // Enumerate all shadow copies. 
    printf("Recursing through snapshots...\n");
    while(true)
    {
        // Get the next element
        ULONG ulFetched;
        hr = pIEnumSnapshots->Next( 1, &Prop, &ulFetched );

        // We reached the end of list
        if (ulFetched == 0)
            break;

        wprintf(L"Snapshot:%s\n", Snap.m_pwszSnapshotDeviceObject);
        /*
        At this point you have the Snap object with all the information required for copying the file.
        example:
        Snap.m_pwszSnapshotDeviceObject is the root for snapshot object
        (like \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1)
        Snap.m_pwszOriginalVolumeName is the full unicode name
        (like \\?\Volume{1240872a-88de-11df-a94d-806e6f6e6963}\)
        for the original root(c: mostly)

        So, you can use CopyFile() to do what you want
        */


        wcscpy(existingFileLocation, Snap.m_pwszSnapshotDeviceObject);
        wcscat(existingFileLocation, existingFilePath);
        CopyFile(existingFileLocation, newFileLocation, false);
        //false here will enable over-write
    }
    return retCode;
}

Note: If your target machine is not the same as build machine, you'll need to include proper definitions and build configurations.

Note: You will have to use the annoying wchars everywhere, because these functions use them.

like image 110
lalli Avatar answered Oct 20 '22 06:10

lalli