DAX FAQs 1.0

by Conrad Herrmann
4 June 97
Q: How do I mark a control as "safe for scripting"/"safe for initializing"? What does that mean?

A: The terms "safe for scripting" and "safe for initializing" represent a second level of security, called Object Safety, which goes beyond the basic code signature. When you sign your code using Authenticode, you're certifying, among other things, that your code is not specifically designed to be harmful, and that the object can be downloaded and instantiated safely.

When you download a control in an HTML page, it's possible for the page to contain property values for your control. It's also possible for the HTML page to contain JavaScript or VBScript, which will set properties on the control or call its methods. If you've defined methods or properties of your control that could potentially be (mis)used to cause damage to a client computer, you need to make sure to protect the client's computer from the hazard.

A control marked "safe for scripting" means the object can be automated safely via OLE automation, regardless of the script that is used to automate the object. A control marked "safe for initializing" means that the object's properties or data can safely be restored from any persistent store.

These concepts are further defined in Microsoft's ActiveSDK web site, at http://www.microsoft.com/intdev/inetsdk/docs/inet1273.htm and http://www.microsoft.com/intdev/inetsdk/docs/inet1274.htm


How do I make my control safe for scripting/initializing? There are two ways to do this. The first is useful when your control is *always* safe for initializing and scripting, the second is useful when your control might be unsafe but can be switched into a safe mode.

Method 1:

Install the appropriate registry keys for your control. You can do this by replacing the factory creation code (at the bottom of your control's implementation unit) with a call that creates a special factory with the object safety registry entries. Basically this means replacing the code that says "TActiveXControlFactory.Create" with "TSafeActiveXControlFactory.Create", and USEing the following unit.

unit SafeFactory;
interface
uses ComObj, ActiveX, AXCtrls;

const
  CATID_SafeForScripting: TGUID = '{7DD95801-9882-11CF-9FA9-00AA006C42C4}';
  CATID_SafeForInitializing: TGUID =
'{7DD95802-9882-11CF-9FA9-00AA006C42C4}';

type
  TSafeActiveFormFactory = class( TActiveFormFactory )
    procedure UpdateRegistry( Register: Boolean ); override;
  end;

  TSafeActiveXControlFactory = class( TActiveXControlFactory )
    procedure UpdateRegistry( Register: Boolean ); override;
  end;

implementation

procedure AddSafetyKeys( const ClassID: TGUID );
var
  ClassKey: string;
begin  
  ClassKey := 'CLSID\' + GUIDToString( ClassID );
  CreateRegKey( ClassKey + '\Implemented Categories','','');
  CreateRegKey( ClassKey + '\Implemented Categories\'+GUIDToString(
     CATID_SafeForScripting ),'','');
  CreateRegKey( ClassKey + '\Implemented Categories\'+GUIDToString(
     CATID_SafeForInitializing ),'','');
end;

procedure RemoveSafetyKeys( const ClassID: TGUID );
var
  ClassKey: string;
begin      
  ClassKey := 'CLSID\' + GUIDToString( ClassID );
  DeleteRegKey( ClassKey + '\Implemented Categories\'+GUIDToString(
      CATID_SafeForInitializing ));
  DeleteRegKey( ClassKey + '\Implemented Categories\'+GUIDToString(
      CATID_SafeForScripting ));
  DeleteRegKey( ClassKey + '\Implemented Categories');
end;
      
{TSafeActiveFormFactory}
procedure TSafeActiveFormFactory.UpdateRegistry( Register: Boolean );
begin
  if Register then
  begin
    AddSafetyKeys( ClassID );
    inherited UpdateRegistry( Register );
  end
  else
  begin
    RemoveSafetyKeys( ClassID );
    inherited UpdateRegistry( Register );
  end;
end;

{TSafeActiveXControlFactory}
procedure TSafeActiveXControlFactory.UpdateRegistry( Register: Boolean );
begin
  if Register then
  begin
    AddSafetyKeys( ClassID );
    inherited UpdateRegistry( Register );
  end
  else
  begin
    RemoveSafetyKeys( ClassID );
    inherited UpdateRegistry( Register );
  end;
end;

end.

Method 2:

Implement the IObjectSafety interface on your control. The IObjectSafety interface is documented by Microsoft in the MSDN from January 1997 or later, or in the ActiveX SDK. This documentation is available from Microsoft's web site at http://premium.microsoft.com/msdn/library/sdkdoc/inetcsdk_36wh.htm

Implementing the IObjectSafety interface allows your control to expose unsafe methods or properties when running in a container that doesn't require safety. In a container that requires safety, like Internet Explorer, the container will use IObjectSafety to ask your control to switch into safe mode, and to disable all unsafe methods and properties.