The Exchange SDK Application Security Module


Many developers requested the ability to set and get permissions on items and folders in the Exchange information store. Security can be complex and hard to understand, so the Application Security Module included with the SDK is especially valuable . The module is installed when you install the Exchange SDK. You can find it in the SDK directory under the Samples/Security folder. The module includes a set of JavaScript and ASP pages that allow you to access and modify the XML security descriptor in both Exchange and SPS 2001. The module can modify permissions either by using the XMLHTTP component on the client or by using ADO on the server. It's up to the application developer to decide which mode to use. I recommend the server-side version if you want the broadest range of browser support. The XMLHTTP component is supported only by Internet Explorer.

Besides providing code to update security descriptors, the module includes an interesting sample application that shows how to use the object model for the module. You can modify this sample application for use in your own applications. The application has an interface similar to the permissions property page in Outlook.

To work with the sample, you just create a new virtual directory. Copy the security files into that new virtual directory and then point your browser to the start.asp page in the virtual directory. If you want to take just the security module files and use them in your application, take the files listed in Table 17-11.

Table 17-11: Application Security Module Files

File

Description

Security.js

Defines the properties and methods for the DACL and Entity objects

LoadSaveDACL.js

Contains properties and methods for loading and saving a DACL

CustomLoadSaveDacl.js

Contains properties and methods for loading and saving a DACL for a non “Internet Explorer browser

Daclstrutil.js

Contains functions for converting DACLs to XML strings and vice versa for non “Internet Explorer browsers

To work with these files in ASP, you just use the #include directive to include the server-side JavaScript files with the rest of your ASP code. The following code snippet shows how to do this:

 <%@ Language=javascript%> <script language="javascript" runat=server src="loadsavedacl.js"></script> <script language="javascript" runat=server src="security.js"></script> 

The security module contains an object model that consists mainly of an Entity object, which is a security principal (a user , usually) and that security principal's SIDs, and a DACL object, which contains one or more entity objects.

You need to know some caveats about the security module, however. First, it cannot change permissions on inherited ACEs. This means that if a user's permissions are inherited from the parent folder, you cannot modify these permissions. Second, the module is written in JavaScript, so if you're using Visual Basic, you have to do some work to load the Internet Explorer control in a form in Visual Basic so you can run code that calls the security module. The Training application setup program does exactly this, as you will see later in this chapter. Also, with the code written in JavaScript, you must make JavaScript the default language for your ASP pages, which means you have to write the rest of your code in JavaScript. If you are like me and prefer to write most of your server-side ASP code in VBScript, this can make working with the security module a bit hard.

If these shortcomings don't affect you, the security module makes the task of working with security easy. We'll look next at the object model for the security module and then at how to perform common security programming tasks using the module.

Entity Object

As mentioned earlier, the security module is made up of Entity and DACL objects. Table 17-12 lists the methods of the Entity object.

Table 17-12: Methods of the Entity Object

Method

Description

ClearByTemplate

Clears a specified DACL from an entity based on a template. You must pass a DACL object used as the template and a string value of an entity to try to match in the template. This name can be an Exchange 5.5 template name such as "Owner", "Author", or "Editor", or a domain\username string.

HasMask

Returns a Boolean that specifies whether the entity has specific rights to the object. You must pass the masks to test for which is a string value.

HasMaskByTemplate

Returns a Boolean and checks to see if an entity has specific rights to an object by comparing the entity rights with a template you specify. You must pass the name of the entity to try to match, such as "Owner", "Editor", or a domain\username. Then you must pass a DACL object to be used as the template to compare with the Entity object.

HasMaskofEntity

Used to determine whether one entity has the same mask as another entity. You must pass to this method the other Entity object. This method returns a Boolean . You can use this method to see if a user has a specific predefined role, such as "Owner" or "Author".

IsEqualMask

Returns a Boolean that specifies whether the entity has exactly the same specified mask. You must pass the bitmask to test the entity against.

IsEqualTo

Returns a Boolean that specifies whether the two entities match exactly. You must pass to this method the second entity to try and test for a match.

MakeEqualToTemplate

Sets the masks in the entity equal to the masks of a template you specify. You must pass a DACL object to use as a template and the name of an entity to match in the DACL object. The module will then set the masks of the entity to match the entity it finds in the DACL template.

SetByTemplate

Adds masks to an Entity object from a template. You must specify the DACL object to use as a template and the name of the entity in the DACL template to add to your specified entity.

Table 17-13 lists the properties of the Entity object.

Table 17-13: Properties of the Entity Object

Property

Description

DisplayName

The display name of the security entity specified by the Entity object. This name is pulled from Active Directory and is usually the friendly name of the user or group .

Inherited

A Boolean property that specifies whether the security descriptor for the entity is inherited from the parent folder.

Masks

The access masks for the entity returned as a hexadecimal number.

NT4Name

The domain and username for the security principal. Note that all the strings used to denote domain and username are double-slashed with the security module, as in \\domain\username .

SID

Returns the SID for the security principal.

SIDType

Returns the type of SID, such as user, group, domain, alias, or well_known_group.

DACL Object

Now that you've seen the methods and properties of the Entity object, let's look at the methods and properties for the DACL object. Table 17-14 lists the methods of the DACL object. I've grouped some similar operations together in the table to make it easier for you to understand how they can be used interchangeably.

Table 17-14: Methods of the DACL Object

Method

Description

AddEmptySecurityEntity

Adds a new Entity object to the DACL object's Entities collection. You must pass the SIDType , such as user, group, domain, alias, well_known_group, deleted_account, invalid, unknown, or computer. You must also pass the SID of the entity. Next you must pass the domain and username of the user. Then you must pass the display name of the security principal. Finally, you can optionally pass a Boolean that specifies whether the entity is inherited.

AddEntity

Copies the Entity object you pass into the Entities collection for the DACL object.

AddSecurityEntity

The same as the AddEmptySecurityEntity except that before the optional Boolean inherited parameter, there is a required masks parameter, which is an array of hexadecimal numbers you pass to specify the access mask for the new entity.

AddSimpleSecurityEntity

Adds a new entity to the DACL object without requiring the SIDType , SID , and display name. You will most commonly use this method to add new entities. You must pass the domain\username of the security principal and access mask as parameters to this method.

ClearByTemplate

Removes a specific access mask from a specific entity in the DACL object. You must pass the entity name to match as domain\username . You must then pass a DACL object to use as a template. Finally, you must pass the name of the entity in the DACL template to search for.

CopyUserMasks

Copies the access masks of one entity to another in the DACL object. You must pass the domain\username of the security principal or a predefined role such as "Author" as the source whose masks are copied. Then you must pass the domain\username or predefined role as the target where the masks are to be copied .

CreateSecurityDACL

Creates a DACL object from an item's XML security descriptor. This is the first method you call when you work with the security module. You can pass SECURITY_ON_SERVER or SECURITY_ON_CLIENT to this method. Server security is enabled by default.

GetAllByEqualMask , GetAllByMask , GetAllBySIDType

These methods are similar. You must pass access masks for the first two methods, and you must pass a SID type for the third method. These methods return an array of index values for all entities that match your specified parameters.

GetEntityByIndex

Returns an Entity object by the index you specify, which must be an integer. Note that the Entities collection is zero-based .

Load

Creates a DACL object from an item. You must pass the URL to the item as a parameter. You can also optionally pass the username and password as parameters to access the item. If you do not pass a username or password, the application will use the credentials of the currently logged on user to attempt to access the item.

MakeEqualToTemplate

Sets the masks in an entity in a DACL object to be equal to the masks in the specified entity. You must pass a string that specifies the entity in the original DACL object. Then you must pass another DACL object to use as a template. Finally, you must pass a string that is the name of the entity in the DACL template to find, retrieve its access mask, and copy that access mask to the specified entity in the first parameter.

ModifyByTemplate

Performs an action you specify on the masks in a DACL object that match any of the masks you specify in a template DACL object. You must specify the name of the entity to match in the DACL template, the DACL template itself, and the string name of the entity to find in the DACL template. Finally, you must pass the action, such as Make , Set , or Clear . Make sets the masks of the specified DACL to the masks of the template DACL. Set does a bitwise OR of the masks. Clear deletes the masks.

RemoveByDisplayName , RemoveByIndex , RemoveByNT4Name , RemoveBySID

Each of these methods removes an Entity object from a DACL based on the parameter you pass. The last words of the method indicate what the parameter should be. For example, for RemoveByDisplayName , you must pass the display name of the entity to remove.

RemoveInheritedEntities

This method takes no parameters and removes the inherited entities from the DACL's Entities collection.

Save

Saves the DACL. You can optionally pass a username and a password as parameters to this method.

SaveTo

Saves the DACL to the item specified by the URL you pass as a string to this method.

SearchForIndexByDisplayName , SearchForIndexByMask , SearchForIndexByNT4Name , SearchForIndexBySID , SearchForIndexBySIDType

Each of these methods searches for and returns an index of an entity based on the last words in its name. You must pass a different parameter depending on the search criteria for each different method. For example, the SearchForIndexByDisplayName method takes a display name and returns the index of the entity, if any, that matches that display name in the DACL's Entities collection.

SearchForObjectByDisplayName , SearchForObjectByMask , SearchForObjectByNT4Name , SearchForObjectBySID , SearchForObjectBySIDType

Each of these methods returns the Entity object that matches the criteria specified by the last words in the method name. For example, SearchForObjectByDisplayName takes the display name of the entity to search for; if it finds the entity, the method returns the Entity object that matches that display name.

SetProtected

A Boolean method. A value of True means the application will prevent DACLs from inheriting ACEs. The method makes copies of all inherited ACEs. If you need to make changes to inherited principals, you must use this method to copy them first to break the inheritance because the module cannot modify inherited permissions. You can then explicitly set your permissions on that principal.

SetByTemplate

Sets the masks of the DACL object from a template. You must specify the domain\username of a security principal. Then you must specify the DACL object to use as a template. Finally, you must specify the name of the entity to find in the template DACL object to apply to the original DACL.

Table 17-15 lists the properties of the DACL object.

Table 17-15: Properties of the DACL Object

Property

Description

Count

Returns the number of entities in the DACL.

Entities

Returns an array of Entity objects that the DACL object contains.

IsFolder

A Boolean that returns True if the DACL points to an item that is a folder and False if the DACL points to an item that is really an item and not a collection.

IsProtected

A Boolean that returns True if the DACL object does not inherit any ACEs from its parent.

Loc

Specifies the location where the DACL object was created. This can be client ( 1 ) or server ( ).

URL

Specifies the URL to the item from which the DACL object was instantiated .

Access Mask Templates

The security module includes access mask templates that make it easier to set permissions or find users or groups that match these templates. The four key templates are DACLLegacyRoles , DACLLegacyMetaRights , DACLWebStorageItem , and DACLWebStorageFolder . DACLLegacyRoles specifies the access masks for MAPI-based roles, such as "Owner", "Publishing Editor", or "Reviewer". Instead of you having to figure out the specific bitmask to pass to set permissions for a user as "Owner", you can just use the DACLLegacyRoles template. We'll look at how to do this later in the following section.

The DACLLegacyMetaRights template specifies the MAPI permissions that make up the legacy roles. This template includes access masks for such permissions as Create Items, Read Items, Folder Owner, Edit All, Edit Own, Edit None, and the other permissions you see in the Permission property page for folders in Outlook.

The DACLWebStorageItem and DACLWebStorageFolder templates contain the access masks for working with Exchange items and folders. These access masks are used when you work with non-MAPI folders or items contained in non-MAPI folders.

To give you a better idea of what these access mask templates look like, here's some code from the security module that creates these access mask templates. These templates can simplify your coding tremendously, as you'll soon see.

 function DaclLegacyRoles() {     // This section initializes the legacy roles (aka MapiRoles)     // Note that the SIDs are empty as they are irrelevant for this object     var daclLegacyRoles = CreateSecurityDACL();          daclLegacyRoles.URL =         "Legacy roles, from the MAPI security dialog in Exchange 5.5";     daclLegacyRoles.AddSimpleSecurityEntity("None",         [0x1208a9, 0xdc916, 0x1208a9, 0xdc916, 0x0, 0x1f0fbf]);     daclLegacyRoles.AddSimpleSecurityEntity("Owner",         [0x1fc9bf, 0x0, 0x1fc9bf, 0x0, 0x1f0fbf, 0x0]);     daclLegacyRoles.AddSimpleSecurityEntity("Publishing Editor",         [0x1208af, 0xdc910, 0x1208af, 0xdc910, 0x1f0fbf, 0x0]);     daclLegacyRoles.AddSimpleSecurityEntity("Editor",         [0x1208ab, 0xdc914, 0x1208ab, 0xdc914, 0x1f0fbf, 0x0]);     daclLegacyRoles.AddSimpleSecurityEntity("Publishing Author",         [0x1208af, 0xdc910, 0x1208af, 0xdc910, 0x120ea9, 0x1f0716]);     daclLegacyRoles.AddSimpleSecurityEntity("Author",         [0x1208ab, 0xdc914, 0x1208ab, 0xdc914, 0x120ea9, 0x1f0716]);     daclLegacyRoles.AddSimpleSecurityEntity("Non-Editing Author",         [0x1208ab, 0xdc914, 0x1208ab, 0xdc914, 0x120ca9, 0x1f0716]);     daclLegacyRoles.AddSimpleSecurityEntity("Reviewer",         [0x1208a9, 0xdc916, 0x1208a9, 0xdc916, 0x1208a9, 0x1f0716]);     daclLegacyRoles.AddSimpleSecurityEntity("Contributor",         [0x1208ab, 0xdc914, 0x1208ab, 0xdc914, 0x0, 0x1f0fbf]);          daclLegacyRoles.MakeDaclReadOnly();     return daclLegacyRoles; } 

Programming Tasks

Now that you've seen all the objects with their properties and methods, let's step through some common programming scenarios that use the methods and properties from the security module.

Instantiating the Security Module

The first thing you typically need to do is instantiate the model itself. If you do not want to use the sample application included with the SDK that shows permissions for a particular folder or item using an interface similar to Outlook and instead want to add the security module functions to an existing Web application using your own interface, you must copy the files LoadSaveDACL.js and Security.js to your Web application ” assuming , of course, that you want server-side security. If you want client-side security, your best bet is to copy over most of the files from the security folder in the SDK because you will need to detect the browser type coming in ”client-side security is supported only in Internet Explorer. Netscape and other non-Microsoft browsers must use server-side security.

The next step after getting the files into your application is to add code to your Web page to use the security module. You must include the two JavaScript files in your Web page. Use the following ASP code to do this:

 <%@ Language=javascript%> <script language="javascript" runat=server src="loadsavedacl.js"></script> <script language="javascript" runat=server src="security.js"></script> 

Specifying Where the Security Code Should Run

The next task after adding the JavaScript files is to create a DACL. When you create a DACL, you must specify where the security code should run ”the server or the client. You use the CreateSecurityDACL method we spoke about earlier to do this. The following code shows how to create the DACL on both the server and the client:

 var objDacl = CreateSecurityDACL(SECURITY_ON_SERVER()); var objDacl = CreateSecurityDACL(SECURITY_ON_CLIENT()); 

The next step is to open the item you want to get or set security on. This item can be a folder or an item in Exchange. You use the Load method to do this, and you pass the URL (based on either http:// or file:// ) to this method. The following code shows an example of using the Load method:

 // Load the security descriptor in dacl object. var objLoadResult = objDacl.Load(itemURL); if(objLoadResult.number != 0) {     bError=true;     return(false); } 

Listing User Permissions

Now that you've seen how to instantiate and load a DACL, we can start doing interesting things with that DACL. The first thing you will want to do is list user permissions. This is easy to do using the security module methods. The following code retrieves the entities for the DACL using the Entities property on the DACL object, which returns the Entities collection. Then the code loops through all the entities and prints out their properties. Figure 17-21 shows the results from the following code:

click to expand
Figure 17-21: Results showing the permissions for an item
 function ListPermissions(itemURL) {     var objDacl = CreateSecurityDACL(SECURITY_ON_SERVER());     var objResult;          // Load the security descriptor in dacl object.     var objLoadResult = objDacl.Load(itemURL);     if(objLoadResult.number != 0)     {         bError=true;         return(false);     }          //Show the information about the DACL     Response.Write("Below is the information about the DACL:<BR>");     Response.Write("<TABLE>");     Response.Write("<TR><TD>URL:</TD><TD>" + objDacl.URL + "</TD></TR>");     Response.Write("<TR><TD>IsProtected:</TD><TD>"                   + objDacl.IsProtected() + "</TD></TR>");     Response.Write("<TR><TD>Number of Entities:</TD><TD>"                   + objDacl.Count + "</TD></TR>");     Response.Write("</TABLE>");          Response.Write("<BR>");     Response.Write("Entities for the folder:<BR>");     Response.Write("<TABLE>");          //Retrieve all the entities for the DACL     var objEntities = objDacl.Entities     for (i=0;i<objDacl.Count;i++)     {         Response.Write("<TR><TD><B>Entity #" + i + "</B></TD></TR>");         Response.Write("<TR><TD>Name:</TD><TD>"                       + objEntities[i].DisplayName + "</TD></TR>");         Response.Write("<TR><TD>Inherited:</TD><TD>"                       + objEntities[i].Inherited + "</TD></TR>");         Response.Write("<TR><TD>Masks:</TD><TD>"                       + objEntities[i].Masks + "</TD></TR>");         Response.Write("<TR><TD>NT4 Name:</TD><TD>"                       + objEntities[i].NT4Name + "</TD></TR>");         Response.Write("<TR><TD>SID:</TD><TD>"                       + objEntities[i].SID + "</TD></TR>");         Response.Write("<TR><TD>SID Type:</TD><TD>"                       + objEntities[i].SIDType + "</TD></TR>");              Response.Write("<TR><TD>&nbsp;</TD></TR>");     } } 

Setting and Changing Permissions for a User or Group

The next thing you might want to do with the security module is to set or change permissions ”such as adding a new user or group to the folder or changing permissions for existing users or groups. The easiest way to add new users or groups is to use the AddSimpleSecurityEntity method and pass the access mask that you want the new security principal to have. Remember that folders and items have different types of security you can set. For this reason, the sample code you will see checks to see if you are trying to modify permissions for a folder or item.

Changing permissions is relatively easy. You can just use the access mask templates included with the security module. You can use the SetByTemplate method to find the appropriate access mask and then modify the user's existing access mask to be the new access mask.

However, before you do any of this, you must do a couple of things so you do not run into problems. First and foremost ”and I cannot stress this enough ”you must make sure the Web application requires authentication before you attempt to use the security module. If you allow anonymous access to your Web application, you will get an access denied error when you try to save your DACL because the module uses the current security credentials of the logged on Web user. With anonymous access enabled, this is the IIS anonymous account, which has no permissions to even see Exchange data, let alone modify security permissions. Remove anonymous access.

Second, you must check that the security principal does not already exist. You can do this by using one of the SearchForObjectByXXXX methods, where XXXX can be the Windows NT 4.0 name, the SID, or the display name. If the Entity object already exists for the user, just modify it rather than creating a new one.

Third, be sure to escape any names that contain slashes (\). For example, when you pass the Windows NT 4.0 name of a user using domain\username, you must pass it as domain\\username because JavaScript will interpret the backslash in domain\username as \u .

The following code shows how to add and change existing permissions on an item or a folder:

 function AddNewPermissions(NT4User, itemURL) {     var objDacl = CreateSecurityDACL(SECURITY_ON_SERVER());     var objResult;          // Load the security descriptor in dacl object.     var objLoadResult = objDacl.Load(itemURL);     if(objLoadResult.number != 0)     {         bError=true;         return(false);     }          //Search for the user to make sure     //they are not already in the Entities collection     var entityUser = objDacl.SearchForObjectByNT4Name(NT4User);     if (!entityUser)     {         bNotFound=true;         //Add new permissions         //You can add new permissions using the built-in MASKS         //or by creating your own mask         //We will create our own mask here         //Check whether it's a folder or not.         //Permissions will be different for the two.         if (objDacl.isFolder)         {             //It is a folder, load the right Access Mask Template for a folder             var daclWSFolderTemplate = DaclWebStorageFolder();             //Create and add a new entity for the user             //Set create container (create subfolder) for the user             var objResult = objDacl.AddSimpleSecurityEntity(NT4User,                 [0x0004, 0x0004, 0x0004, 0x0004, 0x0000, 0x0000]);             if (objResult.number!=0)             {                 Response.Write("Error adding user!");                 bError=true;                 return(false);             }         }         else         {             //It is an item, load the Access Mask Template for an item             var daclWSItemTemplate = DaclWebStorageItem();             //Add permissions to allow the user to Delete items             var objResult = objDacl.AddSimpleSecurityEntity(NT4User,                 [0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000]);             if (objResult.number!=0)             {                 Response.Write("Error adding user!");                 bError=true;                 return(false);             }         }     }     else     {         //User already exists, just change permissions         Response.Write("User already exists!");         if (objDacl.isFolder)         {             //It is a folder, load the right Access Mask Template for a folder             var daclWSFolderTemplate = DaclWebStorageFolder();             //Change the user's permissions             //Set create container (create subfolder) for the user             var objResult = entityUser.SetByTemplate(daclWSFolderTemplate,                                                    "Folder Create container");             if (objResult.number!=0)             {                 Response.Write("Error modifying permissions user!");                 bError=true;                 return(false);             }         }         else         {             //It is an item, load the Access Mask Template for an item             var daclWSItemTemplate = DaclWebStorageItem();             //Add permissions to allow the user to Delete items             var objResult = entityUser.SetByTemplate(daclWSFolderTemplate,                                                      "Delete");             if (objResult.number!=0)             {                 Response.Write("Error adding user!");                 bError=true;                 return(false);             }         }     }          //Try to save the changes     //Save the DACL on the item     objResult = objDacl.Save();     if(objResult.number != 0)     {         Response.Write("<b>Failed to Save DACL: "                       + objResult.description + "</b><br>");        return(objResult.number);     } } 

Deleting Permissions

You might want to remove permissions for a user. To do this, you can use the Remove methods on the DACL object, such as RemoveByNT4Name or RemoveByDisplayName . The following sample deletes a user's permissions from an item.

 function DeletePermissions(NT4User, itemURL) {     var objDacl = CreateSecurityDACL(SECURITY_ON_SERVER());     var objResult;          // Load the security descriptor in dacl object.     var objLoadResult = objDacl.Load(itemURL);     if(objLoadResult.number != 0)     {         bError=true;         return(false);     }          //Try to delete the user     var objResult = objDacl.RemoveByNT4Name(NT4User);     if (objResult.number != 0)     {         Response.Write("<b>Failed to RemoveByDisplayName: " + objResult.number                       + " " + objResult.description + "</b><br>");         return(objResult.number);      }          //Save the DACL on the item     objResult = objDacl.Save();     if (objResult.number != 0)     {         Response.Write("<b>Failed to Save DACL: " +objResult.number + " "                       + objResult.description + "</b><br>");         return(objResult.number);     } } 

Setting MAPI Permissions

One thing you might want to do in your folders is set the permissions using MAPI role names, such as "Editor", "Author", or "Reviewer". Setting permissions using these MAPI roles is supported in any type of Exchange folder. The security module will perform the right translations between MAPI folders and non-MAPI folders. The following code sets permissions on a folder to allow Everyone to be an "Editor".

 var o; //Notice how Everyone is \Everyone o = setMAPIPermissions("\Everyone", strURL, "Editor");      function setMAPIPermissions(NT4User, itemURL, MAPIRole) {     var objDacl = CreateSecurityDACL(SECURITY_ON_SERVER());     var objResult;          // Load the security descriptor in dacl object.     var objLoadResult = objDacl.Load(itemURL);     if(objLoadResult.number != 0)     {         bError=true;         return(false);     }          // Get the legacy DACL template     var objDLR = DaclLegacyRoles();          //get user entity from the first URL     var entityUser = objDacl.SearchForObjectByNT4Name(NT4User);     if (!entityUser)     {         bError=true;         return(false);     }          var objResult = entityUser.SetByTemplate(objDLR, MAPIRole);     if (objResult.number != 0)     {         bError=true;         return(false);     }          objResult = objDacl.Save();     if (objResult.number != 0)     {         bError=true;         return(false);     } } 

Removing Inherited ACLs

You might also want to modify an inherited ACL. The security module cannot do this, so you must break the inheritance of the ACL and then set your permission explicitly on the new noninherited entity. For example, if you try to run the MAPI permissions code shown earlier on the Everyone group, this is usually an inherited entity. You must first use the SetProtected method and pass True to it. SetProtected will copy all inherited entities and disable inheritance. Then you can set the ACLs on the formerly inherited entities.

Finding Entities

You've seen how to find entities in the previous samples, but it is important to know that you can find entities using multiple types of searches. For example, you can use the SearchForIndexByXXXX method, where XXXX can be the display name, the Windows NT 4.0 name, or another parameter. This method returns the index of the entity in the Entities collection if the entity exists. You can also use the SearchForObjectByXXXX method, where XXXX can also be the display name, the Windows NT 4.0 name, or another parameter. This method returns the Entity object if it is found in the Entities collection.

Using the Security Module from Visual Basic

You can use the security module from a Visual Basic application. The Training sample application does this in its setup program. Certain folders need certain permissions set for course instructors, so the Training setup program uses the security module to set permissions on these folders from its Visual Basic setup program. Admittedly, the security module is not the easiest tool to use from anything other than Web pages. However, the Visual Basic setup program embeds an Internet Explorer browser control into a Visual Basic form to call a Web page that in turn calls the security module. It is very roundabout. However, this is easier than trying to figure out all the idiosyncrasies involved with setting permissions in MAPI folders or non-MAPI folders, with all the ACL formatting and error checking involved.

If you want to mimic what the setup program does, I recommend that you look at both the security Visual Basic form that I created and the Sec.asp file. You'll find a good snippet of code in the form that shows the folder trees for Exchange in the setup program to show how you can find the default Web site for a server, copy a Web file to that Web site, and then call that file. This saves you from having to create a virtual directory in IIS, copy your file there, call your ASP page, delete the ASP file, and delete the virtual directory. Use this technique only if you do not have an existing virtual directory and you do not want to code to create a new virtual directory just to run your security ASP file.




Programming Microsoft Outlook and Microsoft Exchange 2003
Programming MicrosoftВ® OutlookВ® and Microsoft Exchange 2003, Third Edition (Pro-Developer)
ISBN: 0735614644
EAN: 2147483647
Year: 2003
Pages: 227
Authors: Thomas Rizzo

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net