Video Screencast Help

SVS 2.X SDK Guide Part Nine: Enumeration of Layers

Created: 12 Mar 2009 • Updated: 29 Jul 2010 | 2 comments
Language Translations
Jordan's picture
+9 9 Votes
Login to vote

The last article in this SVS SDK series is going to cover something quite important for anyone wanting to create their own SVS tool, Enumerating Layers. While this is something that I should have posted in one of the first few articles, getting the list of layers is something that I've held off on because I could never get the function set to work, and have only recently had the time to figure out why.

Changes to the FSL2 Class

Several new functions have been added to managedSVS.cs

A new structure has been in SVSstruct.cs

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

Finding Layers on a System

Up until now we've always assumed you knew the layer names and GUIDs for the tools you were writing. In all honesty that's not a very practical or efficient method and something that you cannot use in the real world. Up until now you'd have to query the WMI object to get all the information needed, hit the registry under HKLM -> SYSTEM -> FSL, or figured out how to marshal in the FSL2FindLayers functions yourself.

In the SDK there are three methods and one structure relating to enumerating layers. All four items require each other to work. These are FSL2FindFirstLayer, FSL2FindNextLayer, FLS2FindCloseLayer and the structure FSL2Find. Since it's required before you can call the first method, we're going to start with FSL2Find.

FSL2Find

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
 public struct Find
 {
  public UInt32 dwStructSize;
  UInt32 index;
  IntPtr key;
  bool includePeers;
 }
 

FSL2Find is a rather simple structure, it had a size, index and pointer to regkey and bool to let it know if you're looking for the peer (the Read Write layer). But the best thing about FLS2Find is outside of initializing it and setting it's structure size, you never have to do anything more but pass a reference to it in your function call. FSL2Find is automatically created if you're using the FSL2 Class I'm providing just like FSL2Info and other structures we've talked about, just remember to set it's structure size it because I don't do that for you.

FSL2FindFirstLayer

Once we have our Find structure created and it's size defined we can call the first of the Find Layer Functions.

public static extern UInt32 findFirstLayer
 (
  ref Find fslFind,
  [MarshalAs(UnmanagedType.LPStr)] StringBuilder fslGUID,
  bool includePeers
 );
 

FSL2FindFirstLayer is a simple function that has a slightly complicated use. All you need to do to get it to work is pass in a reference to the FSL2Find structure you created, a GUID StringBuilder that will return the found layer's GUID (much like you get a GUID with FSL2Import or FSL2CreateLayer) and a bool to tell the function if you want the peer layers (Read Write SubLayers) returned as well. If any layer is found it will return a success (a 0) and if nothing is found it will return a 1006 FSL2_Error_Bad_Args.

FSL2FindNextLayer

Next you need to find all the other layers on the system. Unless you only have one or two layers you're going to have to use FSL2FindNextLayer in a loop, either a While or a Do While loop - it doesn't matter which, so you can use the loop method you prefer. However a Do While is recommended since you'll want to run through whatever your task is (such as adding the layer name and GUID to a list) on the first layer found before finding the second layer.

public static extern UInt32 findNextLayer
 (
  ref Find fslFind,
  [MarshalAs(UnmanagedType.LPStr, SizeConst = MAXIDLEN)] StringBuilder fslGUID
 );
 

To use FSL2FindNextLayer you need to pass in the reference to your FSL2Find structure and the same GUID StringBuilder as before. How this works is the index inside of FSL2Find is getting incremented and the IntPtr to the regkey to know where the last layer found was. So the function set finds a layer, makes the changes to the structure and then waits for either a close (discussed next) or for another FSL2FindNextLayer to be called. Like FLS2FindFirst layer FSL2FindNext layer returns a success (a 0) when it finds a new layer, so you'd have your loop continue to run while FSL2FindNextLayer == FSL2.Error_Success.

FSL2FindCloseLayer

Finally once the last layer is found you call FSL2FindCloseLayer to end the process.

public static extern UInt32 findCloseLayer
 (
  ref Find fslFind
 );
 

All you need to do is pass in the reference to our FLS2Find structure and that's it.

Seeing it in Action

This code sample will illustrate how the FSL2 Find Layer methods work together to get a list of all the layers on the system. We're going to write a simple command line tool that will get all the layers on a system and then allow you to activate or deactivate them based off what's passed into the command line. I'll let you write the command line parser and determine how you want the functions to be called.

First off we need to create a class to store all the information needed for each layer, this is outlined below:

public class svsLayer
 {
 //constructor
 public svsLayer(string GUID, string layerName, string type, bool isActive, bool isAutoStart)
 {
 this.GUID = GUID;

 

this.layerName = layerName; this.type = type; this.isActive = isActive; this.isAutoStart = isAutoStart; } //overload public svsLayer() { } //properties private string _GUID; public string GUID { get { return _GUID; } set { _GUID = value; } } private string _layerName; public string layerName { get { return _layerName; } set { _layerName = value; } } private string _type; public string type { get { return _type; } set { _type = value; } } private bool _isActive; public bool isActive { get { return _isActive; } set { _isActive = value; } } private bool _isAutoStart; public bool isAutoStart { get { return _isAutoStart; } set { _isAutoStart = value; } } //methods public string changeStatus(){ if(this.isActive){ if (deactivateLayer()) { this.isActive = false; return "deactive"; } }else{ if (activateLayer()) { this.isActive = true; return "active"; } } return "error couldn't change layer status"; } private bool activateLayer(){ UInt32 result= FSL2.ActivateLayer(this.GUID, false); if (result == FSL2.ERROR_SUCCESS) { return true; } else { return false; } } private bool deactivateLayer() { UInt32 myPid=0; UInt32 result = FSL2.deactivateLayer(this.GUID, true, myPid); if (result == FSL2.ERROR_SUCCESS) { return true; } else { return false; } } }

This class has two constructors so you can either pass in the information needed when creating the class or you can create it and add it the info afterwards. The properties should be pretty self explanatory, there are a lot more you can add, like PeerGuid and createTime, I only did a few. There are three methods as well, one is public and two private, which change the active status of a layer, just call changeStatus and if the layer is active the method will deactivate it and if it's deactive it will get activated.

Now that the SVSLayer class is defined we need the code that enumerates the layers and adds them to a list of SVSLayers:

FSL2 mySVS = new FSL2();
 mySVS.fslFind.dwStructSize = (UInt32)Marshal.SizeOf(mySVS.fslFind);
 mySVS.pInfo.dwStructSize = (UInt32)Marshal.SizeOf(mySVS.pInfo);
 StringBuilder myGuid = new StringBuilder(FSL2.MAXIDLEN);
 List<svsLayer> layerList = new List<svsLayer>();
 UInt32 result = FSL2.findFirstLayer(ref mySVS.fslFind, myGuid, false);
 
 if(FSL2.ERROR_SUCCESS==result){

 do
 {
 
 if (FSL2.ERROR_SUCCESS == FSL2.getLayerInfo(myGuid.ToString(), mySVS.pInfo))
 {
 svsLayer myLayer = new svsLayer();
 myLayer.GUID = myGuid.ToString();
 myLayer.layerName = mySVS.pInfo.name;
 if (mySVS.pInfo.active == 2)
 {
 myLayer.isActive = true;
 }
 else
 {
 myLayer.isActive = false;
 }

 if (mySVS.pInfo.activeOnStart == 2)
 {
 myLayer.isAutoStart = true;
 }
 else
 {
 myLayer.isAutoStart = false;
 }

 if (mySVS.pInfo.dwLayerType == FSL2.LAYER_TYPE_NORMAL)
 {
 myLayer.type = "Layer";
 }
 else if (mySVS.pInfo.dwLayerType == FSL2.LAYER_TYPE_PEER)
 {
 myLayer.type = "Peer";
 }
 else if (mySVS.pInfo.dwLayerType == FSL2.LAYER_TYPE_DATA)
 {
 myLayer.type = "Data";
 }
 else
 {
 myLayer.type = "Unknown";
 }
 layerList.Add(myLayer);
 }
 
 } while (FSL2.ERROR_SUCCESS == FSL2.findNextLayer(ref mySVS.fslFind, myGuid));
 FSL2.findCloseLayer(ref mySVS.fslFind);

 foreach (svsLayer myLayer in layerList)
 {
 Console.WriteLine("Layer Name: "+myLayer.layerName);
 Console.WriteLine("is Active: "+myLayer.isActive.ToString());
 Console.WriteLine("is Auto Start: " + myLayer.isAutoStart.ToString());
 }
 
 }
 

This block of code is doing several things. First off it initializes the SVS object and then sets the sizes of our structures and creates our list of SVSLayers. Once that's all done FSL2.FindFirstLayer is found and if it returns a success we move on to our Do While loop which then gets the layer info (you could use VzGetLayerAttributes too), saves the information we want into the SVSLayer class myLayer and adds that to our list of layers. Finally, after the loop ends, we close off the find process and then we enumerate through all the layers saved to see what we have. This last for each is obviously something that you wouldn't want to use in a real tool but it's been added so you can see that the code works.

Conclusion

Part Nine ends the series on the SVS 2.1 SDK documentation and while there are still some functions that I haven't added the FSL2 Class with most of those things you'll never use, and I may add a part 10 sometime down the road, but with this series of articles you have all the information you need to create any tool you might need to take full advantage of SVS.

Return to the Virtualization SDK Book

Comments 2 CommentsJump to latest comment

clivant's picture

Hi Jordan,

I could not retrieve the layers via the above mentioned codes in Windows 7 64 bit versions. I could however do so in Windows 7 32 bit versions.

Any ideas on why?

0
Login to vote
clivant's picture

The result number returned from the call to FSL2.findFirstLayer is 1006, which correspond to FSL2_ERROR_BAD_ARGS. Do I have prepare the mySVS.fslFind structure differently in the windows 7 64 bit environment?

0
Login to vote