рефераты конспекты курсовые дипломные лекции шпоры

Реферат Курсовая Конспект

ObjectData

ObjectData - раздел Образование, ABSTRACT     The Projectdata Structure Is...

 

 

The ProjectData structure is custom to each class and must be defined by the project for each class. There are no limits on the size or makeup of this structure. Since both this data structure and the methods are created together in a project, it is simple to allocate any private data required.

 

The ProjectData structure is a runtime creation, thus you will never need to create a .data structure of type ProjectData. The structure definition is quite useful for defining and accessing the private data when writing the custom method code. The size of this structure (m_ObjectSize) is used in the ClassItem.

 

The ObjectEntry structure is used to either direct a method call to the implementation table, or to cast this_ to the base address of the object itself.

 

ObjectEntry STRUCT

m_pVtbl DWORD ; interface object

m_pBase DWORD ; pointer to base

ObjectEntry ENDS

 

When CoLib creates an object, it included(N+1) ObjectEntrystructures to support N interfaces. The extra ObjectEntry is needed to support the two IUnknown interfaces for aggregation (see the discussion following on aggregation).

 

Note that the ProjectObject structure itself is only instanced at runtime, no instance of the project object structure is made. Nor is there any ProjectObject structure defined anywhere. It is just a convenient fiction, used only to see how the of memory is organized at runtime.

OBJECT CONSTRUCTION AND DESTRUCTON

 

To allow for custom object creation and destruction, you may define functions to handle these events. This is a convent way to allocate and deallocate resources.

 

These functions should be written to the following prototypes:

 

ConstructorProto PROC this_:DWORD, pCustomData:DWORD

 

DestructorProto PROC this_:DWORD

 

The Constructor proto includes a pointer to a data structure you may customize for this class. This pointer is included in the AllocObject method. When called from DllGetClassObject, there is no way to customize this pointer, but it may be defined as needs be in a sub-object creation. (This prototype and definition was corrected for CoLib 1.1)

Thus. classes are provided two separate ways to be customized. The constructor accepts a reference to custom data, and there is also a undefined data pointer in the ClassItem itself. Alternate methods of customization are provided since a class may be instanced in two ways, and may be useful with a general prototype class, one that just requires a little extra bit of custom information. An enumeration interface is one example of this.

 

 

CASTING AN OBJECT FOR AN INTERFACE

 

To "cast" an object in assembler does need some explanation. The term "cast" is borrowed from C++, where it does make some concrete sense, but here in the assembly end, the concepts of class and object are a bit fuzzier.

 

The COM interface contract allows an object to support multiple interfaces. This interface has a well-defined binary structure that we can easily duplicate in assembly, but this opens the question of interface casting.

 

A much better explanation of this may be found on page 44 of "Inside COM," "Multiple Inheritance and Casting."

 

Let us look at the interface for an imaginary object. An interface is a table of pointers to functions. Say Object this imaginary object contains Interfaces IX and IY. As this is a COM object, both IX and IY inherit from IUnknown. Let us give both IX and IY a single method each, IX.Foo and IY.Bar. Also remember that this_ holds a reference to a pointer to the virtual table of functions. The binary layout of this interface would look like so:

 

CLIENT   OBJECT   OBJECT  
COM   INSTANCE   IMPLIMENTATION  
POINTER          
      IX::QueryInterface IX
this_   pvtable1   IX::AddRef  
  pvtable2   IX::Release  
        IX::Foo  
        IY::QueryInterface IY
        IY::AddRef  
        IY::Release  
        IY::Bar  

Figure 2. Interface casting detail (or why this_ is sometimes that_).

 

 

The first thing to notice from this figure is that there are two possible values of this_, one for each interface, and remember, it's not possible to call them "this_" and “that_". One little known property of casting is that the actual numeric value returned from a cast may not be equal to what was cast. This is another way of saying a cast may do more then just adjusting for different data formats.

 

When QueryInterface is invoked to get another interface inside an object, the returned pointer changes. this_ actually changes value. It has to, it must. This is completely normal. The only requirement COM imposes on the returned pointer is that a QueryInterface on two separate interfaces for IUnknown return the same value, so object identity may be determined.

 

This is important to us in the following way: we need a method to pass back this_, a cast interface pointer, cast to any arbitrary interface we support, and at the same time, use this_ to unwind our entire object structure. We need to get to all the information of the object, since all our code initially knows about it's instance is literally this_, and if this_can change it means we cannot simply add an offset tothis_to get to other elements in the object structure.

 

Interface casting is performed like so: In our object, each vtable pointer is kept in a ObjectEntry structure, which has two elements, the vtable pointer immediately followed by the base address of our object. The base address is the starting address of the object, it's the address of the ObjectData structure.

 

Also, the ObjectData structure contains the address of the first ObjectEntry structure.

 

In this way, given this_ we can walk about our object and get to any structure from any this_ cast via code such as follows:

 

SomeInterface_SomeFunct PROC this_:DWORD, param1:DWORD, param2:DWORD

mov ecx, this_

mov eax, [ecx + 4] ; ObjectData pointer in eax

 

 

Simple and direct. In actual use, we cast ecx at an ObjectEntry pointer so we don't have to remember the binary layout. Thus the actual library code to cast this_ to the custom data area is like so:

 

pObjectBase MACRO pObject:REQ, reg:REQ, _offset:VARARG

.code

; cast object to the base ClassItem interface

mov reg, pObject ; get object

mov reg, (ObjectEntry PTR[reg]).m_pBase ; walk to base data

IFNB <_offset>

add reg, _offset

ENDIF

ENDM

 

Once we have these references to the object's internal structures, we can access any and all parts of it.

 

Casting for an interface is performed in only one place: the IUnknown::QueryInterface implementation. Back when the object was first created, the ClassMap was used to get reference to the InterfaceMap. The InterfaceItem held the interface ID iid, and a pointer to that vtable. These pointer values were then copied in order over into our object. When QueryInterface is given an interface to cast, it compares the given iid parameter with this InterfaceMap, looking for a match. If interface iid N matches the parameter, then the object is cast to it by returning the address of ObjectEntryN, thus making this_ point to the requested interface.

 

 

AGGREGATION

 

When an object is aggregated, it uses the IUnknown implementation of the containing object. If not aggregated, it uses it's own code for these functions. Aggregation is a runtime choice, so this change must be done on the fly.

 

CoLib uses the same method as found in "Inside COM," Chapter 8, "Component Reuse: Containment and Aggregation." Briefly, this entails having two separate IUnknown implementations, a delegation and non-delegating IUnknown. The non-delegating version does what we've come to expect from IUnknown, reference count and interface cast. The delegating IUnknown looks for another IUnknown implementation to pass it's work off to.

 

At object creation time, pUnkOuter is checked for NULL. If not NULL, it is stored in the object and used by the delegating IUnknown to do the work. If it is NULL, a reference to the very first ObjectEntry is saved instead. The first ObjectEntry is always automatically assigned to the non-delegating IUnknown.

 

If none of this made sense, you really need not worry, the library does this all for you. If you're still worrying, go check out "Inside COM."

 

 

IMPORTING THE LIBRARY

 

The coserver files need to be added to your masm32 area. For consistency sake, it is recommended that you place the library .inc files in masm32cominclude, and the library itself in masm32comcolib. To use the library, you will first need to include the library itself (and it's own dependencies):

 

 

include masm32includemasm32.inc

include masm32comincludeoaidl.inc

include masm32comincludeCoLib.inc

 

includelib masm32libmasm32.lib

includelib masm32comcolibCoLib.lib

 

The main project, if a dll server, should also export a ClassMapfor each coclass:

 

PUBLIC ClassMap

 

CoLib.Lib depends on the linker to add those components a project requires, making it simple to override CoLib methods if you choose to implement anything differently. The CoLib.inc just defines some of the basic structures, it does not make .code or .data.

 

USING OTHER FEATURES OF THE LIBRARY

 

The following macros of CoLib.inc expand to code (not procedures) (they act as inline functions) and may be used anywhere in your code:

 

pObjectBase pObject, reg, _offsetUsed to cast this_ to the base address of the

object so ObjectData may be accessed.

Rarely used, except inside to the library itself

 

pObject the this_ to cast

 

reg register to place result

 

_offset optional parameter, additional offset to

add to cast

 

pObjectData pObject, reg, _offset Used to cast this_ to the base address of the

custom data structure so the custom data

may be accessed.

 

pObject the this_ to cast

 

reg register to place result

 

_offset optional parameter, additional offset to

add to cast

 

DeclareGuid gName, sIID Used to instance a GUID textequate. Will

assign a GUID textequate to a guid name,

and also define a pointer to this guid.

 

gName Label name for this guid. Will also assign

"p" & "gName" to create a reference

to the guid.

 

sIID optional parameter, used to define the

textequate for the guid if this does not

exist elsewhere.

 

DeclareGuid is handy to reduce typing (and hopefully improve clarity). For example:

 

DeclareGuidIID_IUnknown, sIID_IUnknown

 

will generate the following symbols:

 

IID_Unknown GUID {000000000H, 00000H, 00000H, {0C0H, 000H,

000H, 000H, 000H, 000H, 000H, 046H}}

 

pIID_Unknown OFFSET IID_Unknown

 

The second parameter is optional. If sIID_IUnknown is defined elsewhere and is of the form "s" & "guid name" then the macro will supply the equate. sIID is included for the occasion one needs to define a new guid number.

 

A DeclareVARIANT macro is provided to correctly initialize a VARIANT structure. These can be messy on your own. For example:

 

DeclareVARIANT MyVariant, VT_I4, 10

 

will generate the following symbols:

 

MyVariant VARIANT {VT_I4, , , , {10}}

 

OTHER REQUIRED PROJECT FILES

A project will also require the following files to completely build and define a COM server dll. See example project for samples and further explanation.

 

Interface Definition file .idl Defines the object to produce a type library

 

Type Library .tlb Produced by the .idl file, a black

box of object information

 

registry script .rgs Standard script for dll registration or

unregistration. See "Creating Registrar Scripts" in MSDN for .rgs syntax and usage. The library follows the same format.

 

rcrs.rc .rc Standard masm32 resource file. A starter

template is provided, this should be edited to your own needs as to your particular

typelib and registrar script filenames.

 

Project.def .def DLL export definitions.

 

RELATED FILES

· CoLib.inc structures, constants, and macro functions needed by the CoLib library, include with your server project.
· component.inc perhaps a continual work in progress, defining many constants, structures, and interfaces (54 and counting) for .ocx controls.  
· L.inc macro to define Unicode string constants  
· language.inc Equates and macros to support localization (help to interpret lcid parameters)  
· mini_win.inc Striped to the bone windows.inc file to speed the CoLib.Lib building process  
· oaidl.inc Basic definitions for any ASM COM project  
· olectl.inc Basic definitions for an .ocx project  
· colibl.rc Common resource definitions  

APPENDIX A

EXPORTED LIBRARY METHODS

 

Standard dll Exports

DllMain PROTO :DWORD, :DWORD, :DWORD

DllRegisterServer PROTO

DllUnregisterServer PROTO

DllCanUnloadNow PROTO

DllGetClassObject PROTO :DWORD, :DWORD, :DWORD

 

DllRegister/Unregister Internal Functions

Register PROTO :DWORD

SetSubKey PROTO :DWORD, :DWORD, :DWORD

GetNextToken PROTO

AddReplacements PROTO :DWORD

GuardedDeleteKey PROTO :DWORD, :DWORD

 

Standard Interface Implementations

 

IUnknown Interface Implementations

QueryInterface PROTO :DWORD, :DWORD, :DWORD

AddRef PROTO :DWORD

Release PROTO :DWORD

NDQueryInterface PROTO :DWORD, :DWORD, :DWORD

NDAddRef PROTO :DWORD

NDRelease PROTO :DWORD

IDispatch Interface Implementations

GetTypeInfoCount PROTO :DWORD, :DWORD

GetTypeInfo PROTO :DWORD, :DWORD, :DWORD, :DWORD

GetIDsOfNames PROTO :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD

Invoke_ PROTO :DWORD, :DWORD, :DWORD, :DWORD, :WORD, :DWORD,

:DWORD, :DWORD, :DWORD

 

IDispatch Interface Helper Function

GetCachedTypeInfo PROTO :DWORD, :DWORD, :DWORD

 

Class Factory Interface Implementations

CreateInstance PROTO :DWORD, :DWORD, :DWORD, :DWORD

LockServer PROTO :DWORD, :DWORD

 

Class Factory Internal Functions

AllocObject PROTO :DWORD, :DWORD, :DWORD, :DWORD

DeallocObject PROTO :DWORD

 

External Helper Functions

ComPtrAssign PROTO :DWORD, :DWORD

ComQIPtrAssign PROTO :DWORD, :DWORD, :DWORD

 

APPENDIX B

LIBRARY DATA STRUCTURES

 

ClassItem

ClassItem STRUCT

m_clsidDWORD 0 ; CLSID; GUID of this class

m_FlagsDWORD 0 ; various flags

m_pTypeLibInfo DWORD 0 ; type info map

m_pIMapDWORD 0 ; InterfaceMap for this object

m_pConstructor DWORD 0 ; custom object constructor function

m_pDestructorDWORD 0 ; custom object destructor function

m_pData DWORD 0 ; custom object data reference

m_ObjectSizeDWORD 0 ; byte count of the

; private data structure

ClassItem ENDS

 

 

Contains parameters for the ClassMap array elements to define a class supported by the project dll.

– Конец работы –

Эта тема принадлежит разделу:

ABSTRACT

Copyright by Ernest Murphy ernie surfree com... For educational use only All commercial use only by written license...

Если Вам нужно дополнительный материал на эту тему, или Вы не нашли то, что искали, рекомендуем воспользоваться поиском по нашей базе работ: ObjectData

Что будем делать с полученным материалом:

Если этот материал оказался полезным ля Вас, Вы можете сохранить его на свою страничку в социальных сетях:

Все темы данного раздела:

END_CLASS_MAP
  The END_CLASS_MAP macro is provided to flag the end of the Map list.   Classes also may also be instanced without a call to CoCreateI

END_INTERFACE_MAP
  The END_INTERFACE_MAP macro is provided to flag the end of the Map list.   Each object that may be served from the dll will need its particul

M_Flags
Various flags controlling the object. This member can include zero or a combination of the following values:     AGGREGATABLE Object

M_pBase
reference to base address of this object     TypeLibInfo

END_OF_INTERFACEMAP
A macro to define a NULL InterfaceItem element to signify the end of the InterfaceMap.  

M_DataItemN
This structure, and the data defined are arbitrary, for example only. Each particular class needs to define its own custom data structure in the project file.  

ObjectEntryN
An ObjectEntry structure. Each class needs N+1 ObjectEntry structures in sequence to support N interfaces.  

VarValue
Variable value of the VARIANT being defined.  

PObject
Object reference, the this_ parameter passed to an class method. reg Name of the register to return the cast. _offsetl

PObject
Object reference, the this_ parameter passed to an class method. reg Name of the register to return the cast. _offsetl

ComPtrAssign PROC
pp:DWORD,// reference of variable to receive a pointer lp:DWORD// reference to existing COM pointer Parameters

ComQIPtrAssign PROC
pp:DWORD,// reference of variable to receive a pointer lp:DWORD// reference to existing COM pointer riid

Хотите получать на электронную почту самые свежие новости?
Education Insider Sample
Подпишитесь на Нашу рассылку
Наша политика приватности обеспечивает 100% безопасность и анонимность Ваших E-Mail
Реклама
Соответствующий теме материал
  • Похожее
  • Популярное
  • Облако тегов
  • Здесь
  • Временно
  • Пусто
Теги