Page 1 of 1

Writing COM Server DLLs (64bit, 32bit, Windows)

Posted: Fri Feb 03, 2012 10:04 am
by DarkDragon
Hello,

Here I will start a tutorial about how to write COM servers with PureBasic. The COM Server will implement one new test class (derived from a test interface) which will be accessible for the COM clients. First of all you need to know Interfaces/OOP and the sense of COM. Maybe you should even know about how to write COM clients. The most important thing: nearly all interfaces you are using with COM are derived from IUnknown or IDispatch and if you want a type library (not necessary) you must ensure, that every interface method returns an HRESULT, which is equal to a PureBasic long.

By default I am using the 64bit compiler to show that PureBasic is even able to produce 64bit COM modules.

I am not responsible for any damage caused by changes you made in your system with the software presented here. Try to boot in safe mode if your windows doesn't boot anymore like before.


Important Base Knowledge
Whenever a COM client application requests a new class instance by calling CoCreateInstance the function DllGetClassObject will be called inside the server dll. This function creates a class factory object which will be used to create the instance of the requested class.
So the calls are like:

Code: Select all

       CoCreateInstance (Client)
                │
                │
                v
       DllGetClassObject
                │
                │
                v
   ClassFactory\CreateInstance
                │
                │
                v
     RequestedClass\QueryInterface
(As far as I know the ClassFactory only exists to satisfy OOP junkies)
So DllGetClassObject will be the most important function we will need to export in our DLL. Another important function is DllCanUnloadNow, which returns #S_OK (0) if all objects of classes inside this DLL are deleted and #S_FALSE (1) if not. This is everything which is necessary for writing a COM server, but there are two additional functions, which we can export to register and unregister the DLL inside the operating system:
DllRegisterServer gets called when someone executes "regsvr32.exe MyCOM.dll" and it should set up the registry entries for using this COM DLL.
DllUnregisterServer gets called when someone executes "regsvr32.exe /u MyCOM.dll" and it should undo the registry changes made by DllRegisterServer.

If you execute "regsvr32.exe /?" you will notice that it offers an alternative to those two functions:
/i - Call DllInstall passing it an optional [cmdline]; when used with /u calls dll uninstall
This is not necessary. Not even the two above are necessary, you can do the registry entries manually or via an external program (usually the installer does it).


Requirements
GUID is the short form of Global Unique Identifier. They are already declared by PureBasic through the structure "GUID". Usually COM users are having a macro like this to define new GUIDs inside the code:

Code: Select all

Macro DEFINE_GUID(Name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
  Global Name.GUID
  
  Name\Data1    = l
  Name\Data2    = w1
  Name\Data3    = w2
  Name\Data4[0] = b1
  Name\Data4[1] = b2
  Name\Data4[2] = b3
  Name\Data4[3] = b4
  Name\Data4[4] = b5
  Name\Data4[5] = b6
  Name\Data4[6] = b7
  Name\Data4[7] = b8
EndMacro
For identifying our new class we will need a CLSID (for the class) and an IID (for the interface). You can generate them with any GUID generator out there. If you've downloaded the microsoft windows sdk, you even have a "guidgen.exe" which can do this. I got those two GUIDs:

Code: Select all

; {329AA340-3E15-469a-86E7-17CE6DACC2E4}
DEFINE_GUID(CLSID_MyTestClass, $329aa340, $3e15, $469a, $86, $e7, $17, $ce, $6d, $ac, $c2, $e4)

; the interface (iid) guid:
; {375749F8-D6CC-4631-B14A-00224F717391}
DEFINE_GUID(IID_MyTestClass, $375749f8, $d6cc, $4631, $b1, $4a, $0, $22, $4f, $71, $73, $91)
We need this GUIDs also as string, to register the COM server. Therefore I made this long macro:

Code: Select all

Macro PRINT_GUID(guid)
  RSet(Hex(guid\Data1, #PB_Long), 8, "0") + "-" + RSet(Hex(guid\Data2, #PB_Word), 4, "0") + "-" + RSet(Hex(guid\Data3, #PB_Word), 4, "0") + "-" + RSet(Hex(guid\Data4[0], #PB_Byte), 2, "0") + RSet(Hex(guid\Data4[1], #PB_Byte), 2, "0") + "-" + RSet(Hex(guid\Data4[2], #PB_Byte), 2, "0") + RSet(Hex(guid\Data4[3], #PB_Byte), 2, "0") + RSet(Hex(guid\Data4[4], #PB_Byte), 2, "0") + RSet(Hex(guid\Data4[5], #PB_Byte), 2, "0") + RSet(Hex(guid\Data4[6], #PB_Byte), 2, "0") + RSet(Hex(guid\Data4[7], #PB_Byte), 2, "0")
EndMacro
For the DllCanUnloadNow function we will need a global variable inside the dll, which counts how many objects are still alive:

Code: Select all

Global DllRefCount.l
IUnknown
IUnknown is the interface, which every single COM class is derived from. It consists of a reference counter for the current object and a method called QueryInterface, where sub interfaces of the same object can be requested. You may want to implement more than one interface in one class.

The IUnknown interface has this IID:

Code: Select all

DEFINE_GUID(IID_IUnknown,       $00000000, $0000, $0000, $C0, $00, $00, $00, $00, $00, $00, $46)
I don't trust the declaration of IUnknown inside PureBasic, as it has no valid return types and parameter types (see the structure viewer), so we need to define it ourselves again:

Code: Select all

Interface MyUnknown
  QueryInterface.l(*riid.IID, *ppv.Integer)
  AddRef.l()
  Release.l()
EndInterface

Structure SMyUnknown
  *VFTable.i
  
  ReferenceCount.l
EndStructure

Procedure.l MyUnknown_AddRef(*this.SMyUnknown)
  *this\ReferenceCount + 1
  
  ProcedureReturn *this\ReferenceCount
EndProcedure

Procedure.l MyUnknown_Release(*this.SMyUnknown)
  *this\ReferenceCount - 1
  
  If *this\ReferenceCount <= 0
    ; the reference counter is lower or equal zero, so delete this object:
    
    FreeMemory(*this\VFTable)
    FreeMemory(*this)
    
    ; decrement the dll reference counter (usually you should use InterlockedDecrement, but polink doesn't know it):
    DllRefCount - 1
    
    ProcedureReturn 0
  Else
    ProcedureReturn *this\ReferenceCount
  EndIf
EndProcedure

Procedure.l MyUnknown_QueryInterface(*this.SMyUnknown, *riid.IID, *ppv.Integer)
  *ppv\i = #Null
  
  ; We can still return the IUnknown interface, but nobody would ever request that in here:
  If CompareMemory(*riid, @IID_IUnknown, SizeOf(IID))
    *ppv\i = *this
    
    ; a new reference for this object will be returned
    MyUnknown_AddRef(*this)
    
    ProcedureReturn #S_OK
  EndIf
  
  ProcedureReturn #E_FAIL
EndProcedure
You don't need a constructor here, as this can be compared to an abstract class. We will override QueryInterface inside the ClassFactory and the TestClass.


Our TestClass
Before we can start creating instances of our TestClass, we need the TestClass itself. It will save one number, which is initialized randomly at the beginning. You can get and set this number through methods defined in the TestClass. It also inherits the methods from the IUnknown interface.

Code: Select all

Interface MyTestClass Extends MyUnknown
  GetNumber.l(*Number.Integer)
  SetNumber.l(Number.i)
EndInterface

Structure SMyTestClass Extends SMyUnknown
  Number.i
EndStructure

Procedure.l MyTestClass_QueryInterface(*this.MyTestClass, *riid.IID, *ppv.Integer)
  *ppv\i = #Null
  
  ; inherits IUnknown, so we can return this
  ; inherits IMyTestClass (which is equal to MyTestClass), so we can also return this
  If CompareMemory(*riid, @IID_IUnknown, SizeOf(IID)) Or CompareMemory(*riid, @IID_MyTestClass, SizeOf(IID))
    *ppv\i = *this
    
    ; increment the ref. counter
    *this\AddRef()
    
    ProcedureReturn #S_OK
  EndIf
  
  ProcedureReturn #E_FAIL
EndProcedure

; will return the number of the object (initialized as random, see constructor)
Procedure.l MyTestClass_GetNumber(*this.SMyTestClass, *Number.Integer)
  *Number\i = *this\Number
  ProcedureReturn #S_OK
EndProcedure

; will set the number of the object
Procedure.l MyTestClass_SetNumber(*this.SMyTestClass, Number.i)
  *this\Number = Number ; set the number and return #S_OK
  
  ProcedureReturn #S_OK
EndProcedure

; the constructor
Procedure.i MyTestClass_Constructor()
  Protected *this.SMyTestClass
  
  ; allocate the object's memory
  *this = AllocateMemory(SizeOf(SMyTestClass))
  
  If *this
    ; copy the vftable from the datasection
    *this\VFTable = AllocateMemory(?MyTestClassVFTEnd - ?MyTestClassVFTStart)
    CopyMemory(?MyTestClassVFTStart, *this\VFTable, ?MyTestClassVFTEnd - ?MyTestClassVFTStart)
    
    *this\Number = Random(10) ; initialize the object's number attribute
    
    ; increment the dll ref. counter
    DllRefCount + 1
  EndIf
  
  ProcedureReturn *this
  
  DataSection
    MyTestClassVFTStart:
      Data.i @MyTestClass_QueryInterface() ; overridden
      Data.i @MyUnknown_AddRef()           ; from MyUnknown
      Data.i @MyUnknown_Release()          ; from MyUnknown
      Data.i @MyTestClass_GetNumber()      ; from MyTestClass
      Data.i @MyTestClass_SetNumber()      ; from MyTestClass
    MyTestClassVFTEnd:
  EndDataSection
EndProcedure
IClassFactory
The IClassFactory interface inherits the IUnknown interface and has two additional methods:
  • CreateInstance.l(*pUnkOuter.IUnknown, *riid.IID, *ppv.Integer) is creating the instances of the TestClass
  • LockServer.l(fLock.l) is ensuring threadsafety, but we won't use it and we will just return #E_UNEXPECTED
It looks like this:

Code: Select all

Interface MyClassFactory Extends MyUnknown
  CreateInstance.l(*pUnkOuter.IUnknown, *riid.IID, *ppv.Integer)
  LockServer.l(fLock.l)
EndInterface

Structure SMyClassFactory Extends SMyUnknown
EndStructure

Procedure.l MyClassFactory_QueryInterface(*this.MyClassFactory, *riid.IID, *ppv.Integer)
  *ppv\i = #Null
  
  ; inherits IUnknown, so we can return this
  ; inherits IClassFactory, so we can also return this
  If CompareMemory(*riid, @IID_IUnknown, SizeOf(IID)) Or CompareMemory(*riid, @IID_IClassFactory, SizeOf(IID))
    *ppv\i = *this
    
    ; a new reference for this object will be returned
    *this\AddRef()
    
    ProcedureReturn #S_OK
  EndIf
  
  ProcedureReturn #E_FAIL
EndProcedure

Procedure.l MyClassFactory_CreateInstance(*this.MyClassFactory, *pUnkOuter.IUnknown, *riid.IID, *ppv.Integer)
  Protected *object.MyTestClass
  
  ; The Unk in UnkOuter means Unknown. When classes inherit from multiple interfaces,
  ; they would have different relative locations of the IUnknown interface inside the vftable.
  ; But this would be a mess with reference counting, so you could also return a separate pointer for IUnknown.
  If *pUnkOuter <> #Null
    ProcedureReturn #CLASS_E_NOAGGREGATION
  EndIf
  
  ; The *ppv must be valid
  If *ppv = #Null
    ProcedureReturn #E_POINTER
  EndIf
  
  ; Create the TestClass object
  *object = MyTestClass_Constructor()
  If *object = #Null
    ProcedureReturn #E_OUTOFMEMORY
  EndIf
  
  ; increment it's ref. counter
  *object\AddRef()
  
  ; and return the requested interface inside this object.
  ProcedureReturn *object\QueryInterface(*riid, *ppv)
EndProcedure

Procedure.l MyClassFactory_LockServer(*this.MyClassFactory, fLock.l)
  ProcedureReturn #E_UNEXPECTED ; not used.
EndProcedure

; the constructor
Procedure.i MyClassFactory_Constructor()
  Protected *this.SMyClassFactory
  
  ; allocate the object's memory
  *this = AllocateMemory(SizeOf(SMyClassFactory))
  
  If *this
    ; copy the vftable from the datasection
    *this\VFTable = AllocateMemory(?MyClassFactoryVFTEnd - ?MyClassFactoryVFTStart)
    CopyMemory(?MyClassFactoryVFTStart, *this\VFTable, ?MyClassFactoryVFTEnd - ?MyClassFactoryVFTStart)
    
    ; increment the dll reference counter
    DllRefCount + 1
  EndIf
  
  ; return the object
  ProcedureReturn *this
  
  DataSection
    MyClassFactoryVFTStart:
      Data.i @MyClassFactory_QueryInterface() ; overridden
      Data.i @MyUnknown_AddRef()              ; from MyUnknown
      Data.i @MyUnknown_Release()             ; from MyUnknown
      Data.i @MyClassFactory_CreateInstance() ; ClassFactory method
      Data.i @MyClassFactory_LockServer()     ; ClassFactory method
    MyClassFactoryVFTEnd:
  EndDataSection
EndProcedure
As you can see the CreateInstance method doesn't return the class pointer directly. Instead it calls the QueryInterface of the new object to return the interface pointer. With CoGetClassObject a client can get this ClassFactory object to create objects, but usually a client uses CoCreateInstance which will internally get the class factory and return the requested instances of the specified classes directly. For more information: IClassFactory interface.


DllGetClassObject and DllCanUnloadNow
Its not very much I could explain about that, which wasn't said at the beginning. I've written the explanation as comments into this source code:

Code: Select all

; the class factory creator
ProcedureDLL.l DllGetClassObject(*rclsid.CLSID, *riid.IID, *ppv.Integer)
  Protected *object.MyClassFactory
  
  ; the wished class is not CLSID_MyTestClass, so return #CLASS_E_CLASSNOTAVAILABLE
  If Not CompareMemory(*rclsid, @CLSID_MyTestClass, SizeOf(CLSID))
    ProcedureReturn #CLASS_E_CLASSNOTAVAILABLE
  EndIf
  
  ; the wished interface must be IClassFactory
  If CompareMemory(*riid, @IID_IClassFactory, SizeOf(CLSID))
    ; create the class factory
    *object = MyClassFactory_Constructor()
    
    ; increment the reference counter
    *object\AddRef()
    
    ; return the object's pointer
    *ppv\i = *object
    
    ProcedureReturn #S_OK
  EndIf
  
  ProcedureReturn #CLASS_E_CLASSNOTAVAILABLE
EndProcedure

ProcedureDLL.l DllCanUnloadNow()
  ; only if this statement is true, the dll should be ready for unloading
  If DllRefCount <= 0
    ProcedureReturn #S_OK
  EndIf
  
  ProcedureReturn #S_FALSE
EndProcedure
Registering and Unregistering
For registering the DLL as a COM DLL we just need to create three registry entries:

Code: Select all

HKLM\SOFTWARE\Classes\CLSID\{CLSID_MyTestClass}\(Default) = "MyTestClass"
HKLM\SOFTWARE\Classes\CLSID\{CLSID_MyTestClass}\InprocServer32\(Default) = path and filename to your DLL
HKLM\SOFTWARE\Classes\CLSID\{CLSID_MyTestClass}\InprocServer32\ThreadingModel = "Apartment"
I've used this include for managing the registry with PureBasic, as registry handling shouldn't be covered by this tutorial: http://www.purebasic.fr/german/viewtopi ... =8&t=14900

Code: Select all

Procedure UnregisterNative(*CLSID.GUID)
  ; simply delete the HKLM\SOFTWARE\Classes\CLSID\{CLSID} key
  Reg_DeleteKeyWithAllSub(#HKEY_LOCAL_MACHINE, "SOFTWARE\Classes\CLSID\" + "{" + PRINT_GUID(*CLSID) + "}")
EndProcedure

Procedure RegisterNative(*CLSID.GUID, Name.s, File.s)
  UnregisterNative(*CLSID)
  
  Reg_CreateKeyValue(#HKEY_LOCAL_MACHINE, "SOFTWARE\Classes\CLSID\" + "{" + PRINT_GUID(*CLSID) + "}", "", Name, #REG_SZ)
  Reg_CreateKeyValue(#HKEY_LOCAL_MACHINE, "SOFTWARE\Classes\CLSID\" + "{" + PRINT_GUID(*CLSID) + "}" + "\InprocServer32", "", File, #REG_SZ)
  Reg_SetValue(#HKEY_LOCAL_MACHINE, "SOFTWARE\Classes\CLSID\" + "{" + PRINT_GUID(*CLSID) + "}" + "\InprocServer32", "ThreadingModel", "Apartment", #REG_SZ)
EndProcedure

; You may want to register a 32bit DLL through a 64bit program on a 64bit machine.
; Therefore you have to exchange "SOFTWARE" with "SOFTWARE\Wow6432Node"

Macro Register(CLSID, Name, File = ProgramFilename())
  RegisterNative(CLSID, Name, File)
EndMacro

Macro Unregister(CLSID)
  UnregisterNative(CLSID)
EndMacro

; Those two functions are only necessary for registering through regsvr32.exe:
ProcedureDLL.l DllRegisterServer()
  Register(@CLSID_MyTestClass, "MyTestClass", ProgramFilename())
  
  ProcedureReturn #S_OK
EndProcedure

ProcedureDLL.l DllUnregisterServer()
  Unregister(@CLSID_MyTestClass)
  
  ProcedureReturn #S_OK
EndProcedure
After that you must execute "regsvr32.exe MyCOMTestDLL.dll" with administrative rights to register the DLL and "regsvr32.exe /u MyCOMTestDLL.dll" (also with administrative rights) for unregistering. To register a 32bit DLL within a 64bit system (for 32bit clients a 32bit server is necessary) you need to execute "%SystemRoot%\SysWOW64\regsvr32.exe" instead. It will automatically redirect the registry to "HKLM\SOFTWARE\Wow6432Node" instead of just "HKLM\SOFTWARE".

However there is another change you need to make if you want to install the COM server system wide: "HKCR\CLSID" is used instead. RegOverridePredefKey/ may be helpful for those redirecting actions.


Simple Client
After registering your DLL you can try it with this simple client:

Code: Select all

; ************************************************************************************************************
; * Author:             Daniel Brall                                                                         *
; * WWW   :             http://www.bradan.eu/                                                                *
; * Desc. :             A simple COM client                                                                  *
; ************************************************************************************************************

CoInitialize_(0)

; you need the interface definition:
Interface MyUnknown
  QueryInterface.l(*riid.IID, *ppv.Integer)
  AddRef.l()
  Release.l()
EndInterface

Interface MyTestClass Extends MyUnknown
  GetNumber.l(*Number.Integer)
  SetNumber.l(Number.i)
EndInterface

; and the GUIDs
Macro DEFINE_GUID(Name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
  Global Name.GUID
  
  Name\Data1    = l
  Name\Data2    = w1
  Name\Data3    = w2
  Name\Data4[0] = b1
  Name\Data4[1] = b2
  Name\Data4[2] = b3
  Name\Data4[3] = b4
  Name\Data4[4] = b5
  Name\Data4[5] = b6
  Name\Data4[6] = b7
  Name\Data4[7] = b8
EndMacro

; should be the same as in Constants.pbi:
DEFINE_GUID(CLSID_MyTestClass, $329aa340, $3e15, $469a, $86, $e7, $17, $ce, $6d, $ac, $c2, $e4)
DEFINE_GUID(IID_MyTestClass, $375749f8, $d6cc, $4631, $b1, $4a, $0, $22, $4f, $71, $73, $91)

Define *MyTestClassObject.MyTestClass = #Null
Define Result.l
Define Number.i

Result = CoCreateInstance_(@CLSID_MyTestClass, #Null, 1, @IID_MyTestClass, @*MyTestClassObject)
If Result = #S_OK And *MyTestClassObject <> #Null
  If *MyTestClassObject\GetNumber(@Number) = #S_OK
    Debug Number
  Else
    Debug "Error: GetNumber failed"
  EndIf
  
  If *MyTestClassObject\SetNumber(-1) = #S_OK
    Debug "OK: SetNumber returned S_OK"
  Else
    Debug "Error: SetNumber failed."
  EndIf
  
  If *MyTestClassObject\GetNumber(@Number) = #S_OK
    Debug Number
  Else
    Debug "Error: GetNumber failed"
  EndIf
  
  *MyTestClassObject\Release()
Else
  Debug "Error: 0x" + Hex(Result, #PB_Long)
EndIf

CoUninitialize_()
Advanced additional task: Type Libraries
This section isn't necessary at all, but some people might want to create a type libraries. Type libraries are describing the exported classes and interfaces, so anyone who wants to use the COM server can use the type library to tell the linker what offsets are needed etc. Its like a language independent header file. You'll need the Windows SDK (I use 7.1) and Microsoft Visual Studio (I use Express 2010) for the following steps.
To describe the previously shown TestClass we must have an IDL file, which is nothing else than the readable TLB file. It looks like this and the name of the syntax is Object Description Language:

Code: Select all

import "oaidl.idl";
import "ocidl.idl";

// interface declaration
[
	uuid(375749F8-D6CC-4631-B14A-00224F717391),
	helpstring("Is able to save a signed integer (native bit size)")
] interface IMyTestClass : IUnknown {
	// the names are unimportant, but as we specify propget/propput
	// the GetNumber SetNumber doesn't need to have the Get/Set prefix.
	#if defined _WIN64 || defined __amd64__
	  [propget,helpstring("Returns the number.")] HRESULT Number([out,retval] long long*);
	  [propput,helpstring("Sets the number.")] HRESULT Number([in] long long);
	#else
	  [propget,helpstring("Returns the number.")] HRESULT Number([out,retval] int*);
	  [propput,helpstring("Sets the number.")] HRESULT Number([in] int);
	#endif
};

// library declaration
[
	// the type library id:
	// we will need this inside our code
	uuid(B981CAEC-BACE-4fd2-B553-615A0F832D0F),
	helpstring("Contains MyTestClass"),
	version(1.0) // major.minor - we will need this inside our code
] library MyTestClassLib
{
	// class declaration
	[
		uuid(329AA340-3E15-469a-86E7-17CE6DACC2E4),
		helpstring("MyTestClass itself: it will save a signed integer (native bit size)")
	] coclass MyTestClass
	{
		[default] interface IMyTestClass;
	};
};
Every []-block specifies attributes of the following declaration, so uuid(B981CAEC-BACE-4fd2-B553-615A0F832D0F) is the GUID of the type library. There are many different attributes which can be set. One GUID I've added is the one for the library (B981CAEC-BACE-4fd2-B553-615A0F832D0F). We will need this for the import statement when using this type library. The getter and setter inside our interface has no Get/Set prefix. Instead we have specified the propget/propput and retval properties. The reason for this is shown inside the C++ example at the end of this section. You can access the Number via instance->Number as if you would read from/write to a variable instead of calling a method. This increases the readability of the code. The Microsoft Visual C++ compiler will translate this into a call of your setter or getter.
For a better explanation on this language, see Type Libraries and the Object Description Language.
For compiling this IDL file into a TLB file I use this code:

Code: Select all

Define Path.s
Define PathBackup.s

Define CD.s = GetCurrentDirectory()

If Right(CD, 1) <> "\"
  CD + "\"
EndIf

Define IDLFile.s = CD + "MyTestClass.idl"
Define TLBFile.s = CD + "MyTestClass.tlb"

#TARGET_ENVIRONMENT = "x64" ; win32, x64 or ia64


; 64 bit:
Define MSVCBin.s                = "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\amd64"  ; contains cl.exe

; 32 bit:
; Define MSVCBin.s                = "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin"        ; contains cl.exe

Define MSVSCommon7IDE.s         = "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE"
Define MSPSDKWinServer2003Bin.s = "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin"                ; contains midl.exe
Define MSPSDKWinServer2003Inc.s = "C:\Program Files\Microsoft SDKs\Windows\v7.1\Include"            ; contains ocidl.acf

OpenConsole()

Path = GetEnvironmentVariable("PATH")
PathBackup = Path

Path = Path + ";" + MSVSCommon7IDE
Path = Path + ";" + MSPSDKWinServer2003Bin

Path = ReplaceString(Path, ";;", ";")

SetEnvironmentVariable("PATH", Path)

SetCurrentDirectory(MSVCBin)

RunProgram("midl.exe", #DQUOTE$ + IDLFile + #DQUOTE$ + " /tlb " + #DQUOTE$ + TLBFile + #DQUOTE$ + " /robust /" + #TARGET_ENVIRONMENT + " /I " + #DQUOTE$ + MSPSDKWinServer2003Inc + #DQUOTE$, GetCurrentDirectory(), #PB_Program_Wait)

SetEnvironmentVariable("PATH", PathBackup)

PrintN("")
PrintN("")
PrintN(LSet("", 16, ">") + " Finished! " + RSet("", 16, "<"))
PrintN("")
Input()
You may have to correct the paths. The TargetEnvironment also has to be changed to win32 if you're requesting a 32bit tlb file.
The correct output when compiling the IDL to TLB should be similar to this:
Microsoft (R) 32b/64b MIDL Compiler Version 7.00.0555
Copyright (c) Microsoft Corporation. All rights reserved.
64 bit Processing C:\[...]\MyTestClass.idl

MyTestClass.idl
64 bit Processing C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\oaidl.idl

oaidl.idl
64 bit Processing C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\objidl.idl

objidl.idl
64 bit Processing C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\unknwn.idl

unknwn.idl
64 bit Processing C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\wtypes.idl

wtypes.idl
64 bit Processing C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\basetsd.h

basetsd.h
64 bit Processing C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\guiddef.h

guiddef.h
64 bit Processing C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\ocidl.idl

ocidl.idl
64 bit Processing C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\oleidl.idl

oleidl.idl
64 bit Processing C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\servprov.idl

servprov.idl
64 bit Processing C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\urlmon.idl

urlmon.idl
64 bit Processing C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\msxml.idl

msxml.idl
64 bit Processing C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\oaidl.acf

oaidl.acf
64 bit Processing C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\ocidl.acf

ocidl.acf


>>>>>>>>>>>>>>>> Finished! <<<<<<<<<<<<<<<<
This generated type library (the "MyTestClass.tlb" file) has to be registered. I made a little program describing how you can register/unregister the typelib, but usually you should put this inside DllRegisterServer and DllUnregisterServer. If you pass /u to the program it will unregister MyTestClass.tlb, otherwise it will register it:

Code: Select all

OpenConsole()

Macro DEFINE_GUID(Name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
  Global Name.GUID
  
  Name\Data1    = l
  Name\Data2    = w1
  Name\Data3    = w2
  Name\Data4[0] = b1
  Name\Data4[1] = b2
  Name\Data4[2] = b3
  Name\Data4[3] = b4
  Name\Data4[4] = b5
  Name\Data4[5] = b6
  Name\Data4[6] = b7
  Name\Data4[7] = b8
EndMacro

Enumeration ; SYSKIND
  #SYS_WIN16
  #SYS_WIN32
  #SYS_MAC
  #SYS_WIN64
EndEnumeration

Define TLBFile.s

; {B981CAEC-BACE-4fd2-B553-615A0F832D0F}
DEFINE_GUID(LIBID_MyTestClass, $b981caec, $bace, $4fd2, $b5, $53, $61, $5a, $f, $83, $2d, $f);

CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
#OUR_SYSKIND = #SYS_WIN64
TLBFile = "MyTestClass.tlb"
CompilerElse
#OUR_SYSKIND = #SYS_WIN32
TLBFile = "MyTestClass32.tlb"
CompilerEndIf

Procedure.i RegisterTypeLib(Filename.s)
  Protected *TypeLib.ITypeLib = #Null
  Protected *FilenameUnicode = AllocateMemory(StringByteLength(Filename + " ", #PB_Unicode))
  Protected Result.i = #False
  
  If *FilenameUnicode <> #Null
    PokeS(*FilenameUnicode, Filename, -1, #PB_Unicode)
    
    If LoadTypeLib_(*FilenameUnicode, @*TypeLib) = #S_OK
      ; we've loaded the tlb file, so register it now:
      If RegisterTypeLib_(*TypeLib, *FilenameUnicode, #Null) = #S_OK
        PrintN("Typelib successfully registered.")
        Result = #True
      Else
        PrintN("RegisterTypeLib failed.")
      EndIf
      *TypeLib\Release()
    Else
      PrintN("LoadTypeLib failed.")
    EndIf
    
    FreeMemory(*FilenameUnicode)
  Else
    PrintN("Not enough memory")
  EndIf
  
  ProcedureReturn Result
EndProcedure

Procedure UnRegisterTypeLib(*LibID.GUID, Major.w, Minor.w)
  If UnRegisterTypeLib_(*LibID, Major, Minor, #LANG_NEUTRAL, #OUR_SYSKIND) = #S_OK
    PrintN("Typelib sucessfully unregistered.")
    ProcedureReturn #True
  EndIf
  
  PrintN("UnRegisterTypeLib failed.")
  ProcedureReturn #False
EndProcedure

; we don't want HKCR registration, we want HKLM\SOFTWARE\Classes instead, so redirect any changes.
Prototype _RegOverridePredefKey(hKey.i, hKeyNew.i)
Global RegOverridePredefKey_._RegOverridePredefKey
Global Advapi32DLL.i

Advapi32DLL = OpenLibrary(#PB_Any, "Advapi32.dll")
If Advapi32DLL
  RegOverridePredefKey_ = GetFunction(Advapi32DLL, "RegOverridePredefKey")
EndIf

Define KeyHandle.i

RegOpenKey_(#HKEY_CURRENT_USER, @"SOFTWARE\Classes", @KeyHandle)
RegOverridePredefKey_(#HKEY_CLASSES_ROOT, KeyHandle)

If ProgramParameter() = "/u"
  ; for unregistering:
  UnRegisterTypeLib(@LIBID_MyTestClass, 1, 0)
Else
  Define ProgramPath.s = GetPathPart(ProgramFilename())
  
  If Right(ProgramPath, 1) <> "\"
    ProgramPath + "\"
  EndIf
  
  ; now register the typelib
  RegisterTypeLib(ProgramPath + TLBFile)
EndIf

; end with redirecting the registry changes:
RegOverridePredefKey_(#HKEY_CLASSES_ROOT, #Null)
RegCloseKey_(KeyHandle)

If Advapi32DLL
  CloseLibrary(Advapi32DLL)
EndIf
It basically generates a new registry key in "HKLM\SOFTWARE\Classes\TypeLib\{LibUUID}" containing a few sub keys. Nothing more or less.
After registering the DLL(s) and the TypeLib(s) you can use it in any of Microsoft's programming languages which are supporting typelib importing. Here is an example written in C++:

Code: Select all

#include <stdio.h>
#include <comdef.h>
#include <Windows.h>

// be careful: you need to call the native 64bit compiler (not the cross compiler), otherwise it will choose the 32bit registry entries.
// this will import the typelib with the specified uuid
#import "libid:B981CAEC-BACE-4fd2-B553-615A0F832D0F" named_guids no_namespace

int main(int argc, char* argv[])
{
	CoInitialize(0);

	IMyTestClass* test;

	if(CoCreateInstance(CLSID_MyTestClass, NULL, 1, IID_IMyTestClass, (LPVOID*) &test) == S_OK)
	{
		printf("OK\n");

		printf("Number: %d\n", test->Number);

		test->Number = -1;

		printf("Number: %d\n", test->Number);
	} else {
		printf("ERROR\n");
	}

	CoUninitialize();

	system("PAUSE");

	return 0;
}
Useful Links
Functions: CoCreateInstance, DllGetClassObject, DllCanUnloadNow, DllRegisterServer, DllUnregisterServer, RegOverridePredefKey
IClassFactory interface
Type Libraries and the Object Description Language
Type Library Attribute Descriptions
Understanding COM Apartments

Re: Writing COM Server DLLs (64bit, 32bit, Windows)

Posted: Fri Feb 03, 2012 10:06 am
by DarkDragon
Here are the files I used (I hope they are all included). To extract the zip file from this source, just run the program:

Code: Select all

Define Filename.s = SaveFileRequester("Save zip file", "COMServerTutorial.zip", "ZIP|*.zip|All files|*.*", 0)

If Filename <> ""
  If SelectedFilePattern() = 0 And LCase(Right(Filename, 4)) <> ".zip"
    Filename + ".zip"
  EndIf
  
  If CreateFile(0, Filename)
    WriteData(0, ?COMServer, ?COMServerEnd - ?COMServer)
    CloseFile(0)
  EndIf
EndIf

End

DataSection
  COMServer:
  Data.q $0000001404034B50,$7CC740307E130008,$04E6000002508981,$794D0000000F0000,$73616C4374736554
  Data.q $4D94AD6C64692E73,$F258CF861040DA6F,$B180C2A14391187F,$34A45A638C9C9031,$C782D08407A87C87
  Data.q $B4A4EBBB5B59ADB0,$A8A38938D8EF7FC9,$7A3BB43F92C52B6A,$2A59F7CD7D9999E7,$774BA4A3C6533435
  Data.q $B6A6E2D3F834CCF3,$C651A1701EBD1A68,$69926126E110836C,$CF23469858D30A9E,$993B91C34672D479
  Data.q $73D72C082F73AD8D,$0FEFD5BEBB6A6B6C,$DD899C8F646CEE06,$C9694C930EF450EE,$04EB602B9CD5B6C5
  Data.q $C503021DD8A0A741,$B42516DB32A302B7,$F5B4D7358DA1E504,$306B2C69B6CDDB13,$98483A541B872FF3
  Data.q $A45DF15BF30A7052,$3BD6A226517E02F7,$2E42247948F6C104,$35CEB03BA131F58E,$8F0DC32A08F70530
  Data.q $15EEA2DB34C9900F,$5F509F0A2FD72CEF,$457F3F5CF135FBE6,$25C2408341F12A29,$8C28F7055FC15DFE
  Data.q $C272A4BA3FE630D4,$5F56C28BCC5A6A63,$2B2F0F0F0B9E97E7,$48A2B5773C8FB62B,$0AE9B7A9D1054580
  Data.q $EFA653563A852E75,$DF5E157CF84BDB36,$7348B5A891C0DC5E,$2484B258EFA891DD,$84134DB1F1F2DB15
  Data.q $D426D2BD85545AF2,$1AF42C1351730ABF,$E91A60577C289827,$1E2229055492A17B,$5AF84E19D3E3C69B
  Data.q $EB39AB827B787932,$EE3D3A3C41CF8643,$7A4D5249E7B909D0,$7348423C502515C7,$274C0B27C2349B09
  Data.q $41FA9AC0C3F03B63,$A1C3A6B03471B968,$CEC6CFEFD0F67963,$152081637B3FBCE0,$8CB3720ED420919A
  Data.q $FB7765B088A943BA,$EECA96FB3D8E206D,$CB542FF582548B9E,$1A6D7C17DA6A5AE7,$A3755E6BA5363B95
  Data.q $FBE260F472A3B451,$A3921ED09CB7DB8E,$47B2C8E17B1ACC27,$DD083041FB9DE841,$AD723F753D55F412
  Data.q $0FFD647DE94F8930,$A6AF91C45496378F,$61E641637A05EB48,$5FA62827F4FFA279,$034B5037ECF1FD4C
  Data.q $0700080000001404,$CE73709504402D7C,$15000007A4000002,$7369676552000000,$65534D4F43726574
  Data.q $6962702E72657672,$7D1030E26EDB55BD,$6E82B4A9461FE247,$09A2B422DA8BAE1B,$9157696809B9516D
  Data.q $DB23B05592064990,$0A01DAFBFED5A2E1,$66510F3150FB49BD,$E1549E3C66739F1C,$EA14E1554E9688F4
  Data.q $09B34382BF19F4B1,$BE10C24E6B84300D,$AF3948D1A37CB6CA,$B96E5CABA3297CF9,$8C4D423C4E139A5C
  Data.q $6CF96DBFFCA31F73,$40B38FAF86F9AE14,$CB167028C0644E48,$047D20E32980A280,$13FC817C8106DBAB
  Data.q $A74B4477C36D8FE4,$C3D8C37526A7A9D2,$CDAD79B63044209B,$3672985500181268,$11109C73146EAC3F
  Data.q $84E7C866E794E6B8,$2C548B252E0116E6,$5937C5DAD39FA3F2,$16E8B7F9F32F942B,$D9AF02452A1242A3
  Data.q $A0784C29E8B99C7B,$605D5551DE46E13C,$FB79B69A0D6AD4E6,$B1F25254E9B3B4D0,$9028F5C7BC4A218D
  Data.q $727324F1070C3D7E,$BD56BAB71E78DF77,$71A766BBADD76E35,$FBD51C337BA0C606,$049C2810890AC70D
  Data.q $B3F47F183BE031CD,$65BE8D6386766FD7,$506AE286BFA5EACA,$254FFD916BD745EF,$A06714D1CC87419E
  Data.q $929C93F922453553,$F4A49247164A5DB5,$D7B51B3ABF18C248,$76E37E93833B48D8,$3A7EB30E3D95F83C
  Data.q $50AB920DDAA91A4D,$3357BD02E8D56E2A,$EF655F431D4C7940,$523A861E66D67405,$1438D2A47397088F
  Data.q $9862CCF0AA17B6F7,$B0648323552C3593,$09024E2A5020623B,$330A1A80A6A5AB76,$33F4531D652AC55F
  Data.q $27342EC5A6A0E64E,$3E8731A986A6AFAE,$7DD0AD6103D35472,$7427D72B8C8D40B2,$3FC6AA580DECFB86
  Data.q $B152E52B2D88C6A8,$9CB89B53EE4892A3,$FCEEC4292669B4BD,$F68A46DE83583B93,$6C3823BBB2678AA8
  Data.q $F7E048A5371B77D4,$5DFB1BECCEFEFB3C,$1AF757F70E96EFD3,$DDA6FC4A403BDAB3,$5592D0ABA7A46E80
  Data.q $C959B281D0F5AFF1,$9C052D8F50146643,$2E62B7BE4E52AAC3,$06B913241131EF18,$B19F50B0DF0E9285
  Data.q $E21264A0DBB5CFF2,$4D01E6F75EFF6F53,$B1F521D4B1BA15DC,$6172A1668B2E14E3,$5079C17C8598A8FE
  Data.q $DB63DA9F9B385CD3,$7B4E114EEB1B99B1,$551CAD84D167360D,$B465D358AAE8DFD7,$4F37676B242D1AAB
  Data.q $4B507FC2B89AD977,$0008000000140403,$7A1A248840307ED0,$00000CE400000560,$6967655200000012
  Data.q $6570795472657473,$569562702E62694C,$523FFF1046DA8F7B,$F71A90293B88C3BE,$98785535CD723B80
  Data.q $2BAA3491E25E3A0B,$B64F76627017B16B,$D7ACCEF77EAA8709,$67766B48A95A18C6,$733F1D9DCF3B7E67
  Data.q $5E572F01922291D1,$4250DCC86AFD7ABF,$E8B8F39647F5EAD7,$060406E5B623CB77,$7FF12C06EA386BEC
  Data.q $70EE38B71C0DFF49,$00288F71C3BC7134,$24D44800B25C818F,$3165DD8220D1A210,$AC4270403EFE01AB
  Data.q $D4D0DA84ED7DC427,$913F9B8FF6F509FA,$F22D4535A815ACBA,$F51436A051B515D6,$F502BBD455BD40B6
  Data.q $DF51536A059B514E,$2BF5FEF514EFA815,$EC4B58E49FCA784B,$C03C052FB1643CB6,$B97E523FA9ECEBEC
  Data.q $F335AA3FA5F3B9C2,$FC9D5B0D5B3D46AB,$BE08F0E70156F34E,$7BB41F30E0BE57CB,$57F00F6888CDC07E
  Data.q $AA7565A75AFB97FB,$7ABCAEDEAAC756ED,$776B36A8D7777DB5,$E9BDDEA37DDE9BAD,$EDFA0F78B9D28DFD
  Data.q $3B8A3CE61E19D77E,$E30897AE03228B01,$D70E98B994D2EE32,$261DF5FD8C2B4504,$159F863346B375C2
  Data.q $1E555A3DD5227B8E,$6162A33EDC8E9748,$9D2E93B69357057F,$974432451E5D2849,$ABD0C85E76B646D1
  Data.q $CE47116768EA62F1,$9ACA7296A454DA07,$8882B38F1D2CB071,$A34A32F8F90A2BFF,$2876457F5E11C45E
  Data.q $7CA61F4DC85DBCFD,$3E6787E70F3147ED,$91F29412026597F0,$0F731BB98D64022A,$C4A427AFB30E6ADE
  Data.q $216014B605041768,$A4082B54A47A577C,$CA1E195BE43E62CB,$F9887DBAC5F438B3,$9F848EC9BC758B80
  Data.q $574B50B9432504A0,$54620BB4794C4A0A,$28A497E531EECF1B,$51DBFAFF27672431,$645CACF9DF910441
  Data.q $9E9DAD5018252032,$E6481FC45F25C89D,$07531F380B9DD369,$092253F19C745455,$008707E6FE7B2958
  Data.q $030301C37886D001,$10EA10922030442B,$1CA9F7FB90831F80,$C667AB9E0E88599E,$E4E9D9EC6246B999
  Data.q $03448972A3C45F3E,$C8573D2973B45B8C,$1CAA599EE70EC87D,$F1DC3CD613471265,$9416E29F8F696E94
  Data.q $F13A70F2CD431584,$6701E53D816A4592,$CE7229D88BB2BA91,$85EDF2661CD445E5,$11C8946BA2B0CD3C
  Data.q $BB90B818C91F453F,$90CEC1304AB606F5,$2EF1E532A525EA75,$4EB6CAF2EA2FDA14,$F16F5258A2160A4A
  Data.q $7D90C0621EAAEFD3,$52682F89C7B9A193,$2D3968E6267BD9D1,$D1E8D683CA3005A2,$65C035B4F98B5919
  Data.q $B3DC42FEC4285AEE,$CD8D17C085C4EFB0,$F1A67B0249705F62,$3D16BD74C0CE8869,$D8626F149E01D547
  Data.q $6754CEA7A7C31133,$835BD0620C19D265,$535A5FE6F71B3DA1,$A817C08F1C9756CB,$57887E792974F303
  Data.q $9AC4C37700713005,$12D4632C4E8AA647,$EFA18783FC79D41C,$943F13D5F37209F1,$C47FE8037D31F837
  Data.q $897FF6E8168FA6F7,$EF2D3264C22F31DF,$A6060D2FB1F67B07,$BE31A21808E6364F,$FBA554C3215DD057
  Data.q $D31E5294060E25A6,$8C4E44E620F2020B,$71E47BC415517A3C,$82273955F25C276F,$BA04EB3B08249798
  Data.q $5CF61E1313F922E3,$BE5F048EA1892EA5,$E98B3A757D64F4FA,$E29ACCC59DCD1AD4,$8FED6F01062A5755
  Data.q $C535533841254819,$C74CE66B3366B41A,$C63465297901B9E3,$6387E184EDB21D6A,$4AEF3F4BAB299572
  Data.q $263D9761580782E4,$DD179E5D7512362F,$C86FDFBC004F0BC7,$E303B3E368137D7A,$102A39A4EE25198D
  Data.q $7E93949F7A5EF597,$0B1937AFEA764BA4,$BB253AEA1509E089,$212DCD47BA541594,$0EC7F8DD03D3149F
  Data.q $27E23AAE52437AA0,$E78F9FB6E9E29D46,$4FDC7DEC1E685E03,$65497560A45D014B,$2D692944FFFEF165
  Data.q $B3C62B88C813A24A,$9E89A67155F215D0,$85AEFD00FC2A3BDB,$9DE09FAE4BA940F5,$BCD9ADC2EF9166D0
  Data.q $411F72785F17F281,$85EB7E215521F015,$E193DE032D98BBBB,$EDDA7F4FD2875196,$ABE4644D757C42EC
  Data.q $27B913AFB807EA27,$430AAA01F0DC8F03,$6DE5BCE393EFFC90,$6DDDB6CC8F0A717D,$E93AB0F3E0D6FA8D
  Data.q $858E3E1187888BD8,$7C5D2BBB43CF83CF,$86E80787B2388ABB,$37CF8C6C5F2979F2,$B5C8295DF7647974
  Data.q $43C670F19DD83B01,$FE6C0618DA26505C,$FFB34FD614497F26,$4B5007F959BEFDB6,$0008000000140403
  Data.q $36A96AA13F218348,$0000435800000989,$696765520000000C,$6962702E79727473,$FE1248DA736D5CED
  Data.q $C15DCC2987FCAA9E,$38E376E76BC1665A,$E4938182A1C2C631,$51830C952AE57B38,$DDBAEC6C48D44859
  Data.q $1A2F347AE43F7B7F,$5558D9C10DB06109,$FDD3D33F74BCD1B6,$BDBAB1D83E484B74,$C63C60A7D00EAFD7
  Data.q $C0C8B78F4410E47E,$8E47F500FE3900CE,$ED76D0C234518D7F,$EBA6A33F43B91186,$3089D77D06187AE1
  Data.q $8E4D80A3469F5F9D,$A7D5F07E37FB9FE7,$788F882007EE265D,$688C30613B37C68B,$684B325176CC09D7
  Data.q $9319FFDA5CAE4CA8,$6B54AB5FD97C0DD0,$122F3D8461275DB4,$F8A7CDA07C3E1FED,$B5FB5CD91300FE7F
  Data.q $D17FD5AB7655AB52,$4E8013C608D3FA5E,$ADA26808C300C1C6,$6F840AFD78E7AD3F,$859EED1BB6ED8EF5
  Data.q $FBA8DC49828C28D7,$F6E789DBF58795CE,$2F5388275A6E28DD,$8603B6DD6A3C72B8,$867CDB2F15202423
  Data.q $70ED7095C6B9D0C3,$5D0F04E886B426C4,$011D8C80CD4A0F1F,$F1F4123D68D44341,$A6ADA21D19704A60
  Data.q $D91FD10868E085E3,$6BA749666A510955,$A658561857C74CEB,$23F708F8C027A8CA,$4C43874F1D3F403C
  Data.q $538704435F61E434,$E86FD8A3A62BA22F,$D9AB6976A9297D00,$669BA67D96EACE35,$51B776EDEBB754FD
  Data.q $8DD4D9BCF8FB74B7,$9B667BA34DFDB33F,$053555A67E969BBF,$5AAD550C091D9C14,$467D96A010C13A66
  Data.q $96637C61E880151C,$B8C596ED0768C854,$8F80C126BC77D076,$A68E0640D25D918F,$990DCEAF5922E7C4
  Data.q $BC7043ED4310AE37,$D55BE23E8DB40545,$C4C35A0FEEBE5CA4,$87CBDBA8E52A7066,$B6C7EA6AA499D9AD
  Data.q $8825C5378ECFA389,$EEFC21434EF84FB4,$89771CF814F06338,$EEB3C9FA33E23FB3,$83A214F71474E026
  Data.q $DCC16C0A17FB000D,$83C562408D0BB8E5,$967251A18F032359,$5CC194746A471E97,$4A9CF9804DE7D32C
  Data.q $BB657F37FDDDDFF8,$7A20C155277157FA,$F8023BC6A479EFC2,$51878DA7FC1DA2AA,$85341A3543562C49
  Data.q $C3068468A09002CB,$6797D8DAA3A91EBD,$5DD936F5982DF065,$C8CE1F2B50999A90,$6C72B552285E28CC
  Data.q $EBE1F146A448E663,$67B5BF5D30FB04EE,$FA4F8660554350B6,$C101A37AECFC34EF,$253EF11FBA23A1A6
  Data.q $AB07DF0235842D8E,$090D72AA4BB21D8A,$2412C24CADD94705,$1AE8C374B68F7BBD,$D993C114EB1E79B6
  Data.q $B2C8F67074CB520D,$C2136237379D4949,$1FE0B2998E5BC54B,$3C2C4D6F97213060,$7F777BA127C2AD6F
  Data.q $D8B2D303D899B59F,$865B462138688B11,$66096D11FF9B6A7E,$0CACED88F4149B11,$362C8804CD950648
  Data.q $5AA36065CFB13799,$4938D745C9D15679,$CC57F07D0188B174,$0E0EF53458922C7C,$4BD578B63FA12F66
  Data.q $8B6ED3FC78870DF2,$2752BC0C2A7EC54C,$8E76A24F79E5944A,$2A729851CCAB87D2,$4C6C0AB600BCB828
  Data.q $86653873D248694F,$CC5F731B9883AB2F,$DA8DC8089844B57A,$BE0D3219506CFA94,$414926DF5ACD957E
  Data.q $B534F974EA69A15E,$47D5920121A4ACA9,$55352EB1F21A30CA,$255F3FB990E373C5,$523EFF2DF3FB2552
  Data.q $634A96C692FB1718,$FF24098532CF2EC2,$E238427F7772629E,$1303F8F3F311E235,$2C97902CBCF23298
  Data.q $FDC762E2D5CBA5E7,$908404530221D8E8,$A87A6024A3B72D28,$343E78D884466C69,$594FDF4DCC7A7ED9
  Data.q $911980302BD74CBB,$0D94CECB25752292,$73F5590E95E5318B,$4884A73BE171F783,$E4857DA2400284AD
  Data.q $C2249739E53ABEB1,$4036928B46FF5877,$A4B2DC90B057A736,$2F847ABCEDF00FE5,$918BC0D308C5A56D
  Data.q $0F1EF102394CDC04,$105C1FA88C30119D,$B6AD9A030B96C237,$E57917B174CEB56E,$16A5E45A97EBDF09
  Data.q $16A66AF7C22D6B59,$8F49612398E9FDD1,$24DF9E078B11DD87,$AA5F5F5984CF2A9C,$B64CFAC92A63512A
  Data.q $19AC975D79C822D0,$65159B64A47B330C,$004892739F3A3983,$C45388924CDDA653,$2BA5EA7E11301409
  Data.q $6FE0828592A3E25F,$A5F2217D8B945F74,$155A151BDD59FC88,$52C384947DD414C7,$6186E6DF4088AC7C
  Data.q $E026AB86BBBCE346,$D9982B07339F6A79,$A227608370D20D90,$80F768FBE125C90B,$75E861BBEAECDB57
  Data.q $A10D85FA3BB13F4B,$BD3DBA83B36B4300,$756AD32D2FF46303,$228F4EC55DC0F94E,$FDC4DDBAD986B972
  Data.q $EE2228F577321429,$DCE37A98AC252C15,$8EB46596AD105968,$F2107E0014DD2DCF,$8B7BE2FF4B9AF697
  Data.q $7E07763B756ACF6E,$F27AAE0B75DB773E,$8FE1019CCECF2EA8,$17A1948FA5C3F754,$7404D97C9A759024
  Data.q $A673F49115A0DE90,$863F0D5167A86962,$570FE3529A4B1F86,$652477E42795CAFB,$318A514FEFE023A6
  Data.q $44696596632A0966,$D5351899E94A44CA,$499FACDD275BA0AD,$AF9BE924C736AAE4,$34FAFDBDEFAD2FF3
  Data.q $846FFCD80DC87956,$C32FB95CBEC16E5F,$FC75D4D82DCDDF6B,$B82EEB29AB60B732,$C6FA89959EF99AE3
  Data.q $92F9AC610FB35C77,$90AA665CE7D68E7F,$888271114A9B8163,$9F362A0F85100363,$7CDAAE1FCAA41794
  Data.q $D9CB6FD0EAA5EBE1,$AA32BA856E511DD2,$C44A4DEE2EF9E94A,$17D4164A5906C06C,$88A7F01E7BAA346E
  Data.q $86852B65EEAE8520,$2C3C538B4A3C465C,$781B864C55743414,$D0F155CD50F91D82,$D83EE46D18138A29
  Data.q $DE28D509AAB37D20,$9E19EA7DEEF8A71E,$14EDB4AC0DB51725,$EB91FB9CBC496955,$83BDEF71B61C3051
  Data.q $4EF29DBA37979934,$17D4C9D944BAEA4B,$DCD660F60A8DF27E,$EACC92D99E494E5D,$C87A2F391BBBACD1
  Data.q $59F229FC6243CAE9,$BE8E677CAA339B34,$BF5B4DEA96DFA740,$0E01EC8DBE1A8A8D,$B517E06E449DC4FB
  Data.q $35171E3389AE0909,$515DF06FAFCECFB7,$F681B481E9078FEB,$BB443516741006E4,$D29118D876DA5E93
  Data.q $B45B66A96DE57B2F,$3C9A8FFCF9215014,$D89607D08442E789,$8A89FE8CA976795B,$D70BBB600E1566CD
  Data.q $FE7EB1D4435F041F,$1F5B45E3905113D2,$9BA9A6EBB4683269,$27D42A1A5AEDD1B6,$508429AE87385DF4
  Data.q $F3D8470AB085CBE2,$E307EAE870BB25A0,$BC5A75100A0FE3B1,$B6B3A63A4102F152,$1EF90F15301BA255
  Data.q $10F6051A676C176C,$9080570B00CB2676,$1C9428B9B614A856,$9C3CA134A2D51B14,$B8CCB5C71594500F
  Data.q $4A51EC483016BE50,$13F760CD63BAB2D3,$B13102D45EA6743C,$4ACD7C9A2A7963ED,$30DCFDAF99399101
  Data.q $15A1BA9B9F658EF4,$3CBE08757D1860CC,$725E90EFA024FB73,$F0BEC1094C6CBB9F,$B930406566FA4BCC
  Data.q $68E6C99785166164,$C73165606415AFAA,$5DBB7FA7C2074117,$EACFB6D811BE9588,$C244B74E8EAD8F8D
  Data.q $CA031562184E786D,$C1EDA49A3929A83B,$E832741CBE1CBD2E,$D5DA95FEF2D0B8B2,$09FB8CB83A7B4F1C
  Data.q $51965C1660B8CB70,$2AC46ABA5C17BDDE,$E661EB08C6CEC587,$6587DDE3AE490E5C,$6933943638E51E19
  Data.q $2653A953B607FC35,$7BCE97ECDCB0BE4E,$330E5FB5795DCB8F,$CA2CDE66EA5FC9CE,$E2A259D2A7510F35
  Data.q $0B5D4C16E8B21201,$F62D21F3B4C12F0F,$267EA8E968D8C7FA,$8649AA8B141F91B1,$D29D118428B5D1FC
  Data.q $10AD657D92544873,$25333FE2082D304C,$9B35DCC0211FE676,$D78DD4744EB500E9,$09D8E3007A3EAF40
  Data.q $63A2A9BCABDA3EDD,$B77E125417E8391C,$DAAE172AD0DF6E83,$3A5D082F480C24A7,$A6F6D3EDEFEE6615
  Data.q $C226F4FAEDA8C24B,$7037814DC5BFAFDE,$FF89D9D9D8686BFD,$FEF4BE1D8FFC4531,$00001404034B500F
  Data.q $81402A80C5000800,$CA000001761BAE43,$5200000011000003,$4332337276536765,$62702E72656C6C61
  Data.q $861040C24F4D92BD,$C6D0F14987FC24EF,$2147C26A0B840A8A,$59A481E220A84C4D,$16EEC977693601DB
  Data.q $D370A2940BBBDFE1,$3799F799D9D99B78,$82B83DB9FF4A82D3,$336E48A972ACB047,$086539C3D4B979D0
  Data.q $2A3DC609248A933E,$1B7F52AB6C5C5230,$3B2844065A880AA0,$3209A7DA48217C10,$C39FDFA638EDA292
  Data.q $C2E09F3ECA962E88,$12B4CD604F0F03BD,$B163CD7DEB80905C,$16BC62E119813F3F,$CE0A9AD8F0873846
  Data.q $123E4A088DEA6452,$9C474C2A56F1ADB4,$A103FFD14A3BEB2B,$9BD2BA7977499C28,$0D3CC27412A43D09
  Data.q $310685C94A11D6F5,$CCDD8D9A6E1E6385,$99B5EA89C99C1D8C,$1B8AAD7A8B5C85C0,$1E4B4B04B6ED5CB4
  Data.q $F57C3265EF41D7EC,$B86CE23F16D9784C,$938D51B36D909146,$4CDD258D72E93AC4,$1CDC76CBB1C76D08
  Data.q $017395425384C0D0,$A80A7F1B369C3A70,$244BDA773002FCA7,$9C3FBB847F9F8BFE,$39452B860F3DF816
  Data.q $D2443B02641AB733,$CA53D81DE6D51A08,$38B9F406E129FE62,$4507BEF5CCC7BFE6,$A306E976CA538EDC
  Data.q $D2F4C2693D27994C,$4B500BFB587FEF54,$0008000000140403,$DB06AA0A40434E53,$000002ED000001C5
  Data.q $7473655400000008,$6EDD91957070632E,$77E4B1AF8510409B,$C4FF120B02B51118,$2848EC6C91D6EA51
  Data.q $1656D17B75D91C6E,$897768BB048CC186,$24DC70177BBCAB45,$CCE1CCE6F99BB977,$8BE1088B4C2C4672
  Data.q $3ADDA6E4F3F11154,$E06FC6116790B13B,$5BB69AC83F11620F,$7181030843B01717,$08C43005E4A08E91
  Data.q $2C0825414D30D714,$0523B9757088F450,$AB8C580514A733DA,$0EDB89E52E0A1C7A,$1FD6822481C54D70
  Data.q $D4ADBAE70984BB48,$89524F7022E57E83,$24EBCF2841299012,$D17396502CD9212A,$AB9A7694C732ABD8
  Data.q $21D26290C73206A4,$6A6C46B4EAA2828B,$379EEBA7E9A34515,$CBDDCDE274EE7B99,$5EE070E1D3BBEA38
  Data.q $3FA0F5EDEE9386F5,$EDA30CA6FA9ADEEB,$32B55B7C60481B5E,$2C829884DEAC420F,$A3A1F62045556620
  Data.q $FE7F1FAAA744080F,$71E196EDBFADDBB6,$75683FA520A2919F,$BF2D7FE1A6D5CFED,$A501D9481A5E54A1
  Data.q $1813DC796C5386CB,$F2D10B015499F428,$C0E0B17DB67F6B16,$AF80E7A070B166FD,$BEF878B591ABFE27
  Data.q $36B6563E1B1D67F4,$1A74EF2EDEB0C78C,$2D8DC742E4638AA3,$2738C7998BF77973,$10F823143B645F78
  Data.q $F81A6F730753A1E9,$7DEF6E0C60C97D2C,$ABF1FFAA6013C616,$31C63AB96AD5F32C,$7FFD186F8F3F6A9E
  Data.q $9666152965D7E3B8,$05E9CFE7ACD930F9,$FDDEAEEAE83042AA,$00001404034B5007,$4F40307729000800
  Data.q $FB000008BF796F45,$430000000C000027,$7265767265534D4F,$DB6FED5ACD62702E,$9103FF201EFF1A36
  Data.q $CBD6C9A9E73B387E,$6303B1D7377AF10E,$040A03D34EC59D89,$A923D264DCC7448A,$28922F87BF5FDE38
  Data.q $5B454E9AF4E39699,$BB23DF97F79F228B,$A36BDFDAF15F0E8D,$E453F18CE549D443,$781F41382521675E
  Data.q $B77E5975FFE82498,$729337E65370B7B7,$EE0CB972EDF6FA71,$3F5BE9C034871879,$511619DF965FE795
  Data.q $90AF988F41D7E150,$897477518245F320,$89489C9684B0E604,$087F1CA55D142229,$BF0CBB5F90368905
  Data.q $347AF7F6F7F6BC57,$88909169EF704FBC,$8D24A34069F2B548,$85465D076A809F71,$541C9EE2C114A90C
  Data.q $60E6242207E35E9F,$77BFB5DD8036B181,$7249674130FBB09E,$6A241952965DA78D,$BFA1BC1E5435B5FD
  Data.q $D7E5FFECDBA4B653,$61A6038280E0F137,$87BFBA6ACAE5D184,$482CFE684429AFD0,$CE0C1838909C871A
  Data.q $B3D40C78B170E85A,$C18E27736A9BCC07,$8704E35DDF49B04D,$8A2A738D1EDB9B02,$68DB109234F258DD
  Data.q $A1513FB1F877E25C,$C7314CC867751014,$5C7E5681FBB9C234,$04DC31C22CE2BAD1,$2871A6119DFC2149
  Data.q $5E9A2D1305044467,$338E89FE8CA65CFC,$77A84C0C6BC5399E,$6B0E59B8DF2396BF,$306410AEF9041D86
  Data.q $CF523A3DE9F96FF5,$8F6788C339236A11,$25022109439EA451,$148FF847181F096C,$86090B59CC4FE892
  Data.q $7622E8A462489062,$FE65A1A9E48E1BFF,$95F19CF12F8C73ED,$B8FFD34975B3F991,$39E388F1036D9EE9
  Data.q $35EE14315C951906,$339533A927372CD9,$C0897B5D6BFB5532,$BA0809C0F77EC7FE,$7735F48E54FD73E9
  Data.q $4CF85ABE44D7B841,$E649269866F47BD0,$848A43A505BA36BD,$4197655A5A10DA24,$53EE85B0C6484C56
  Data.q $592D0AF167BB2889,$79C1C056AB08C49A,$1983F552866B2858,$8BE6CBA3436A78E8,$CFD0B5F250DEE790
  Data.q $FE4C7A9720DDE120,$53D69B160369A3C4,$4442F7B2C55AACB9,$89C7A214D8F1D2F1,$0AAB63DC7A54B413
  Data.q $A30295D27F39CD8E,$8E2FD1BBE337B2EA,$EFD777A6F779FC8F,$51F5DAF85DD62E0C,$DDD26A837289FFD5
  Data.q $D79BEBBD7D021424,$3004F7B251A9A57F,$30E58E709EE51624,$3F6076869B43DF9D,$640FDB9E7630C9B9
  Data.q $190BEE5967580B5B,$67CFE3A73FD56D9D,$4048509A12CBC367,$D2EA2A0C322A0522,$DDDCAD26E09E79A4
  Data.q $5533448CE58D86AE,$E9BC15CC96614DA1,$82FB215CF8130C52,$9464A6735E2347C4,$BA87B56EA105EADD
  Data.q $D995D59EDE456411,$129596105BAF8556,$B677D53620C4754B,$280984922508357E,$CD98D21E2050A319
  Data.q $2AA8C0277558E2C1,$0795614D810A98B0,$83A4F290DC21D17F,$F5782CD9F84C2B5D,$A372C09DA0D85633
  Data.q $24EC4AD71E259B6A,$ED0FDAD207892A28,$6DDCE9665A30632A,$6576E63968A3693B,$3E1326C5BBD92527
  Data.q $6575BDE0B68251B0,$C6A1459179852C8A,$875CD021FE7D9938,$6CFBB1D82827AE7E,$B0249A6977D8D852
  Data.q $AC5FE41B4024E769,$4D08F054A9C7FD34,$7C004A13D01B9B39,$D4616059BA8C2491,$981360FC3AFFDB3A
  Data.q $2E432C716550F00B,$DEA8FFB38175026D,$A56D49556BF32AD5,$94CEB5C2C79D0AEF,$45967DA75351F1C6
  Data.q $00272521F1670B65,$52B0D0B0B15D7067,$416D790168505C30,$C7E1819EFEA25DC8,$3669F05A3A3DE1AE
  Data.q $AA9433D35CFDB443,$FAE98C712718400C,$9B6AE2A269EA0AC1,$3E6CE1FF30F52870,$CD47ABEC3F6F4E70
  Data.q $7E3E3A6C5E52E1CA,$29BEB53A18B5F1EE,$ED934CD380EFFD19,$BEBC57D0AC68AA87,$A17A8A669AD34E39
  Data.q $F2FD0333A863975A,$D4823A780BEF8CC5,$4582E6C9ACF51E84,$EEAA63493297DBBF,$E2E5CAF3981B6482
  Data.q $E304DF1EE70C7AB9,$5F9CCAE48BAF3DDC,$5ED606EFB855AA19,$8209AB841ABDDC36,$DB435D820A6F1872
  Data.q $19EAA54102C612C1,$7C353D0159A04FD7,$6F6454844A000C67,$EA4514C33B740304,$4F3A3A98A8591618
  Data.q $17D07CDDDBD44913,$CFE836607A16432D,$231DAA6487E847C2,$94692C092849FEC1,$B5FD6F5064557500
  Data.q $09102EC624127C01,$3C35DE34A90FFD0C,$4971950D8821AFC0,$1D07D08652FAACE4,$86EFD805AA962BCB
  Data.q $AA01520210000873,$04D264EC75ACD305,$53FE9FA0070BD436,$F19D17BA04279BA4,$CFCE751C3777AEF8
  Data.q $5C3460C99DE77BAF,$233036E57A631C8B,$388E8023C2A0DECC,$DDE9F2D7DE0F0767,$43DAEF49C3068D5D
  Data.q $659A315C3694C4DB,$F16A0C0121651A58,$E8CA2F59DF2392A8,$D7472EF65FEA3266,$90A223805388F3FF
  Data.q $343CA52659191554,$BEFD30666E301D07,$07AE792313DA8208,$A9AE4B5478CCCCBE,$68B6B29DCDDCCA3F
  Data.q $835E2768B6321B1D,$49DD7AAE9F7B0CDD,$E054A24CA4D40CEF,$CF25AE513CC17838,$74BFA58E03DC2918
  Data.q $B2E160D2BEC970AA,$E178F37D657FB174,$5328C05E309BE8DB,$B3632BD2E0173BD8,$48A11376D070DB75
  Data.q $B19EC89F06675DE5,$9E80E4C17CA60EA1,$AF9D6787866BFF83,$639B8212F64AAEEB,$37B24E2216F16339
  Data.q $6FE5A2F8891B10AD,$4A7EA05C5D9C4E3B,$C64DF5E2BF88D323,$61948ECD4ABCDC89,$6880B234424BD334
  Data.q $8D9030F020D4B92A,$28A086BA839ED283,$52B67B4B14EDE19E,$56B8D9883327FC34,$96BDC33D2B65B344
  Data.q $0D1FF6CF47C5BB9E,$A5539523DC36A620,$4C364DFD02CC044E,$7B4140BA47FC3AEC,$AC62F741CF68128D
  Data.q $94AADFD5808EEA51,$05C8D5B066224B40,$C2FCA4CD5075498D,$0FFFD32C397980B7,$0F9DEA0047CE9347
  Data.q $65428A86A6DB3D17,$6CA1E274C3C2D136,$A11B27CD927E9F1B,$155A3BBAA56797A0,$EA25AA83868326E0
  Data.q $6DB5125520EF2F87,$83AF9B6BBDD7889C,$5F72FBCD4611EB10,$8B5AC482BD61F39B,$8F9E3DB951620C03
  Data.q $C6AD91C2FC0B4580,$D21BBDE265C97549,$51A5B21E30B09A1B,$0D4C88564D237A06,$040AFA16939C8524
  Data.q $CB31010191400386,$A4763D2B7C951786,$2A2EC9D62C4C189A,$1863A6A17F17BE28,$C230D4BD1EC62F4E
  Data.q $0EDE69A192C30404,$15EAAB142E8CB820,$2101683FB7222372,$3D713507D2CE1541,$527E01F7C3FE4788
  Data.q $4C15FB29DBAEE05F,$97C35AD97C9545D6,$F2E94B41DDCE075F,$E70D0D49FAB9C3C0,$CBDEFA5A359BC7D0
  Data.q $62A847B943748BAF,$7068DB4C6ED623D5,$E77BE6B185A343D6,$B8D4239382EF4ED7,$E9F250014B663425
  Data.q $A51C27BDCAAE9DE4,$FD2A879F19F7171A,$1B55E4AC437033C6,$1441315F8C1729BA,$EF5AA3FC7C7C7851
  Data.q $6259D8A105E42E13,$4D2E0EF858238A89,$FEE2FA94C98EFF5D,$3DF5C81C339955D3,$B01B143196C41779
  Data.q $0D5A27DFE357AF3D,$72900B988FA7FBFB,$C13EDBDAAD4CA740,$CFEA5A8E74047C49,$C03F47E6F1D1F571
  Data.q $1256F023428C01A3,$235F94A5FF8FAAAE,$EFC0EEC280AB0277,$001404034B50017F,$402D5A8900080000
  Data.q $00000344AE366C2E,$000000100000090E,$43747365544D4F43,$62702E746E65696C,$FE1038E26F6D55BD
  Data.q $8E007CB1187FC48E,$4B6A7AE5F40204A6,$F55BB5E96DB46ED8,$9EF149927213DBA4,$67F5FDDA39DB20EB
  Data.q $A749ED3B810D293B,$32679E3C79EC725A,$5EAD8EF3A18FB19E,$8A916A659C0E863B,$CE0C8A709F372823
  Data.q $3DF056AFFE0C6105,$D4A16F9361683C3C,$A1395AB57F7F68F2,$ADBBFB660EE13120,$5391947CF82B78FC
  Data.q $610C969F49033BE1,$1FEAE4518882BB32,$AB63BDF39687FC8C,$28AA701A49B5EAD7,$C1B6BD5BCE3BF461
  Data.q $A0C62380CD25E18E,$108909142B940816,$BD51F94ED1A84C62,$27FE7B97ABE1AC16,$4335F8035EBC574F
  Data.q $2823AB58735EB2F1,$2E59D0BBF0209D8D,$51B68A23DACC72FF,$9592B44C5BE38B3E,$1E538B989121916E
  Data.q $505F74CAA718ADAF,$2159F4C2522309AA,$B3AEA8170BA6E58F,$D665662F618510A7,$8F183BA1317AD2BB
  Data.q $2F81F717023CF081,$E9FC1489122BB5EB,$9AEB58373A7AE0C7,$EEAE56175817613C,$D038CD0C7A842EFD
  Data.q $B1F748FBA87DD3DD,$6121A582FD9607EE,$374CC188C63AB660,$38649AE2289F57C0,$6EE57073F601B601
  Data.q $EFDEA06FED0283A0,$B5D415BA1A343FBD,$1D0541D16FB75568,$1587459EA0ABD458,$74591D0551D16874
  Data.q $B6D1B03D16C7415C,$62C669172D23CCF1,$52207D6A5BC6D108,$4AE1152E524C1E67,$7F472BACEA90CB3A
  Data.q $743A52F3F8177972,$7AF032121FE839A1,$1D1BD37E8EAE8A66,$3EA26853E81C3D12,$E6B73E913E6BA686
  Data.q $566FB119121FD628,$3C7E6DB04126F6BD,$A3C69E81C9877B1C,$E69BCCFA07E6B228,$637DD432219E9BE0
  Data.q $CEB1F06C67F44BCE,$3537CB8B6BA1E686,$30DF859DD929D084,$75C3E04FAF394E52,$94C66516FD5AD8C6
  Data.q $2F9931ADE6BC06F3,$0C28902274933DEA,$623BA7D05D22CC6C,$F5BA763B41772D64,$0483AF697EDBA783
  Data.q $70CFB3E6EE1F1CD6,$E5FE7E155B632BA6,$EBE35B69BD006FD5,$B57ED8F9A75B36BA,$B1ECC30397E8F669
  Data.q $4AF2C4994C833BF8,$2076D66D79842A63,$82BACAB0DC619421,$FDAEBFCDDA7AD793,$7CFB31BA93BB9ED6
  Data.q $AE099540804376F4,$EE8F37F8D7A3426F,$85FBD2EA3F391E2A,$B71BDAE771790764,$9F80DCF7B569BBB0
  Data.q $F9D014F2B73E13E0,$7163F94CBF3E7373,$E969CF7233F92665,$CC29FC0EA29B6921,$09937D0930B9E696
  Data.q $1EA339E04692273C,$3D8495D38F281EB4,$9909927F56791E78,$196F4627DA549B8A,$4D2EA90A91FC0DF6
  Data.q $31652459EB809FD2,$9394E233DE5A8FE5,$4DF8FDCE8597E190,$04034B506FE6EDFE,$7EBA000800000014
  Data.q $03E699BD19414030,$000D00000A420000,$6174736E6F430000,$BD6962702E73746E,$5EFE1038E26F6D56
  Data.q $11ECA1F2C461FFA9,$4210FD4502424E36,$EAEAA5AAD28EE6E8,$AE34D440C499545E,$C66FDFF7568A509C
  Data.q $B4E9C777B694B761,$1E3CCF1F8F389C96,$0ED81FC7C1E9478F,$90B965FC11F07A0F,$C8A9E780DBB618EA
  Data.q $36D5FFC19678AFA0,$BFA5E3F06E6E6EFE,$5AB4FA7F1C3E5945,$C4B79E13C5535AAD,$F8DB7DFE56DBD3F2
  Data.q $8B1BF8ED6E22881B,$5E65886B57051458,$5AA514268B2F3C94,$C09E78028952E5C6,$66FD31DE283475E9
  Data.q $78707876C0FDFCAB,$9830E7FCF2E2E1F0,$C19451136A04E1D4,$F4D5428F5095D9F9,$3AC28D1874FCE8F4
  Data.q $1B504FF267813BEA,$E1F6912A7CAB79C9,$10D7E8ABBC82FFCC,$A072D331A0C5CC49,$2975D39334BBE347
  Data.q $3C6897F4F0CBB5B4,$01347AFF43841DB8,$357477C09ADCD56D,$9F189ADB04F52F09,$6322C04E9C4DC38F
  Data.q $0E3452D012563C67,$9A2F7E6347D8296F,$984D5BB0C5613590,$BD83BB1B6F4A7BE2,$0E34EF61EEC5DD8D
  Data.q $9680CF1D514E000F,$7DF809D46108C8B6,$D00BD9972ACE4BC0,$D41BDA817B15C0AA,$3A207F99BF3A817A
  Data.q $D2D72EE8D3283B65,$5076751ADA83BDA8,$7751ADB41DEDA347,$469EA0EDEA357507,$5278E89E6107873B
  Data.q $F7F90D6CF3207B60,$B94042E505499F1C,$BE0F46253A59107E,$F46061F8161DBBF6,$FD1962599C3420FD
  Data.q $61CDF6D65C36DB76,$6EE24FF0E606B6C7,$B3DB8347EA28D11F,$EA6D78178CB4CEB5,$C790D31173143453
  Data.q $5C785F4632758278,$E23465DD5D9E36F5,$F4256410EF6198F8,$B91732F26291E8D5,$3880B48B9544BC50
  Data.q $AE00B9695604D22B,$D5FC88A979B7E26F,$8761A63B6FBEBAB6,$371D1B976E386DAC,$83F03BA105E60CF4
  Data.q $183D2DBF141D0AC0,$334738668E92BD5D,$88922992E48C1434,$0F46756698175659,$4C66DA7314972BBD
  Data.q $4DA14E52A34E13BB,$D28E1EEE19A852F3,$95C726997CC06934,$18C761DD39EDAF52,$99F4666D4A8041B8
  Data.q $63D0CE5969A61BE3,$3AD7A34A3B65DD9E,$C71B8987075991B5,$77521BA5314DA75A,$F1F074B2C1ED3148
  Data.q $F1ACBB9C51EE11E1,$095C010BE758C42D,$E8D7B5E488910DCC,$AE6E6F2AE5CBBF3A,$7E7C3566B4DCDD6A
  Data.q $78DB8E1EEFF8D505,$9278C790D2DE83C3,$F43D9FF607B3E6EB,$C10A1CF310972D60,$4F8CD3C8F3098C55
  Data.q $E5C942E5E129B133,$74EDF3E69FE9417C,$8779491FBFC8AD06,$98787C9426A94353,$52A947F1982A8C92
  Data.q $D22F1E7BE98DCA4C,$4B982DE6B4590F1C,$BAB8A6BB782F4739,$A4F1A32E2ED45CF1,$5797542E822533DA
  Data.q $5552349E2CFA3CA2,$E248EDFEE41626A6,$835ACCD6D9E026DA,$55BE6BE7C351B32A,$23FCEF904AA46FF1
  Data.q $D25AAE854F93DEDF,$DE4BEFAC4B8F7AC7,$F6B7DBEFC8F7B322,$B721F67643EF6FB1,$C937BD90FBBB21F7
  Data.q $F38420D107B9E5DB,$17DE2C0F1FC53287,$D3831A45E7D1BFF8,$AE44F349BA384D72,$07767475C9E0300A
  Data.q $D6948B217548554B,$4259943C119B12E0,$6539867D06027CE9,$034B5000BF8B97FC,$7400080000001404
  Data.q $864A369B5140307E,$0C00000655000002,$7461657243000000,$B562702E424C5465,$477C1040DB4F5D54
  Data.q $6A6A383E8F6C3FE2,$0DB1122845428842,$960FA1B89B892558,$BA2EE754E05F6390,$701B67BBEFF1F33B
  Data.q $CDEC4879A90AA0C0,$C974BAEEDDECCCEC,$DEDAB637D6208538,$5F27F271875F9F72,$DF056D71D853E09B
  Data.q $ED729297276A8CE1,$32D583E42D134932,$2DA37D7653097F30,$818E8E0B5EC36DC7,$94BE13300B7B6444
  Data.q $77D38D65FD4F1ECF,$3512E20B46594E2F,$652B164ED2A9087A,$F862F0D04F2334B3,$C27778620B67540E
  Data.q $B9E3795E1799E993,$3C4438DE478C9D3F,$F18EE00C08F7EFB9,$1604840DF01B6EFD,$18006B7B67267BF7
  Data.q $CD9A36A4F87D3059,$6483E2F6A8E3219D,$15E32D71481461CE,$56FD6FFBAC0A4718,$CC352C4A14896234
  Data.q $994F3A660CE3CA99,$B44EE689DD8EBD80,$568271A9578A3C60,$B32482B8CC75C112,$172B77EC5D2D3DE9
  Data.q $A34B23C83EAFF803,$C12B562399E9678F,$74A0F839ABD77C0F,$330489A9192115C5,$A96F2A33E325C7F7
  Data.q $220DB965FB3A76EC,$E2A5661151CC7A35,$AC345EF607B7454E,$ACA97B0ADD50D555,$C6101F279F616DEF
  Data.q $584D7886E94F2CAC,$AC9FAE8A4E394624,$CCE5A32257047729,$4CB7E3CA672B5198,$C592C79AB9C2BE0A
  Data.q $AD273C24E090840B,$2D4BCD82244E5612,$DEFC101869C1F8B7,$635E474D30B7B3BC,$25A674271675D29C
  Data.q $407531B60996D7E3,$DBF3DECF6C2937CC,$D54576AF711EE42E,$6D07579CD3FFC5D1,$E7F71DFCC21BC791
  Data.q $82D5B3467DE849AF,$3BCE2EC0905AA7C0,$A5415E20B568CD90,$586F016EC34AE458,$1FDCD6C97FC8050F
  Data.q $60FBA21379BB4C35,$FD33197575555578,$7816D9705E5627AF,$3F5FEEE2916C7AF2,$F1F6CB70061B205F
  Data.q $7194E1A8AB498E4E,$BA6528A9FA686EA6,$5F3E5417AD223981,$83D8CF00E134DAE7,$B92BD34C6C335AC9
  Data.q $BF767A04B158C3A4,$CDACD5F0ECD55603,$98A103212B458F02,$6E3D84CF6E94C1C9,$014B5005FC1DFA4A
  Data.q $0800000014001402,$817CC740307E1300,$0004E60000025089,$0000000000000F00,$0000000020000100
  Data.q $736554794D000000,$692E7373616C4374,$001402014B506C64,$7C07000800000014,$02CE73709504402D
  Data.q $0015000007A40000,$0001000000000000,$0000027D00000020,$7265747369676552,$65767265534D4F43
  Data.q $014B506962702E72,$0800000014001402,$1A248840307ED000,$000CE4000005607A,$0000000000001200
  Data.q $7E00000020000100,$7369676552000005,$4C65707954726574,$014B5062702E6269,$0800000014001402
  Data.q $A96AA13F21834800,$0043580000098936,$0000000000000C00,$0E00000020000100,$736967655200000B
  Data.q $506962702E797274,$000014001402014B,$81402A80C5000800,$CA000001761BAE43,$0000000011000003
  Data.q $0000200001000000,$676552000014C100,$6C61433233727653,$4B5062702E72656C,$0000001400140201
  Data.q $AA0A40434E530008,$02ED000001C5DB06,$0000000000080000,$0000002000010000,$7473655400001666
  Data.q $02014B507070632E,$0008000000140014,$796F454F40307729,$000027FB000008BF,$000000000000000C
  Data.q $1851000000200001,$7265534D4F430000,$4B5062702E726576,$0000001400140201,$6C2E402D5A890008
  Data.q $090E00000344AE36,$0000000000100000,$0000002000010000,$544D4F430000213A,$6E65696C43747365
  Data.q $02014B5062702E74,$0008000000140014,$99BD194140307EBA,$00000A42000003E6,$000000000000000D
  Data.q $24AC000000200001,$6174736E6F430000,$506962702E73746E,$000014001402014B,$5140307E74000800
  Data.q $55000002864A369B,$000000000C000006,$0000200001000000,$657243000028BD00,$702E424C54657461
  Data.q $00000006054B5062,$00025C000A000A00,$00000000002B6D00
  COMServerEnd:
EndDataSection

Re: Writing COM Server DLLs (64bit, 32bit, Windows)

Posted: Fri Feb 03, 2012 12:25 pm
by helpy
DarkDragon wrote:Here are the files I used (I hope they are all included). To extract the zip file from this source, just run the program...
Cool 8)

Nice way to attach a file ;-)

Re: Writing COM Server DLLs (64bit, 32bit, Windows)

Posted: Fri Feb 03, 2012 6:14 pm
by luis
Thanks for the tutorial and the time you put into this !

Re: Writing COM Server DLLs (64bit, 32bit, Windows)

Posted: Fri Feb 03, 2012 7:24 pm
by Ajm
I'm not sure I really understand half of that but thanks for the time and effort in sharing it. :)

Re: Writing COM Server DLLs (64bit, 32bit, Windows)

Posted: Sun Feb 05, 2012 11:35 am
by DarkDragon
Thanks for your answers.
helpy wrote:
DarkDragon wrote:Here are the files I used (I hope they are all included). To extract the zip file from this source, just run the program...
Cool 8)

Nice way to attach a file ;-)
Hehe, yes, but it doesn't work with too large files.
luis wrote:Thanks for the tutorial and the time you put into this !
I was interested in creating shell extensions (especially icon overlays) without ATL in C++ and noticed that it is even possible to do with PureBasic. Then I thought it would be cool to share the information on how to create a simple COM server somehow.
Ajm wrote:I'm not sure I really understand half of that but thanks for the time and effort in sharing it. :)
Oh I really hope you'll understand it at least better than before with my tutorial. :)

Re: Writing COM Server DLLs (64bit, 32bit, Windows)

Posted: Sun Feb 05, 2012 2:01 pm
by helpy
[offtopic]
DarkDragon wrote:
helpy wrote:
DarkDragon wrote:Here are the files I used (I hope they are all included). To extract the zip file from this source, just run the program...
Cool 8)

Nice way to attach a file ;-)
Hehe, yes, but it doesn't work with too large files.
It probably would work with larger files, if you use Base64 :-)

cu,
guido
[/offtopic]

Re: Writing COM Server DLLs (64bit, 32bit, Windows)

Posted: Sun Feb 05, 2012 2:35 pm
by yrreti
I also want to thank you very much for the tutorial and the time you put into this !
Although I haven't yet ventured into that area. Your tutorial and the code you shared
will be of great help in understanding it better in the future.
Thanks much

Re: Writing COM Server DLLs (64bit, 32bit, Windows)

Posted: Sun Feb 12, 2012 6:14 pm
by netmaestro
Very good work, thanks for posting it!

Re: Writing COM Server DLLs (64bit, 32bit, Windows)

Posted: Tue Mar 20, 2012 8:24 pm
by Nico
How to implement progID?

I added directly in the registry but it does not work!

Re: Writing COM Server DLLs (64bit, 32bit, Windows)

Posted: Tue Mar 05, 2013 9:56 am
by SeregaZ
i try to convert this code to PB:

Code: Select all

using System;
using System.Runtime.InteropServices;
using HRESULT = System.UInt32;
 
namespace AddIE7Rule
{
    [Guid("012d7f2c-5f7d-468b-83b3-fb8ad12461e7"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface IBrowserEmulationFilter
    {
        void IsIE7Mode();
        void IE7Rules();
        HRESULT AddIE7Rule(string domain);
        //void RemoveRule();
        //void GetRuleTime();
        //void SetRuleTime();
        //void ResetBrowserModeFilter();
    }
 
    class Program
    {
        [DllImport("urlmon.dll", EntryPoint = "#442")]
        static extern HRESULT CreateBrowserEmulationFilter(uint type, out IBrowserEmulationFilter filter);
 
        static void Main(string[] args)
        {
            IBrowserEmulationFilter filter;
 
            if (CreateBrowserEmulationFilter(0, out filter) == 0)
            {
                if (filter.AddIE7Rule("test123.com") == 0)
                    Console.WriteLine("Added!");
            }
        }
    }
}
and cant do this. how to correctly catch function
0x6f3f687f: public: virtual long __stdcall CBrowserModeFilter::AddIE7Rule(unsigned short const *) ?

my code is didnt work:

Code: Select all

  Prototype.l ProtoAddIE7Rule(url$)

  If OpenLibrary(0, "urlmon.dll")
   
    AddIE7Rule.ProtoAddIE7Rule = GetFunction(0, "AddIE7Rule")
    
    AddIE7Rule("test.com")
    CloseLibrary(0)
  EndIf
this code must to add test.com to list of compatibility urls for explorer 8-9