Video Screencast Help
Scheduled Maintenance: Symantec Connect is scheduled to be down Saturday, April 19 from 10am to 2pm Pacific Standard Time (GMT: 5pm to 9pm) for server migration and upgrades.
Please accept our apologies in advance for any inconvenience this might cause.

SVS 2.X SDK Guide Part 8: Rights, Priorities, and Processes

Created: 01 Jul 2008 • Updated: 29 Jul 2010 | 6 comments
Language Translations
Jordan's picture
+2 2 Votes
Login to vote

As we near the end of the SDK documentation there are only a few more things to cover. While most of remaining functions fall into a specific category a few don't, so I' ll be spreading those that don't between parts eight and nine (the last article). The main focus for this article is layer rights (or permissions), layer priority and processes (namely ignoring them and running one from an existing layer).

Changes to the FSL2 Class

Several new functions have been added to managedSVS.cs

A few new constants have been added to SVSconst.cs

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

Layer Rights

Permissions in SVS 2.X aren' t as robust as most people would like. You really can only affect activate, deactivate by enabling them for non-admins so there aren' t many functions that relate to user rights, in fact there' s only one. There are no functions in the SDK for enabling non-admins the ability to activate and deactivate so you' ll have to create your own script or do it manually, thankfully that' s easy. All you need to do is create a key named Activate or Deactivate under HKLM -> System -> Altiris -> Rights (which you' ll also have to create) and any use that has read access to those locations will have the ability to activate or deactivate. The driver handles all permission checking in SVS, so you don' t have to do anything on your end if you don' t want, if you don' t have permission that error will get returned. However if you' re working with a GUI based application you' ll want to have a way to check to see if someone can perform an action based on their rights before actually calling the function. That' s where FLS2checkRights comes into play.

FSL2CheckRights

public static extern bool checkRights
(
  int right
 );
 

CheckRights is a fairly straight forward function, it checks to see if you have rights and then returns true or false. There are three valid values for the right variable: USER_RIGHTS_ADMIN, USER_RIGHTS_ACTIVATE, and USER_RIGHTS_DEACTIVATE.

Layer Priority

Layer priority can be confusing, what they do is affect in what order a layer is in a "stack" so when an application is looking for something it will go in the order of that stack. I' m not going to cover how priority works or anything relating to it outside of these two functions in the SDK because it' s covered quite well in the actual SVS documentation which you should read before continuing if you' re interested in manipulating priorities. I will state, however, that you should never make any SVS layers lower then the base or you' ll break things and you really should only change the decimal value instead of the tens value. You should also always test priority changes in a VM extensively before moving them to any live machines.

FSL2GetLayerPriority

public static extern UInt32 getLayerPriority
 (
   string fslGUID,
   int priorityType,
   [MarshalAs(UnmanagedType.LPStr)] StringBuilder priorityBuffer,
   UInt32 cbPriorityBuffer,
   [MarshalAs(UnmanagedType.LPStr)] StringBuilder defaultPriorityBuffer,
   UInt32 cbDefaultPriorityBuffer
 );
 

GetLayerPriority does a few things. First off you pass in a GUID and a Priority Type which can be any of the following: LAYER_PRIORITY_TYPE, LAYER_PRIORITY_TYPE_HKCR, LAYER_PRIORITY_TYPE_OWNER, LAYER_PRIORITY_TYPE_HKCR_OWNER. Type means base, owner means the layer that owns the process, for more information read the section on layer prioritization in the SVS user manual (Linked above).

Once you pass in the layer GUID and the Priority Type you get two things returned, the current priority of the layer and then that layer' s default (each layer has it' s own). As with all string buffers these are string builders of size 64, which you' ll use when creating the size of the buffer as well passing into the cb buffer variables.

FSL2SetLayerPrioity

public static extern UInt32 setLayerPriority
 (
   string fslGUID,
   int priorityType,
   string priority
 );
 

SetLayerPriority takes in a GUID and a priorityTYpe (see above) and then what the new priority should be. Simple enough. A mistake to watch out for though is that even though priority is a number (for example 65.5) we' re passing it in as a string and not as a number.

Ignoring Processes

There are times where you want to hide the virtualized path from a program so it only sees the FSLRDR path, this is useful for both Firewalls and Anti-Virus programs (the former which can block apps or take up processing power, the latter because they can pull files from the layer into the base). In fact it' s a good idea to ignore any security related process or program that will be on your system especially if it opens files for writing or does deleting.

There are two API for dealing with ignoring Processes, one for setting and one for removing a process, however, there' s no API for actually querying what processes are being ignored by SVS. Like so many other things this can be pulled out of the registry if you want. There' s a single Multi-String Value under HKLM -> System -> Altiris ->FSL named ProgramIgnoreList. each new line is a different process being ignored. You can also directly add items to that value if you don' t want to use the available APIs which only work with a PID.

Note: For a process added to the list, or removed from the list, to get ignored (or unignored) you have to reastart the system.

FSL2IgnoreProcess

public static extern UInt32 ignoreProcess
 (
   UInt32 processId
 );
 

IgnoreProcess takes a PID and will add the corresponding executable to the process ignore list.

FSL2EndIgnoreProcess

public static extern UInt32 endIgnoreProcess
 (
   UInt32 processId
 );
 

EndIgnoreProcess is the opposite of IgnoreProcess, the PID that gets passed in, if the corresponding executable is found on the list, is removed from the process ignore list.

Running a Process from a Layer

There' s one other process related which allows you to run a process as if it' s captured into layer already - meaning any changes this process makes go to the layer even though the program is in the base. This is a very useful feature that not a lot of people use. It' s available in SVScmd as the poorly named "Execute from layer" and the API is even worse off name wise.

FSL2SetPidRunningFromLayer

public static extern UInt32 setPidRunningFromLayer
 (
  string layerId,
  UInt32 pid,
  bool runFromLayer
 );
 

SetPidRunningFromLayer takes a GUID of the layer you want to run the process in, the PID of the process you want to run in the layer and lastly a true or false for it you want to run the process in the layer. True means you want to start, false means you want to stop.

Make sure the layer in question is active because the API will not error out if a layer exists but isn't active.

Getting the Layer Name or GUID

If you' ve been following along through all the SDK articles up until now you' ll notice that all the functions require a layer GUID to do anything, but what if you only have a layer name? While it' s not best practice to do so (because there could be more then one layer with the same name) it does happen, SVScmd is an example. You have it list all the layers, then use the layer name to bring up properties to get a GUID or you can use that layer name to do any of the SVScmd options like activate and so on.

To do this using the SDK you could load all the layers into an object and then go through each until you find one with the passed in name or you can use getLayerGUIDFromName.

FSL2GetLayerGUIDFromName

public static extern UInt32 getLayerGUIDFromName
 (
   string fslName,
   [MarshalAs(UnmanagedType.LPStr)] StringBuilder fslGuid
 );
 

GetLayerGUIDFromName takes in a string and returns a GUID as a stringbuilder. You' ll need to initialize the stringbuilder' s size to the constant MAXIDLEN which is in the constant list and is 100 in size.

FSL2GetLayerNameFromGUID

public static extern UInt32 getLayerNameFromGUID
(
   string fslGuid,
   [MarshalAs(UnmanagedType.LPStr)] StringBuilder fslName
 );
 

getLayerNameFromGUID does the opposite, it gets a layer' s name from a GUID. This isn' t as useful since you can always use one of the layer properties functions to get this info but it takes fewer lines of code to do so. For the stringbuilder you need to set it' s size to the constant MAXNAMELEN which is 64 in size.

Seeing it in Action

This is a short code sample that will illustrate running a program that' s not in a layer from a layer using setPidRunningFromLayer and the .Net System.Diagnotices.Process class.

We' re going to take in 3 parameters, a layer name or GUID, a path to the EXE, and any arguments so basically just what the API expects except we' re not allowing people to stop running a process in a layer plus the added arguments for the EXE.

FSL2 mySVS = new FSL2();
string myGUID = "";
      if (args[0].Length != 36)
      {
        StringBuilder myGUIDSB = new StringBuilder(FSL2.MAXNAMELEN);
        FSL2.getLayerGUIDFromName(args[0], myGUIDSB);
        myGUID = myGUIDSB.ToString();
      }
      else
      {
        myGUID = args[0];
      }
      System.Diagnostics.Process proc = new System.Diagnostics.Process();
      proc.StartInfo.FileName = args[1];
      proc.StartInfo.Arguments = args[2];
      proc.StartInfo.UseShellExecute = false;
      proc.StartInfo.RedirectStandardOutput = false;
      proc.Start();
	UInt32 myPID = (UInt32) proc.Id;
	FSL2.setPidRunningFromLayer(myGUID,myPID,true);
	

The first thing we' re doing is checking to see if the layer name/GUID argument is 36 characters in length which is the length of a GUID if it' s not we get the layer GUID via the layer' s name. There' s a better way of handling this check because there' s bound to be layer names that are 36 character' s long which would cause this script to fail.

Next we create a new process using the process class under System.Diagnostics, we pass in the filename (which is the path) and any arguments we have. I' m also stating we don' t want to execute via the Shell or redirect output, you can read more about what those two settings do on the MSDN if you want to use them but for now it' s best to leave them off.

Lastly we start the process, get the ID of the process then tell it to either start running via the layer.

Note: We cannot get a PID until after we start the process. There could be some stuff that doesn' t get captured if anything gets modified between the time it takes .Net to create the Process, get the PID and then run the SVS API. SVScmd and API like capture create processes in a similar manner but they start suspended which allows for SVS to get the PID and pass it into the proper function before starting the application. .Net doesn' t have a way to do this that I know of.

Conclusion

Part 8 covers some of the more confusing and abstract concepts of SVS such as Layer Permissions and running a process in a layer among others. Despite the complexity of using these features they all add something to SVS that allows for some really powerful tools. Part 9, the last article in the series, will cover Delete Entries, how to actually get a list of SVS layers on a system and a few other odd and ends.

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

Comments 6 CommentsJump to latest comment

philbenson's picture

Hi Jordan,
I've been following all your articles so far, and I must say they make good reading, it's just a shame that your code is .NET

I read with interest about the API call to run processes from the 'layer' or to ignore processes. I used the 'raw' c interface to these API's and found that they did not always work as expected when you first create the process (in a suspended state), pass the PID to the svs api, and then resume the process.

Perhaps this is because I was using the 'c' api directly (and VC++)... what have your experiences been on a more 'practical' level?

Thanks, and keep the articles coming,
B.R.
Phil

+2
Login to vote
Jordan's picture

I should update my article here for this answer.

For a process ignore to work you have to restart the system, same with removing something from the list.

For running a process from the layer, and this may seam silly to point out but I forget all the time, your layer has to be active. The API will still work if the layer isn't so sometimes you don't even know that's happening until after you're done with the program you were running.

I've never used running in a layer with C/C++ I don't know those languages that well as so my only experience is with .Net and SVScmd. However, the API are the same no matter the language so they should work fine.

If a forum post solves your problem please flag is as the solution

+1
Login to vote
DaneZ's picture

Hi Jordan,

I try and retry to make working getLayerPriority but I always have that:

"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

Do you have an idea of the problem ?

Part of code used;
StringBuilder priorityBuffer = new StringBuilder(FSL2.MAXNAMELEN);

StringBuilder defaultPriorityBuffer = new StringBuilder(FSL2.MAXNAMELEN);

string fslguid = "e34bdf55-33a3-4d2d-aa35-f467280cebeb";
FSL2.getLayerPriority(fslguid, FSL2.LAYER_PRIORITY_TYPE, priorityBuffer, 64,
defaultPriorityBuffer, 64);

Regards,
DaneZ

+1
Login to vote
Jordan's picture

Odd, that should work.

The error you're getting usually means the buffer size is wrong, I'll have to check to see if FSL2GetLayerPriority is an exception to the 64 string size.

If a forum post solves your problem please flag is as the solution

+1
Login to vote
DaneZ's picture

I have try to determine the good value with a while loop but nothing ..
I think the import declaration is not good.
(for information, I use SVS SP2)

code used to determine buffer:
int Bufsize = 1;
while (Bufsize <= 65535)
{
try
{
StringBuilder priorityBuffer = new StringBuilder(Bufsize);
StringBuilder defaultPriorityBuffer = new StringBuilder(Bufsize);

string fslguid = "e34bdf55-33a3-4d2d-aa35-f467280cebeb";

uint res=FSL2.getLayerPriority(fslguid, FSL2.LAYER_PRIORITY_TYPE, priorityBuffer, (uint)Bufsize,
defaultPriorityBuffer, (uint)Bufsize);
MessageBox.Show("Bufsize: " + Bufsize, "", MessageBoxButtons.OKCancel);

}
catch {
}
Bufsize++;
}
MessageBox.Show("finished", "", MessageBoxButtons.OKCancel);

+1
Login to vote
Jordan's picture

The funny thing is FSL2GetLayerPriority is pulling the priority from the registry just like all the other property functions so it's funny this one won't work.

So since this is just a registry value you can hit HKLM->System->Altiris->FLS for the layer number and then look for it. if you haven't changed the layer priority then there will be no entry in the layer to which the API will return 85.5 which is the default for the layer, not sure what it is for the base.

If a forum post solves your problem please flag is as the solution

+1
Login to vote