Video Screencast Help

SVS 2.X SDK Guide Part 4: Layer Attributes

Created: 29 Apr 2008 • Updated: 29 Jul 2010
Language Translations
Jordan's picture
0 0 Votes
Login to vote

By now if you've been following along with my article series you should be able to initialize SVS, perform common actions and Import and Export, so what next? A common task in SVS is to get a layer name from a GUID or vice-versa, which is where Layer Attributes come into play. But it's not just getting GUIDs, you can do a lot more with SVS Attributes such as the location of the redirect paths or if a layer is active or not.

This is something you've seen in WMI already. But with the SDK there are a lot more options that aren't exposed to WMI or even used in SVSadmin that you could take advantage of if you want.

Changes to FLS2 Class

Two new Enumerations have been added to SVSStuct.cs, VzDataType and VzLayerAttribute as well as one new structure.

Several new methods have been marshaled in ManagedSVS.cs

A few new Constants have also been added.

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

FSL2GetLayerInfo vs. VzGetLayerAttribute

Both of these methods can be used to get a layer attributes, the main difference is FSL2GetLayerInfo returns a structure of all the attributes while VZGetLayerAttribute returns a single attribute via enumerations. Their respective set methods also work similar, FSL2SetLayerInfo allows you to set many attributes at once while VzSetLayerAttribute only allows for one.

Lastly there are attributes that can only be touched by one of these two methods and not both, these are:

  • GetLayerInfo: PeerName, RegPath, Enabled, LastActiveTime, CreateTime, LastRefreshTime, CompressionLevel
  • VzGetLayerAttribute: Company, Author, Notes, ReadOnly, Flags

VzGetLayerAttribute

One of the tricks to get VzGetLayerAttribute to work in .Net is it requires a LPVOID type for it's buffer. LPVOIDs are basically a undefined type that then gets defined at the time a value is assigned to it. This is something you can't do in C# that I'm aware of. However this problem is easy to work around because we know that we have only two types of attributes, string and integers, so we know what type of variable we need going into the attribute request.

Armed with this info I created two separate versions of the VzGetLayerAttribute method: vzGetLayerAttributeInt and vzGetLayerAttributeString. They're pretty much the same except the passed in buffer is an integer in one and a stringBuilder in the second as you can see below.

vzGetLayerAttributeInt

public static extern UInt32 vzGetLayerAttributeInt
 (
  string layerId,
  VzLayerAttribute layerAttribute,
  ref VzDataType attributeDataType,
  ref int buffer,
  ref UInt32 cbBuffer
);

vzGetLayerAttributeString

public static extern UInt32 vzGetLayerAttributeString
 (
  string layerId,
  VzLayerAttribute layerAttribute,
  ref VzDataType attributeDataType,
  [MarshalAs(UnmanagedType.LPStr)] StringBuilder buffer,
  ref UInt32 cbBuffer
 );
 

In these methods you'll notice two lines that point to our Enumerations, VzLayerAttribute and VzDataType. We'll cover these in the next section, but if you've read over the Import/Export article you should know what's going on here. For those that don't we're going to create two objects of custom enumerations so that these functions can use them.

VzLayerAttribute is the first enumeration and it is what we'll use to tell SVS what layer attribute we want for the GUID we passed in as layerId. VzDataType returns if it's a string or an integer and while this isn't something that's important for the .Net class it's necessary for the C++ users out there so they know what type the LPVOID contains so they can reference it properly.

Note: The buffer size for the string buffer is always 64 and the size for the integer buffer is always 4.

VzLayerAttribute

public enum VzLayerAttribute 
 {
  VzLayerAttributeLayerId,
  VzLayerAttributeName,
  VzLayerAttributeCompany,
  VzLayerAttributeAuthor,
  VzLayerAttributeNotes,
  VzLayerAttributeVersion,
  VzLayerAttributeActiveOnStart,
  VzLayerAttributeActive,
  VzLayerAttributeFileRedirPath,
  VzLayerAttributeRegRedirPath,
  VzLayerAttributeFlags,
  VzLayerAttributeLayerMajorVersion,
  VzLayerAttributeLayerMinorVersion,
  VzLayerAttributeReadOnly,
  VzLayerAttributeType,
  VzLayerAttributePeerLayerId
 }
 

Here's our first enumeration, and as you can see there are a lot of attributes that you're probably not familiar with such as Company, Author and Notes. These are fields that you can use if you want to help keep track of who made what (so author), your company name and well Notes that can be really anything you want.

A few other attributes are worth pointing out as well, such as Version which is what SVS layer version that is. It can be different than the driver version. This is useful to check for compatibility errors that can arise from going from some SVS versions to a newer one (such as 1407 to 2069), SVSadmin will actually convert a layer from one version to another but there's no API for doing this so you'll have to code it yourself or just not let it run.

Major and Minor Version also tells you what layer version your layer is, currently we're at layer 2.2 (even though SVS is 2.1) with Major Version being the first number and Minor Version being the second number.

Flags are something that, while you can access via this method (and set them as well with VzSetLayerAttribute), you really shouldn't mess with. Basically any flag that gets set in SVS for a layer, such as read only, ignore global excludes and so fourth, change this value. All the flags have API that will change them for you and it's highly recommended that you use those methods to do so.

Lastly is type which can either be read, read/write, or data. Constants have been added for each of these types as LAYER_TYPE_NORMAL, LAYER_TYPE_PEER and LAYER_TYPE_DATA respectively.

VzDataType

public enum VzDataType 
 {
  VzDataTypeDword,
  VzDataTypeString
 }

Our second enumeration is short and sweet and, as mentioned above, will return either that it's a Dword (integer) or a string.

VzSetLayerAttribute

public static extern UInt32 VzSetLayerAttributeInt
 (
  string layerId,
  VzLayerAttribute layerAttribute,
  VzDataType attributeDataType,
  int buffer,
  UInt32 cbBuffer
 );

So now that we know how to get the layer attributes we need to be able to change them if we want. You'll notice that as with VZGetLayerAttribute there are two different methods, one for integers and one for strings. There's also one other change which is we're using a pointer with VzDataType but instead passing in a data type directly so the library knows what you're sending it, we're also doing the same with the buffer size. Now it may seam silly that we still have two separate methods to deal with data types despite one being passed in but this is again a .Net issue because the LPVOID type doesn't exist so we're doing the dual methods trick for C#'s sake and passing the data type enumeration value for the API's sake.

FSL2GetLayerInfo

public static extern UInt32 getLayerInfo
 (
  string layerId,
  [In,Out] Info pInfo
 );

GetLayerInfo is a much simpler method then VzGetLayerAttribute but it requires you to get all the attributes for a layer which you may not want to do due to memory requirements. The method populates a structure, which you point to, named FSL2Info that contains much of the same information you can get with VzGetLayerAttribute. The differences are listed below:

PeerName, lactActivatedTime, createTime, lastRefreshTime, regPath, enabled and compressionLevel are attributes only available through this method while Company, Author, Notes, Flags and ReadOnly are not accessible. RegPath is the location, in the registry, where attributes are stored-which is essentially SYSTEM>Altiris>FSL>magicNumber. The other attributes unique to GetLayerInfo are pretty self explanatory from the names alone and don't need further explanation.

FSL2SetLayerInfo

public static extern UInt32 setLayerInfo
 (
  string layerId,
  string layerName,
  string fileRedirect,
  string regRedirect,
  ref UInt32 pType,
  ref UInt32 pReadOnly,
  string peerGuid
 );

SetLayerInfo, unlike GetLayerInfo, works with .Net and is actually quite convenient since it allows you to set multiple layer attributes at once. It bypasses the structure and you pass in the value for each attribute into the method with nulls for attributes you don't want to change. It doesn't allow you to change all the attributes of a layer but it does allow you to change the Guid, name, redirect paths, type of the layer (as a pointer) and the Guid of the peer. SetLayerInfo also allows you to change the layer to change the ReadOnly status of a layer like VzSetLayerAttribute.

FSL2Info Structure

public class Info 
 {
  public UInt32 dwStructSize;
  public bool bIsGroup;
  public UInt32 dwLayerType;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string name;// FSL2_MAXNAMELEN
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string peerName;// FSL2_MAXNAMELEN
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string regPath;// FSL2_MaxReg
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string fileRedirPath;// FSL2_MaxPath
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string regRedirPath;// FSL2_MaxReg
  public UInt32 active;
  public UInt32 activeOnStart;
  public UInt32 enabled;
  public UInt32 majorVersion;
  public UInt32 minorVersion;
  public UInt32 lastActivatedTime;
  public UInt32 createTime;
  public UInt32 lastRefreshTime;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 200)] public string fslGUID;// FSL2_MAXIDLEN_BYTES
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 200)] public string peerGUID;// FSL2_MAXIDLEN_BYTES
  public UInt32 compressionLevel;
 }

FSL2Info is very similar to past structures we've seen before. An instance of it needs to be created (see Part Three for more info), pInfo in our case. However unlike other structures we've used, FSL2Info requires a size to be assigned before it can be used. This is done by marshaling in, for .Net, the size of the structure after the pInfo has been created to dwStructSize. This will be demonstrated in the "Seeing it in Action" section below.

Custom Attributes

One of my favorite features in SVS that's not used in SVSadmin or SVScmd is Custom Attributes. There's so much potential with these, which let you-as the name would imply-define your own SVS Layer Attributes. There are two API available for this, VzGetCustomLayerAttribute and VzSetCustomLayerAttribute. The downside to Custom Attributes is there is no way natively to query what Custom Attributes a layer has. You could create something that checks in the registry for anything that's not a standard SVS Layer Attribute and go off of that. Despite this missing feature they're quite useful.

The Custom Layer Attribute methods work just like VzGet/SetLayerAttribute functions except you're not using the VzLayerAttribute enumeration. There needs to be separate methods for both get and set with regards to string values and numeric ones, and you're still pointing to VzDataType even though you're not using it.

Seeing it in Action

In this code sample I'm just going to show how you use VzGetLayerAttribute and GetLayerInfo with a simple example.

FSL2 mySVS = new FSL2();
        string myGuid = "3a8100e9-527a-46cd-88cb-8c519c4cc7fb"; 
        int myBuffer = 10;
        myBufferSize = 4;
        FSL2.vzGetLayerAttributeInt(myGuid,FSL2.VzLayerAttribute.VzLayerAttributeVersion, ref mySVS.attributeDataType,ref myBuffer,ref myBufferSize);
        Console.WriteLine("my buffer: " + myBuffer);
        StringBuilder myBuffet = new StringBuilder(64);
        myBufferSize = 64;
        UInt32 result = FSL2.vzGetLayerAttributeString(myGuid, FSL2.VzLayerAttribute.VzLayerAttributeRegRedirPath, ref mySVS.attributeDataType, myBuffet, ref myBufferSize);
        Console.WriteLine("my buffet: " + myBuffet);
        mySVS.pInfo.dwStructSize = (UInt32) Marshal.SizeOf(mySVS.pInfo);
        result = FSL2.getLayerInfo(myGuid, mySVS.pInfo);
        Console.WriteLine("layer type: " + mySVS.pInfo.compressionLevel);
        Console.WriteLine("layer name: " + mySVS.pInfo.minorVersion);

        Console.Read();

This is a fairly simple set of code, but as always there are a few things to point out.

FSL2 mySVS = new FSL2();

Like all examples the first thing we need to do is create an SVS object.

string myGuid = "3a8100e9-527a-46cd-88cb-8c519c4cc7fb"; 

For simplicity's sake I'm just passing in a known GUID, you'll obviously have to change this to get it to work.

int myBuffer = 10;

I'm defining the int buffer to be 10 so I know if it changes, there should be nothing that returns a 10 in these variables by default.

mySVS.pInfo.dwStructSize = (UInt32) Marshal.SizeOf(mySVS.pInfo);

I mentioned in the getLayerInfo section that you had to initialize the size of the info structure--this is how you do that in C#.

Conclusion

That's layer attributes in a nutshell. It's a little confusing that the two methods don't cover the same attributes so you can't use them interchangeably but neither at that complex. Part Five will cover capturing and creating layers.

Remember that future versions will be listed in the FSL2 Class Portal where the FSL2 class is available for download. Be sure to subscribe to that thread which will inform you of any new articles and updates to the class.

Return to the Virtualization SDK Book