Video Screencast Help
Protect Your POS Environment Against Retail Data Breaches. Learn More.

SWV 6.1 SDK Guide Part 2: Patching

Created: 29 Jul 2009 • Updated: 29 Jul 2010 | 1 comment
Language Translations
Jordan's picture
+1 1 Vote
Login to vote

In Part 1 of the SWV 6.1 SDK Guide I covered how to use the same API for SVS and SWV and SVS functions that changed for SWV. Now with Part 2 I'll be talking about the first half of the new Layer Management API in SWV - Layer Patching to be more specific. Note that while I'll be briefly discussing these new features I won't be going into detail on how they can be used, which is better left for a different article. Instead I'll be giving enough info about the new feature so you can understand the API itself.

FunctionNameA vs. FunctionNameW

If you have the SDK help file, which can be installed via the SWV installer (run a repair and add features if you haven't done this), you'll notices that several of the new API are listed twice with either an 'A' or a 'W' after them. This is to designate if the function is in Ansi (A) or Unicode (W) which is something that shouldn't be new to you if you're a C++ developer on Windows. For the FSL2 Class I'll only be using the Ansi version for several reasons: first and foremost all the other API are Ansi only so I don't want to confuse people with what type they're calling. Secondly .Net by default marshals in unmanaged code as Ansi.

It's also worth noting that all the functions that have an 'A' and 'W' version are found in VzLib.dll instead of FSLLib32.dll.

Changes to the FSL2 Class

ManagedSVS.cs has several new methods added.

SVSStruct.cs has a new structure added, VZ_DIFF_PTCH, which is similar to IMP_EXP_V1.

SVSConst has several new items added.

You can download the newest version of the FSL2 Class from the download portal.

Patching

The first new feature is Layer Patching, which allows you to take a special vpa (virtual patch archive) file and apply it to a layer, or create a new layer based off the content, which would in essence "upgrade" the software on the machine to the new version. An example of this would be you've got Firefox 3.01 deployed and you want to upgrade to Firefox 3.02. What you'd do is create a new capture of 3.02 (or just update the layer) and then create a patch archive which is a diff of the 3.01 layer and the 3.02 layer. Then you push down the patch archive file and it converts the 3.01 layer into a 3.02 layer.

VZ_DIFF_PTCH

public class VZ_DIFF_PTCH
 {
  public int currentStage;
  public int currentFunction;
  public int totalStages;
  public bool useUnicode;
  public bool abortOperation;
  public int totalPercent;
  public int stagePercent;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string fileNameA;// FSL2_MAX_PATH
  public int fileSize;
  public UInt32 errorCode;
  public VZ_PTCH_CB_FUNC pCallerCBFunc;
  public IntPtr diffUserData;
 }

VZ_DIFF_PTCH is the new structure that Patch, clone and merge use for reporting the status of the operation. This is very similar IMP_EXP_V1 that Import, Export and ExportEX use. Like IMP_EXP_V1 the delegate and DiffUserData are defined in the FSL2 Class constructor so as long as you create an instance of the FSL2 Class these will all get created for you. See Part 1 and Part 3 of the SVS SDK Documentation for more information on this.

There are several parts of VZ_DIFF_PTCH that you can call to get information out to report to a user and these are:

  1. CurrentStage: what stage, or step, SWV is currently on
  2. TotalStages: how many steps there are
  3. currentFucntion: the name the function that called VZ_DIFF_PTCH
  4. stagePercent: the percent complete of the current stage
  5. totalPercent: the overall percent complete
  6. FileNameA: the name of the file being patched or the layer name that's being clone/merged

There are too many stage names to list in this article but they're all listed in the SDK help file under VZ_DIFF_PTCH Structure or in SVSStruct.cs (they're enumerations).

VzCreatePatchA

public static extern UInt32 createPatch
 (
   string sourceGUID,
   string targetGUID,
   string patchFile,
   bool overWriteVPA,
   VZ_PTCH_CB_FUNC CBInfoFunc,
   ref VZ_DIFF_PTCH diffUserData
 );

Creating a patch file is pretty simple: you need two layer's GUIDS, the source (the new version or Firefox 3.02 in our example) and the Target (original, so Firefox 3.01 in our example). PatchFile is the path to the VPA you want to create (remember to add .vpa at the end) and overWriteVPA is a bool to let the function know to replace any existing VPA with the same name. Lastly we have our structure and the delegate of VZ_DIFF_PTCH that we have to define, more on the delegate function of VZ_DIFF_PTCH will be discussed later in this article.

VzApplyPatchA

public static extern UInt32 applyPatch
 (
   string patchFile,
   bool inNewLayer,
   bool keepRWLayer,
   VZ_PTCH_CB_FUNC CBInfoFunc,
   ref VZ_DIFF_PTCH diffUserData
 );

Once you have a VPA file created you can apply that file to an existing layer by using VzApplyPatchA by passing in the patch files location. There's no need to pass in a GUID of the layer you want to patch because that's stored in the patch file, more on this in a bit, so you need to make sure the GUID of the layer you used as your target layer. Applying a patch changes the target layer into the new layer so the name, GUID, and anything else that's different will get overwritten.

The inNewLayer parameter allows you to instead of patching into an existing layer create a new layer with the updated info. This still requires the target layer to be on the machine but instead of essentially overwriting the target layer it leaves it on the machine and creates a new one so you could have both version of Firefox installed.

KeepRWLayer is used when patching into an existing layer and won't work if inNewLayer is set to true, this option preserves the target layer's Read Write sublayer and the information inside which is usefully if you want your users to keep their settings.

Like Create Patch, Apply Patch requires VZ_DIFF_PTCH to be referenced.

FSL2GetMetaDataFromPatchFile

public static extern UInt32 getMetaDataFromPatchFile
 (
   string patchFileName,
   string metaFileName,
   [MarshalAs(UnmanagedType.LPStr, SizeConst = MAXIDLEN)] StringBuilder content
 );

There may come a time where you want to find out what's in a Patch File which is where FSL2GetMetaDataFromPatchFile comes into play. In each VPA both the Target and Source layer's GUIDs and Names are stored for easy reference. To get them pass in the path to a patch file and then what you'd like to get, there are four constants defined for this: VZ_META_TARGET_GUID, VZ_META_SOURCE_GUID, VZ_META_TARGET_LAYER and VZ_META_SOURCE_LAYER. These are pretty self explanatory and the information returned into a StringBuilder set to the size of FSL2_MAXIDLEN which is another constant.

Patch Status

When using C++ you can just pass a null in for VZ_DIFF_PTCH but that's not doable, as far as I've been able to tell, in .Net because the way I've coded it-- the application is expecting a function to be passed in to the delegate VZ_PTCH_CB_FUNC, and while a function needs to exist it can be as simple as what you see below:

public static void patchStatus(FSL2.VZ_DIFF_PTCH CBInfoFunc)
 {

 }

To report back to a user a status you would use the object CBInfoFunc, which is an instance of VZ_DIFF_PTCH, to compare to one of the status enumerations.

if (FSL2.VZ_CREATE_STAGES.VZ_CREATE_BEGIN == CBInfoFunc.currentStage)
 {

 }

In the example above we're checking to see if CBInfoFunc's current stage is equal to the start of a create patch archive call (VzCreatePatchA) and if it is we'll report something. But maybe you just want to report the percentage complete and nothing else, then all you'd need is a console write and no if statements as the code below shows:

Console.CursorLeft = 0;
Console.Write(CBInfoFunc.totalPercent+"%");

Seeing it in Action

The sample code below is going to do a few things:

  1. create some layer
  2. create a patch file from those layers
  3. apply a patch to a layer
FSL2 mySVS = new FSL2();
 StringBuilder myGuid = new StringBuilder(FSL2.MAXIDLEN);
 FSL2.createLayer("sourceLayer", FSL2.LAYER_TYPE_NORMAL, true, myGuid);
 StringBuilder myGuid2 = new StringBuilder(FSL2.MAXIDLEN);
 FSL2.createLayer("targetLayer", FSL2.LAYER_TYPE_NORMAL, true, myGuid2);
 UInt32 result = FSL2.createPatch(myGuid.ToString(), myGuid2.ToString(), "C:\\myPatch.vpa", true, new FSL2.VZ_PTCH_CB_FUNC(patchStatus), ref mySVS.diffUserData);
 result= FSL2.DeleteLayer(myGuid2.ToString(), true);
 Console.WriteLine("waiting to apply patch");
 Console.Read();
 result= FSL2.applyPatch("C:\\myPatch.vpa", false, true, patchStatus, ref mySVS.diffUserData);
 Console.WriteLine();
 Console.WriteLine("Done, code "+result);

The above code is doing a lot but is pretty simple. I'm creating two empty layers-this is just so you can see how patch works-- and then creating a patch file from them, so it's really small, deletes the source layer and then waits for user import to apply the patch. The Console.Read() allows you time to look at SVSadmin to see what the layer is before the patch and then after the patch.

Below is the patchStatus function that you can use.

public static void patchStatus(FSL2.VZ_DIFF_PTCH CBInfoFunc)
 {
  Console.CursorLeft = 0;
  Console.Write(CBInfoFunc.totalPercent+"%");
 }

Conclusion

There you have, the first API for a new feature for SWV. I started with Patch because I thought it was one people would want to use and play around with (there's a lot of stuff you can do with it that isn't what the original purpose of the feature intended) and it will be interesting to see what people come up with. Part 3 will cover Layer Cloning and Layer Merging (setting a new reset point) and probably something else.

Return to the Virtualization SDK Book

Comments 1 CommentJump to latest comment

meggie_woodfield's picture

For anyone interested in this topic, there is now a video on creating layer patches posted on Connect here.

0
Login to vote