summaryrefslogtreecommitdiff
path: root/packages/winunits-base
diff options
context:
space:
mode:
authormarco <marco@3ad0048d-3df7-0310-abae-a5850022a9f2>2009-10-31 22:31:26 +0000
committermarco <marco@3ad0048d-3df7-0310-abae-a5850022a9f2>2009-10-31 22:31:26 +0000
commit6bbb6f0a5a2dd651ab2b323efe15f91cb2d3bea0 (patch)
tree531f11a2b71519029b9920d37798ed1d866d3f27 /packages/winunits-base
parentf406c5f67c076a388baf5a34e7555e3cdfff3ab3 (diff)
downloadfpc-6bbb6f0a5a2dd651ab2b323efe15f91cb2d3bea0.tar.gz
* fixed compilation win32/win64 after (my) last commit.
due to wince <-> win32/win64 headerwise. wince has some identifiers in Windows that win32/win64 has in activex * patches for comobj/comserv from 0014822 and 0014939 as well as one minor fix to activex. git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@13991 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'packages/winunits-base')
-rw-r--r--packages/winunits-base/src/activex.pp5
-rw-r--r--packages/winunits-base/src/comobj.pp441
-rw-r--r--packages/winunits-base/src/comserv.pp88
3 files changed, 489 insertions, 45 deletions
diff --git a/packages/winunits-base/src/activex.pp b/packages/winunits-base/src/activex.pp
index 16d68a797a..2b8161c4fc 100644
--- a/packages/winunits-base/src/activex.pp
+++ b/packages/winunits-base/src/activex.pp
@@ -2846,9 +2846,10 @@ TYPE
Function LocalInvoke ():HResult;StdCall;
{$endif}
{$ifndef Call_as}
- Function GetDocumentation(memid: MEMBERID; OUT pBstrName: WideString; OUT pBstrDocString: WideString; OUT pdwHelpContext: DWORD; OUT pBstrHelpFile: WideString):HResult;StdCall;
+ //Function GetDocumentation(memid: MEMBERID; OUT pBstrName: WideString; OUT pBstrDocString: WideString; OUT pdwHelpContext: DWORD; OUT pBstrHelpFile: WideString):HResult;StdCall;
+ Function GetDocumentation(memid: MEMBERID; pBstrName: PWideString; pBstrDocString: PWideString; pdwHelpContext: PDWORD; pBstrHelpFile: PWideString):HResult;StdCall;
{$else}
- Function GetDocumentation(memid: MEMBERID; refPtrFlags: DWORD; OUT pBstrName: WideString; OUT pBstrDocString: WideString; OUT pdwHelpContext: DWORD; OUT pBstrHelpFile: WideString):HResult;StdCall;
+ Function GetDocumentation(memid: MEMBERID; refPtrFlags: DWORD; OUT pBstrName: WideString; OUT pBstrDocString: WideString; OUT pdwHelpContext: DWORD; OUT pBstrHelpFile: WideString):HResult;StdCall;
{$endif}
{$ifndef Call_as}
diff --git a/packages/winunits-base/src/comobj.pp b/packages/winunits-base/src/comobj.pp
index 4000d29390..0bdd8aa1a9 100644
--- a/packages/winunits-base/src/comobj.pp
+++ b/packages/winunits-base/src/comobj.pp
@@ -18,8 +18,8 @@ unit comobj;
interface
-{$define DEBUG_COM}
-
+{ $define DEBUG_COM}
+{ $define DUMMY_REG}
uses
Windows,Types,Variants,Sysutils,ActiveX,classes;
@@ -136,6 +136,8 @@ unit comobj;
TClassInstancing = (ciInternal, ciSingleInstance, ciMultiInstance);
TThreadingModel = (tmSingle, tmApartment, tmFree, tmBoth, tmNeutral);
+ { TComObjectFactory }
+
TComObjectFactory = class(TObject, IUnknown, IClassFactory, IClassFactory2)
private
FRefCount : Integer;
@@ -144,6 +146,7 @@ unit comobj;
FComClass: TClass;
FClassID: TGUID;
FClassName: string;
+ FClassVersion : String;
FDescription: string;
FErrorIID: TGUID;
FInstancing: TClassInstancing;
@@ -171,12 +174,16 @@ unit comobj;
constructor Create(ComServer: TComServerObject; ComClass: TComClass;
const ClassID: TGUID; const Name, Description: string;
Instancing: TClassInstancing; ThreadingModel: TThreadingModel = tmSingle);
+ constructor Create(ComServer: TComServerObject; ComClass: TComClass;
+ const ClassID: TGUID; const Name, Version, Description: string;
+ Instancing: TClassInstancing; ThreadingModel: TThreadingModel = tmSingle);
destructor Destroy; override;
function CreateComObject(const Controller: IUnknown): TComObject; virtual;
procedure RegisterClassObject;
procedure UpdateRegistry(Register: Boolean); virtual;
property ClassID: TGUID read FClassID;
property ClassName: string read FClassName;
+ property ClassVersion: string read FClassVersion;
property ComClass: TClass read FComClass;
property ComServer: TComServerObject read FComServer;
property Description: string read FDescription;
@@ -210,6 +217,48 @@ unit comobj;
property ClassInfo : ITypeInfo read FClassInfo;
end;
+ { TAutoObject }
+
+ TAutoObject = class(TTypedComObject, IDispatch)
+ protected
+ { IDispatch }
+ function GetTypeInfoCount(out count : longint) : HResult;stdcall;
+ function GetTypeInfo(Index,LocaleID : longint; out TypeInfo): HResult;stdcall;
+ function GetIDsOfNames(const iid: TGUID; names: Pointer; NameCount, LocaleID: LongInt; DispIDs: Pointer) : HResult;stdcall;
+ function Invoke(DispID: LongInt;const iid : TGUID; LocaleID : longint; Flags: Word;var params; VarResult,ExcepInfo,ArgErr : pointer) : HResult;stdcall;
+ public
+
+ end;
+
+ TAutoClass = class of TAutoObject;
+
+ { TAutoObjectFactory }
+ TAutoObjectFactory = class(TTypedComObjectFactory)
+ public
+ constructor Create(AComServer: TComServerObject; AutoClass: TAutoClass; const AClassID: TGUID;
+ AInstancing: TClassInstancing; AThreadingModel: TThreadingModel = tmSingle);
+ end;
+
+ { TAutoIntfObject }
+
+ //example of how to implement IDispatch: http://www.opensource.apple.com/source/vim/vim-34/vim/src/if_ole.cpp
+ TAutoIntfObject = class(TInterfacedObject, IDispatch, ISupportErrorInfo)
+ private
+ fTypeInfo: ITypeInfo;
+ fInterfacePointer: Pointer;
+ protected
+ { IDispatch }
+ function GetTypeInfoCount(out count : longint) : HResult;stdcall;
+ function GetTypeInfo(Index,LocaleID : longint; out TypeInfo): HResult;stdcall;
+ function GetIDsOfNames(const iid: TGUID; names: Pointer; NameCount, LocaleID: LongInt; DispIDs: Pointer) : HResult;stdcall;
+ function Invoke(DispID: LongInt;const iid : TGUID; LocaleID : longint; Flags: Word;var params; VarResult,ExcepInfo,ArgErr : pointer) : HResult;stdcall;
+
+ { ISupportErrorInfo }
+ function InterfaceSupportsErrorInfo(CONST riid: TIID):HResult;StdCall;
+ public
+ function SafeCallException(ExceptObject: TObject; ExceptAddr: Pointer): HResult; override;
+ constructor Create(TypeLib: ITypeLib; const Guid: TGuid);
+ end;
function CreateClassID : ansistring;
@@ -256,7 +305,7 @@ unit comobj;
implementation
uses
- ComConst,Ole2, Registry;
+ ComConst, Ole2, Registry, RtlConsts;
var
Uninitializing : boolean;
@@ -374,7 +423,6 @@ implementation
OleCheck(CoCreateInstance(id,nil,CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER,IDispatch,result));
end;
-
function GetActiveOleObject(const ClassName : string) : IDispatch;
{$ifndef wince}
var
@@ -391,6 +439,79 @@ implementation
end;
{$endif wince}
+ procedure CreateRegKey(const Key, ValueName, Value: string);
+{$ifndef DUMMY_REG}
+ var
+ Reg: TRegistry;
+{$endif}
+ begin
+{$ifdef DEBUG_COM}
+ WriteLn('CreateRegKey: ', Key, ': ', ValueName, ': ', Value );
+{$endif}
+{$ifndef DUMMY_REG}
+ Reg := TRegistry.Create;
+ try
+ Reg.RootKey := HKEY_CLASSES_ROOT;
+ if Reg.OpenKey(Key, True) then
+ begin
+ try
+ Reg.WriteString(ValueName, Value);
+ finally
+ Reg.CloseKey;
+ end;
+ end
+ else
+ raise ERegistryException.CreateResFmt(@SRegCreateFailed, [Key]);
+ finally
+ Reg.Free;
+ end;
+{$endif}
+{$ifdef DEBUG_COM}
+ WriteLn('CreateRegKey exit: ', Key, ': ', ValueName, ': ', Value );
+{$endif}
+ end;
+
+ procedure DeleteRegKey(const Key: string);
+{$ifndef DUMMY_REG}
+ var
+ Reg: TRegistry;
+{$endif}
+ begin
+{$ifdef DEBUG_COM}
+ WriteLn('DeleteRegKey: ', Key);
+{$endif}
+{$ifndef DUMMY_REG}
+ Reg := TRegistry.Create;
+ try
+ Reg.RootKey := HKEY_CLASSES_ROOT;
+ Reg.DeleteKey(Key);
+ finally
+ Reg.Free;
+ end;
+{$endif}
+ end;
+
+ function GetRegStringValue(const Key, ValueName: string): string;
+ var
+ Reg: TRegistry;
+ begin
+ Reg := TRegistry.Create();
+ try
+ Reg.RootKey := HKEY_CLASSES_ROOT;
+ if Reg.OpenKeyReadOnly(Key) then
+ begin
+ try
+ Result := Reg.ReadString(ValueName)
+ finally
+ Reg.CloseKey;
+ end;
+ end
+ else
+ Result := '';
+ finally
+ Reg.Free;
+ end;
+ end;
procedure OleError(Code: HResult);
begin
@@ -685,7 +806,7 @@ implementation
function TComObjectFactory.GetProgID: string;
begin
- RunError(217);
+ Result := FComServer.GetServerName + '.' + FClassName;
end;
@@ -771,6 +892,13 @@ implementation
Description: string; Instancing: TClassInstancing;
ThreadingModel: TThreadingModel);
begin
+ Create(ComServer, ComClass, ClassID, Name, '', Description, Instancing, ThreadingModel);
+ end;
+
+ constructor TComObjectFactory.Create(ComServer: TComServerObject;
+ ComClass: TComClass; const ClassID: TGUID; const Name, Version, Description: string; Instancing: TClassInstancing;
+ ThreadingModel: TThreadingModel);
+ begin
{$ifdef DEBUG_COM}
WriteLn('TComObjectFactory.Create');
{$endif}
@@ -779,6 +907,7 @@ implementation
FThreadingModel := ThreadingModel;
FDescription := Description;
FClassName := Name;
+ FClassVersion := Version;
FComServer := ComServer;
FComClass := ComClass;
FInstancing := Instancing;;
@@ -805,6 +934,9 @@ implementation
procedure TComObjectFactory.RegisterClassObject;
begin
+ {$ifdef DEBUG_COM}
+ WriteLn('TComObjectFactory.RegisterClassObject');
+ {$endif}
RunError(217);
end;
@@ -841,38 +973,69 @@ HKCR
procedure TComObjectFactory.UpdateRegistry(Register: Boolean);
var
reg: TRegistry;
+ classidguid: String;
+
+ function ThreadModelToString(model: TThreadingModel): String;
+ begin
+ case model of
+ tmSingle: Result := '';
+ tmApartment: Result := 'Apartment';
+ tmFree: Result := 'Free';
+ tmBoth: Result := 'Both';
+ tmNeutral: Result := 'Neutral';
+ end;
+ end;
+
begin
- RunError(217);
+{$ifdef DEBUG_COM}
+ WriteLn('UpdateRegistry begin');
+{$endif}
+ if Instancing = ciInternal then Exit;
- //todo: finish this
if Register then
begin
- reg := TRegistry.Create;
- reg.RootKey := HKEY_CLASSES_ROOT;
- reg.OpenKey(FClassName + '.1', True);
- reg.WriteString('', Description);
- reg.WriteString('CLSID', GUIDToString(ClassID));
- reg.CloseKey;
-
- reg.OpenKey(FClassName, True);
- reg.WriteString('', Description);
- reg.WriteString('CLSID', GUIDToString(ClassID));
- reg.WriteString('CurVer', FClassName + '.1');
- reg.CloseKey;
-
- reg.OpenKey('CLSID\' + GUIDToString(ClassID), True);
- reg.WriteString('', Description);
- reg.WriteString('ProgID', FClassName);
- reg.WriteString('VersionIndependentProgID', FClassName);
- reg.WriteString('InprocServer32', 'MODULENAME');
- reg.CloseKey;
-
- reg.Free;
+ classidguid := GUIDToString(ClassID);
+ CreateRegKey('CLSID\' + classidguid, '', Description);
+ if ClassVersion <> '' then
+ begin
+ CreateRegKey('CLSID\' + classidguid + '\ProgID', '', ProgID + '.' + ClassVersion);
+ CreateRegKey('CLSID\' + classidguid + '\VersionIndependentProgID', '', ProgID + '.' + ClassVersion);
+ end
+ else
+ CreateRegKey('CLSID\' + classidguid + '\ProgID', '', ProgID);
- end;
- //This should be in typedcomobject
- //reg.WriteString('TypeLib', FClassName);
+ CreateRegKey('CLSID\' + classidguid + '\InprocServer32', '', FComServer.ServerFileName);
+
+ //tmSingle, tmApartment, tmFree, tmBoth, tmNeutral
+ CreateRegKey('CLSID\' + classidguid + '\InprocServer32', 'ThreadingModel', ThreadModelToString(ThreadingModel));
+
+ CreateRegKey(ProgID, '', Description);
+ CreateRegKey(ProgID + '\CLSID', '', GUIDToString(ClassID));
+ if ClassVersion <> '' then
+ begin
+ CreateRegKey(ProgID + '\CurVer', '', ProgID + '.' + ClassVersion);
+ CreateRegKey(ProgID + '.' + ClassVersion, '', Description);
+ CreateRegKey(ProgID + '.' + ClassVersion + '\CLSID', '', GUIDToString(ClassID));
+ end;
+ end else
+ begin
+ classidguid := GUIDToString(ClassID);
+ DeleteRegKey('CLSID\' + classidguid + '\InprocServer32');
+ DeleteRegKey('CLSID\' + classidguid + '\VersionIndependentProgID');
+ DeleteRegKey('CLSID\' + classidguid + '\ProgID');
+ DeleteRegKey('CLSID\' + classidguid);
+ DeleteRegKey(ProgID + '\CLSID');
+ DeleteRegKey(ProgID);
+ if ClassVersion <> '' then
+ begin
+ DeleteRegKey(ProgID + '.' + ClassVersion + '\CLSID');
+ DeleteRegKey(ProgID + '.' + ClassVersion);
+ end;
+ end;
+{$ifdef DEBUG_COM}
+ WriteLn('UpdateRegistry end');
+{$endif}
end;
@@ -1259,13 +1422,28 @@ HKCR
constructor TTypedComObjectFactory.Create(AComServer: TComServerObject; TypedComClass: TTypedComClass; const AClassID: TGUID;
AInstancing: TClassInstancing; AThreadingModel: TThreadingModel = tmSingle);
var
- TypedName, TypedDescription: WideString;
+ TypedName, TypedDescription, TypedVersion: WideString;
+ ppTypeAttr: lpTYPEATTR;
begin
//TDB get name and description from typelib (check if this is a valid guid)
OleCheck(AComServer.GetTypeLib.GetTypeInfoOfGuid(AClassID, FClassInfo));
+
//bug FPC 0010569 - http://msdn2.microsoft.com/en-us/library/ms221396(VS.85).aspx
- OleCheck(FClassInfo.GetDocumentation(-1, TypedName, TypedDescription, PLongWord(nil)^, PWideString(nil)^));
- inherited Create(AComServer, TypedComClass, AClassID, TypedName, TypedDescription, AInstancing, AThreadingModel);
+ OleCheck(FClassInfo.GetDocumentation(-1, @TypedName, @TypedDescription, nil, nil));
+ FClassInfo.GetTypeAttr(ppTypeAttr);
+ try
+ TypedVersion := '';
+ if (ppTypeAttr^.wMajorVerNum <> 0) or (ppTypeAttr^.wMinorVerNum <> 0) then
+ begin
+ TypedVersion := IntToStr(ppTypeAttr^.wMajorVerNum);
+ if ppTypeAttr^.wMinorVerNum <> 0 then
+ TypedVersion := TypedVersion + '.' + IntToStr(ppTypeAttr^.wMinorVerNum)
+ end;
+ finally
+ FClassInfo.ReleaseTypeAttr(ppTypeAttr);
+ end;
+
+ inherited Create(AComServer, TypedComClass, AClassID, TypedName, TypedVersion, TypedDescription, AInstancing, AThreadingModel);
end;
@@ -1276,11 +1454,198 @@ HKCR
procedure TTypedComObjectFactory.UpdateRegistry(Register: Boolean);
+ var
+ ptla: PTLibAttr;
begin
- inherited UpdateRegistry(Register);
- // 'TypeLib' = s '%LIBID%' missing ??? or does TComServer register it ?
- //un/register typed library
- RunError(217);
+ if Instancing = ciInternal then
+ Exit;
+
+ if Register then
+ begin
+ inherited UpdateRegistry(Register);
+
+ //http://www.experts-exchange.com/Programming/Misc/Q_20634807.html
+ //There seems to also be Version according to Process Monitor
+ //http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx
+ if FComServer.TypeLib = nil then
+ raise Exception.Create('TypeLib is not set!');
+
+ OleCheck(FComServer.TypeLib.GetLibAttr(ptla));
+ try
+ CreateRegKey('CLSID\' + GUIDToString(ClassID) + '\TypeLib', '', GUIDToString(ptla^.GUID));
+ finally
+ FComServer.TypeLib.ReleaseTLibAttr(ptla);
+ end;
+ end else
+ begin
+ DeleteRegKey('CLSID\' + GUIDToString(ClassID) + '\TypeLib');
+ inherited UpdateRegistry(Register);
+ end;
+ end;
+
+ { TAutoIntfObject }
+
+ function TAutoIntfObject.GetTypeInfoCount(out count: longint): HResult; stdcall;
+ begin
+{$ifdef DEBUG_COM}
+ WriteLn('TAutoIntfObject.GetTypeInfoCount');
+{$endif}
+ count := 1;
+ Result := S_OK;
+ end;
+
+ function TAutoIntfObject.GetTypeInfo(Index, LocaleID: longint; out TypeInfo
+ ): HResult; stdcall;
+ begin
+{$ifdef DEBUG_COM}
+ WriteLn('TAutoIntfObject.GetTypeInfo: ', Index);
+{$endif}
+ if Index <> 0 then
+ Result := DISP_E_BADINDEX
+ else
+ begin
+ ITypeInfo(TypeInfo) := fTypeInfo;
+ Result := S_OK;
+ end;
+ end;
+
+ function TAutoIntfObject.GetIDsOfNames(const iid: TGUID; names: Pointer;
+ NameCount, LocaleID: LongInt; DispIDs: Pointer): HResult; stdcall;
+ begin
+{$ifdef DEBUG_COM}
+ WriteLn('TAutoIntfObject.GetIDsOfNames: ', GUIDToString(iid));
+{$endif}
+ //return typeinfo->GetIDsOfNames(names, n, dispids);
+ Result := fTypeInfo.GetIDsOfNames(names, NameCount, lpDISPID(DispIDs)^);
+ end;
+
+ function TAutoIntfObject.Invoke(DispID: LongInt; const iid: TGUID;
+ LocaleID: longint; Flags: Word; var params; VarResult, ExcepInfo,
+ ArgErr: pointer): HResult; stdcall;
+ begin
+{$ifdef DEBUG_COM}
+ WriteLn('TAutoIntfObject.Invoke: ', DispID, ': ', Flags, ': ', TDispParams(params).cArgs, ': ', GUIDToString(iid));
+ //WriteLn('TAutoIntfObject.Invoke: ', DispID, ': ', Flags, ': ', TDispParams(params).cArgs, ': ', TDispParams(params).rgvarg^, ': ', GUIDToString(iid));
+{$endif}
+ if not IsEqualGUID(iid, GUID_NULL) then
+ Result := DISP_E_UNKNOWNINTERFACE
+ else
+ // Function Invoke(pvInstance: Pointer; memid: MEMBERID; wFlags: WORD; VAR pDispParams: DISPPARAMS; OUT pVarResult: VARIANT; OUT pExcepInfo: EXCEPINFO; OUT puArgErr: UINT):HResult;StdCall;
+ // Result := fTypeInfo.Invoke(IDispatch(Self), DispID, Flags, TDispParams(params), PVariant(VarResult)^, PExcepInfo(ExcepInfo)^, PUINT(ArgErr)^);
+ Result := fTypeInfo.Invoke(fInterfacePointer, DispID, Flags, TDispParams(params), PVariant(VarResult)^, PExcepInfo(ExcepInfo)^, PUINT(ArgErr)^);
+ end;
+
+ function TAutoIntfObject.InterfaceSupportsErrorInfo(const riid: TIID): HResult;
+ StdCall;
+ begin
+{$ifdef DEBUG_COM}
+ WriteLn('TAutoIntfObject.InterfaceSupportsErrorInfo: ', GUIDToString(riid));
+{$endif}
+ if assigned(GetInterfaceEntry(riid)) then
+ Result:=S_OK
+ else
+ Result:=S_FALSE;
+ end;
+
+ function TAutoIntfObject.SafeCallException(ExceptObject: TObject;
+ ExceptAddr: Pointer): HResult;
+ var
+ //Message: string;
+ Handled: Integer;
+ begin
+{$ifdef DEBUG_COM}
+ WriteLn('TAutoIntfObject.SafeCallException');
+{$endif}
+ Handled:=0;
+ Result:=0;
+ //TODO: DO WE NEED THIS ?
+ //if assigned(ServerExceptionHandler) then
+ // begin
+ // if ExceptObject is Exception then
+ // Message:=Exception(ExceptObject).Message;
+ //
+ // ServerExceptionHandler.OnException(ClassName,ExceptObject.ClassName,
+ // Message,PtrInt(ExceptAddr),WideString(GUIDToString(FFactory.ErrorIID)),
+ // FFactory.ProgID,Handled,Result);
+ // end;
+ if Handled=0 then
+ Result:=HandleSafeCallException(ExceptObject,ExceptAddr,StringToGuid('{7C538328-8A75-4EC4-A02E-FB3B27FAA411}'),
+ '','');
+ end;
+
+ constructor TAutoIntfObject.Create(TypeLib: ITypeLib; const Guid: TGuid);
+ begin
+{$ifdef DEBUG_COM}
+ WriteLn('TAutoIntfObject.Create: ', GUIDToString(Guid));
+{$endif}
+ OleCheck(TypeLib.GetTypeInfoOfGuid(Guid, fTypeInfo));
+ OleCheck(QueryInterface(Guid, fInterfacePointer));
+ end;
+
+ { TAutoObject }
+
+ function TAutoObject.GetTypeInfoCount(out count: longint): HResult; stdcall;
+ begin
+{$ifdef DEBUG_COM}
+ WriteLn('TAutoObject.GetTypeInfoCount');
+{$endif}
+ count := 1;
+ Result := S_OK;
+ end;
+
+ function TAutoObject.GetTypeInfo(Index, LocaleID: longint; out TypeInfo
+ ): HResult; stdcall;
+ begin
+{$ifdef DEBUG_COM}
+ WriteLn('TAutoIntfObject.GetTypeInfo: ', Index);
+{$endif}
+ if Index <> 0 then
+ Result := DISP_E_BADINDEX
+ else
+ begin
+ ITypeInfo(TypeInfo) := TAutoObjectFactory(Factory).ClassInfo;
+ Result := S_OK;
+ end;
+ end;
+
+ function TAutoObject.GetIDsOfNames(const iid: TGUID; names: Pointer; NameCount,
+ LocaleID: LongInt; DispIDs: Pointer): HResult; stdcall;
+ begin
+{$ifdef DEBUG_COM}
+ WriteLn('TAutoIntfObject.GetIDsOfNames: ', GUIDToString(iid));
+{$endif}
+ //return typeinfo->GetIDsOfNames(names, n, dispids);
+ Result := TAutoObjectFactory(Factory).ClassInfo.GetIDsOfNames(names, NameCount, lpDISPID(DispIDs)^);
+ end;
+
+ function TAutoObject.Invoke(DispID: LongInt; const iid: TGUID;
+ LocaleID: longint; Flags: Word; var params; VarResult, ExcepInfo,
+ ArgErr: pointer): HResult; stdcall;
+ var
+ fInterfacePointer: Pointer;
+ begin
+{$ifdef DEBUG_COM}
+ WriteLn('TAutoIntfObject.Invoke: ', DispID, ': ', Flags, ': ', TDispParams(params).cArgs, ': ', GUIDToString(iid));
+ //WriteLn('TAutoIntfObject.Invoke: ', DispID, ': ', Flags, ': ', TDispParams(params).cArgs, ': ', TDispParams(params).rgvarg^, ': ', GUIDToString(iid));
+{$endif}
+ if not IsEqualGUID(iid, GUID_NULL) then
+ Result := DISP_E_UNKNOWNINTERFACE
+ else
+ begin
+ // Function Invoke(pvInstance: Pointer; memid: MEMBERID; wFlags: WORD; VAR pDispParams: DISPPARAMS; OUT pVarResult: VARIANT; OUT pExcepInfo: EXCEPINFO; OUT puArgErr: UINT):HResult;StdCall;
+ // Result := fTypeInfo.Invoke(IDispatch(Self), DispID, Flags, TDispParams(params), PVariant(VarResult)^, PExcepInfo(ExcepInfo)^, PUINT(ArgErr)^);
+ OleCheck(QueryInterface(TAutoObjectFactory(Factory).ClassID, fInterfacePointer));
+ Result := TAutoObjectFactory(Factory).ClassInfo.Invoke(fInterfacePointer, DispID, Flags, TDispParams(params), PVariant(VarResult)^, PExcepInfo(ExcepInfo)^, PUINT(ArgErr)^);
+ end;
+ end;
+
+ { TAutoObjectFactory }
+
+ constructor TAutoObjectFactory.Create(AComServer: TComServerObject;
+ AutoClass: TAutoClass; const AClassID: TGUID; AInstancing: TClassInstancing;
+ AThreadingModel: TThreadingModel);
+ begin
+ inherited Create(AComServer, AutoClass, AClassID, AInstancing, AThreadingModel);
end;
procedure TOleStream.Check(err:integer);
diff --git a/packages/winunits-base/src/comserv.pp b/packages/winunits-base/src/comserv.pp
index 6b5ca79911..069ebc636f 100644
--- a/packages/winunits-base/src/comserv.pp
+++ b/packages/winunits-base/src/comserv.pp
@@ -21,7 +21,7 @@ interface
uses
Classes, SysUtils, comobj, ActiveX;
-{$define DEBUG_COM}
+{ $define DEBUG_COM}
//according to doc
// * ComServer Variable
@@ -44,6 +44,9 @@ type
private
fCountObject: Integer;
fCountFactory: Integer;
+ fTypeLib: ITypeLib;
+ fServerName,
+ fServerFileName: String;
protected
function CountObject(Created: Boolean): Integer; override;
function CountFactory(Created: Boolean): Integer; override;
@@ -60,6 +63,7 @@ type
procedure UnregisterServerFactory(Factory: TComObjectFactory);
public
constructor Create;
+ destructor Destroy; override;
function CanUnloadNow: Boolean;
procedure RegisterServer;
procedure UnRegisterServer;
@@ -90,6 +94,9 @@ function DllUnregisterServer: HResult; stdcall;
implementation
+uses
+ Windows;
+
function DllCanUnloadNow: HResult; stdcall;
begin
{$ifdef DEBUG_COM}
@@ -168,6 +175,43 @@ begin
end;
end;
+function GetModuleFileName: String;
+const
+ MAX_PATH_SIZE = 2048;
+begin
+ SetLength(Result, MAX_PATH_SIZE);
+ SetLength(Result, Windows.GetModuleFileName(HInstance, @Result[1], MAX_PATH_SIZE));
+end;
+
+function GetModuleName: String;
+begin
+ Result := ExtractFileName(GetModuleFileName);
+ Result := Copy(Result, 1,LastDelimiter('.', Result)-1);
+end;
+
+procedure RegisterTypeLib(TypeLib: ITypeLib; const ModuleName: string);
+var
+ FullPath: WideString;
+begin
+ FullPath := ModuleName;
+ //according to MSDN helpdir can be null
+ OleCheck(ActiveX.RegisterTypeLib(TypeLib, @FullPath[1], nil));
+end;
+
+procedure UnRegisterTypeLib(TypeLib: ITypeLib);
+var
+ ptla: PTLibAttr;
+begin
+ //http://www.experts-exchange.com/Programming/Misc/Q_20634807.html
+ OleCheck(TypeLib.GetLibAttr(ptla));
+ try
+ OleCheck(ActiveX.UnRegisterTypeLib(ptla^.guid, ptla^.wMajorVerNum, ptla^.wMinorVerNum, ptla^.lcid, ptla^.syskind));
+ finally
+ TypeLib.ReleaseTLibAttr(ptla);
+ end;
+end;
+
+
{ TComServer }
function TComServer.CountObject(Created: Boolean): Integer;
@@ -193,7 +237,7 @@ end;
function TComServer.GetServerFileName: string;
begin
- RunError(217);
+ Result := fServerFileName;
end;
function TComServer.GetServerKey: string;
@@ -203,7 +247,7 @@ end;
function TComServer.GetServerName: string;
begin
- RunError(217);
+ Result := fServerName;
end;
function TComServer.GetStartSuspended: Boolean;
@@ -213,7 +257,7 @@ end;
function TComServer.GetTypeLib: ITypeLib;
begin
- RunError(217);
+ Result := fTypeLib;
end;
procedure TComServer.SetHelpFileName(const Value: string);
@@ -228,13 +272,41 @@ end;
procedure TComServer.UnregisterServerFactory(Factory: TComObjectFactory);
begin
- Factory.UpdateRegistry(false);
+ Factory.UpdateRegistry(False);
end;
constructor TComServer.Create;
+var
+ name: WideString;
begin
+ inherited Create;
+{$ifdef DEBUG_COM}
+ WriteLn('TComServer.Create');
+{$endif}
fCountFactory := 0;
fCountObject := 0;
+
+ fServerFileName := GetModuleFileName();
+
+ name := fServerFileName;
+ if not(Succeeded(LoadTypeLib(@name[1], fTypeLib))) then
+ fTypeLib := nil;
+
+ if FTypeLib <> nil then
+ begin
+ fTypeLib.GetDocumentation(-1, @name, nil, nil, nil);
+ fServerName := name;
+ end
+ else
+ fServerName := GetModuleName;
+end;
+
+destructor TComServer.Destroy;
+begin
+ inherited Destroy;
+{$ifdef DEBUG_COM}
+ WriteLn('TComServer.Destroy');
+{$endif}
end;
function TComServer.CanUnloadNow: Boolean;
@@ -244,11 +316,17 @@ end;
procedure TComServer.RegisterServer;
begin
+ if fTypeLib <> nil then
+ RegisterTypeLib(fTypeLib, fServerFileName);
+
ComClassManager.ForEachFactory(self, @RegisterServerFactory);
end;
procedure TComServer.UnRegisterServer;
begin
+ if fTypeLib <> nil then
+ UnRegisterTypeLib(fTypeLib);
+
ComClassManager.ForEachFactory(self, @UnregisterServerFactory);
end;