HOWTO: Implement IObjectSafety in Visual Basic Controls
ID: Q182598
|
The information in this article applies to:
-
Microsoft Visual Basic Control Creation, Professional, and Enterprise Editions for Windows, version 5.0
SUMMARY
This article shows you how to implement the IObjectSafety interface in
Visual Basic controls to mark the controls safe for scripting and
initialization. By default, Visual Basic controls use component category
entries in the registry to mark the control safe for scripting and
initialization. Implementing the IObjectSafety interface is the preferred
method. This article contains all the code required to implement this
interface in Visual Basic controls.
Please keep in mind that a control should only be marked as safe if it is,
in fact, safe. This article does not describe the details of marking
controls as safe for scripting and initialization, it simply shows you how
to do it in code. Please refer to the Internet Client SDK documentation for
a detailed description of this. See "Safe Initialization and Scripting for
ActiveX Controls" under the Component Development Section.
MORE INFORMATIONWARNING: One or more of the following functions are discussed in this article; VarPtr, VarPtrArray, VarPtrStringArray, StrPtr, ObjPtr. These functions are not supported by Microsoft Technical Support. They are not documented in the Visual Basic documentation and are provided in this Knowledge Base article "as is." Microsoft does not guarantee that they will be available in future releases of Visual Basic.
In this article you will create a simple Visual Basic control and mark it
safe for scripting and initialization.
- Copy the following text in Notepad and save the file as OBJSAFE.ODL:
[
uuid(C67830E0-D11D-11cf-BD80-00AA00575603),
helpstring("VB IObjectSafety Interface"),
version(1.0)
]
library IObjectSafetyTLB
{
importlib("stdole2.tlb");
[
uuid(CB5BDC81-93C1-11cf-8F20-00805F2CD064),
helpstring("IObjectSafety Interface"),
odl
]
interface IObjectSafety:IUnknown {
[helpstring("GetInterfaceSafetyOptions")]
HRESULT GetInterfaceSafetyOptions(
[in] long riid,
[in] long *pdwSupportedOptions,
[in] long *pdwEnabledOptions);
[helpstring("SetInterfaceSafetyOptions")]
HRESULT SetInterfaceSafetyOptions(
[in] long riid,
[in] long dwOptionsSetMask,
[in] long dwEnabledOptions);
}
}
- From a command prompt, type the following command to generate a TLB
file:
MKTYPLIB objsafe.odl /tlb objsafe.tlb
- From Visual Basic, create an ActiveX Control project. In the Properties
box, change the name of the project to IObjSafety and the name of the
control to DemoCtl. Put a CommandButton named cmdTest on the control.
In the Click event handler of the cmdTest, put a MsgBox "Test"
statement.
- From your Visual Basic Project References, browse to and add the
objsafe.tlb file created in step 2.
- Add a new module to your project with the following code and name the
module basSafeCtl:
Option Explicit
Public Const IID_IDispatch = "{00020400-0000-0000-C000-000000000046}"
Public Const IID_IPersistStorage = _
"{0000010A-0000-0000-C000-000000000046}"
Public Const IID_IPersistStream = _
"{00000109-0000-0000-C000-000000000046}"
Public Const IID_IPersistPropertyBag = _
"{37D84F60-42CB-11CE-8135-00AA004BB851}"
Public Const INTERFACESAFE_FOR_UNTRUSTED_CALLER = &H1
Public Const INTERFACESAFE_FOR_UNTRUSTED_DATA = &H2
Public Const E_NOINTERFACE = &H80004002
Public Const E_FAIL = &H80004005
Public Const MAX_GUIDLEN = 40
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(pDest As Any, pSource As Any, ByVal ByteLen As Long)
Public Declare Function StringFromGUID2 Lib "ole32.dll" (rguid As _
Any, ByVal lpstrClsId As Long, ByVal cbMax As Integer) As Long
Public Type udtGUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(7) As Byte
End Type
Public m_fSafeForScripting As Boolean
Public m_fSafeForInitializing As Boolean
Sub Main()
m_fSafeForScripting = True
m_fSafeForInitializing = True
End Sub
- From Project Properties, change the Startup Object to "Sub Main" in
order to execute the Sub Main above. This is where you will specify the
values of safe for scripting and/or initialization variables using the
m_fSafeForScripting and m_fSafeForInitializing variables.
- Open the code window of your control. Add the following line of code to
the Declaration Section (right after Option Explicit or as the first):
Implements IObjectSafety.
- Copy the following two procedures to your controls code:
Private Sub IObjectSafety_GetInterfaceSafetyOptions(ByVal riid As _
Long, pdwSupportedOptions As Long, pdwEnabledOptions As Long)
Dim Rc As Long
Dim rClsId As udtGUID
Dim IID As String
Dim bIID() As Byte
pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER Or _
INTERFACESAFE_FOR_UNTRUSTED_DATA
If (riid <> 0) Then
CopyMemory rClsId, ByVal riid, Len(rClsId)
bIID = String$(MAX_GUIDLEN, 0)
Rc = StringFromGUID2(rClsId, VarPtr(bIID(0)), MAX_GUIDLEN)
Rc = InStr(1, bIID, vbNullChar) - 1
IID = Left$(UCase(bIID), Rc)
Select Case IID
Case IID_IDispatch
pdwEnabledOptions = IIf(m_fSafeForScripting, _
INTERFACESAFE_FOR_UNTRUSTED_CALLER, 0)
Exit Sub
Case IID_IPersistStorage, IID_IPersistStream, _
IID_IPersistPropertyBag
pdwEnabledOptions = IIf(m_fSafeForInitializing, _
INTERFACESAFE_FOR_UNTRUSTED_DATA, 0)
Exit Sub
Case Else
Err.Raise E_NOINTERFACE
Exit Sub
End Select
End If
End Sub
Private Sub IObjectSafety_SetInterfaceSafetyOptions(ByVal riid As _
Long, ByVal dwOptionsSetMask As Long, ByVal dwEnabledOptions As Long)
Dim Rc As Long
Dim rClsId As udtGUID
Dim IID As String
Dim bIID() As Byte
If (riid <> 0) Then
CopyMemory rClsId, ByVal riid, Len(rClsId)
bIID = String$(MAX_GUIDLEN, 0)
Rc = StringFromGUID2(rClsId, VarPtr(bIID(0)), MAX_GUIDLEN)
Rc = InStr(1, bIID, vbNullChar) - 1
IID = Left$(UCase(bIID), Rc)
Select Case IID
Case IID_IDispatch
If ((dwEnabledOptions And dwOptionsSetMask) <> _
INTERFACESAFE_FOR_UNTRUSTED_CALLER) Then
Err.Raise E_FAIL
Exit Sub
Else
If Not m_fSafeForScripting Then
Err.Raise E_FAIL
End If
Exit Sub
End If
Case IID_IPersistStorage, IID_IPersistStream, _
IID_IPersistPropertyBag
If ((dwEnabledOptions And dwOptionsSetMask) <> _
INTERFACESAFE_FOR_UNTRUSTED_DATA) Then
Err.Raise E_FAIL
Exit Sub
Else
If Not m_fSafeForInitializing Then
Err.Raise E_FAIL
End If
Exit Sub
End If
Case Else
Err.Raise E_NOINTERFACE
Exit Sub
End Select
End If
End Sub
- Save your project and files. Make an OCX from your project. Your control
now implements the IObjectSafety interface. You can test it be inserting
the control in an HTM file.
REFERENCES
Internet Client SDK - Component Development - Safe Initialization and
Scripting for ActiveX Controls
For additional information, please see the following article in the
Microsoft Knowledge Base:
Q161873 HOWTO: Mark MFC Controls Safe for Scripting/Initialization
Additional query words:
safety scripting persistence initialization
Keywords : kbActiveX kbVBp500 kbDSupport kbhowto AXSDKControls InetSDKSafeControl kbIEFAQ
Version : WINDOWS:5.0
Platform : WINDOWS
Issue type : kbhowto
|