// ============================================================================
// VBVM6Lib - A type library for unrestricted memory access in Visual Basic 6
// ============================================================================
// Copyright (C) 2002 Michel Rutten
//
// All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// ============================================================================
// TypeLib      : VBVM6Lib
// Version      : 1.0
// Compiler     : MIDL
// Dependencies : msvbvm60.dll
//
// GUIDs        : TypeLib VB6VM6Lib {CDFFA366-1D4F-43f9-B4BF-5438BC7C7D29}
//
// Description  : Declarations and aliases for (undocumented) functions in
//                the Visual Basic runtime library msvbvm60.dll allowing
//                unrestricted read/write memory access, pointer manipulation
//                and type casting.
//
// ============================================================================
// Introduction
//
// This library was conceived mainly out of frustration with the far from
// elegant but seemingly omnipresent (ab)use of a function exported by
// kernel32.dll that is quite useful for VB programmers when used to do
// what it is meant for, the discovery - and for that matter also first
// application in this context - of which should be contributed to Hardcore
// Visual Basic author and (classic) VB guru Bruce McKinney. Readers who
// haven't got the slightest clue which particular function is being
// referred to are advised to at least *try* to get with the program first
// and return to this typelib only if they still have an healthy appetite
// for more delicatessen. However if you are into VB gourmet then you are
// invited to stray from the path layed out for us mortals by the code
// gurus on mount olympus (sorry Bruce, no hard feelings) and join in this
// copious feast of strange fruits and the likes. As most exotic food, it
// may take some time getting used to, so don't let that slight nausea at
// the third three finger salute turn you down, but hang in there and keep
// trying - carefully that is. Ultimately, you will be rewarded with fast
// and elegant code, as well as a bit of insight into the intestines of
// your favourite programming environment.
//
// A bit of advise: If you feel like peeking and poking around in there
// like them good 'ole BASIC times, I suggest that you check out the
// IsBadReadPtr and IsBadWritePtr functions in kernel32. They can tell you
// if it is safe to read from or write to a memory address or range.
// Otherwise that kernel will hit right back at ya with a nasty exception
// fault. Also keep in mind that none of these aliases tolerate being
// called with an argument value that equals 0, Nothing or vbNullString.
//
// Michel Rutten (C) 2002
//
// ============================================================================
// DISCLAIMER:
//
// 1. Explicit coding. Parental discretion is advised.
// 2. Using this type library will not make your source code more readable,
//    understandable, accessible, generic, portable, self-documenting,
//    manageable, upgradeable, reliable nor stable.
// 3. Using this type library without appropriate insight will cause strange
//    behaviour, resource leaks or algemeine Schmutzverletzungen and is
//    guaranteed to crash the application, the Visual Basic IDE or even the
//    operating system.
// 4. Using this type library does not guarantee to increase software
//    performance noticeably, nor does it improve or countereffect bad
//    software design, algorithms, coding practices or hardware.
// 5. Using this type library does not implicate you have to adhere to these
//    naming conventions. More version updates were the result of name changes
//    than of actual declaration modifications or extensions. Customizing this
//    source code to your personal likings is highly encouraged, but remember
//    to change the GUIDs.
// 6. The opinions expressed in this disclaimer are not necessarily those of
//    the author.
// ============================================================================


[
	// This description is shown in the VB references dialog box and
	// in the VB Object Browser when the library is selected.
	helpstring("Visual Basic 6 Virtual Machine Type Library 1.0 by Michel Rutten - Declarations and aliases for (undocumented) functions in the VB6 runtime library."),
	// The LIBID was generated by GUIDGen
    uuid(CDFFA366-1D4F-43f9-B4BF-5438BC7C7D29),
	lcid(0x00000000),
	version(1.0)
]
library VBVM6Lib {

	// ============================================================================
	//
	//                          Compound type declarations
	//
	// ============================================================================
	// Structures describing groups of 1, 2, 4 or 8 bytes
	// Used in combination with memory access functions


	// These declarations come in pairs for each possible structure size; one
	// declaration has the form of a record with named members, the other packs
	// the elements into a fixed-size array. All structures are associated with
	// one or more memory access function declarations using arguments of that type.
	// Depending on the situation, one of these may be more convenient to apply.


	// ============================================================================
	// 16-bit structures
	// ============================================================================

	[helpstring("A 16-bit integer represented by two bytes.")]
	typedef struct DByte {
		[helpstring("Least significant byte value.")] byte LoByte;
		[helpstring("Most significant byte value.")]  byte HiByte;
	} DByte;

	[helpstring("A 16-bit integer represented by an array of two bytes.")]
	typedef struct DByteArray {
		[helpstring("Two bytes representing one 16-bit integer.")] byte Bytes[2];
	} DByteArray;


	// ============================================================================
	// 32-bit structures
	// ============================================================================

	[helpstring("A 32-bit long integer represented by four bytes.")]
	typedef struct QByte {
		[helpstring("Least significant 16-bit DByte value.")] DByte LoWord;
		[helpstring("Most significant 16-bit DByte value.")]  DByte HiWord;
	} QByte;

	[helpstring("A 32-bit long integer represented by an array of four bytes.")]
	typedef struct QByteArray {
		[helpstring("Four bytes representing one 32-bit long integer.")] byte Bytes[4];
	} QByteArray;

	[helpstring("A 32-bit dword represented by two integers.")]
	typedef struct DWord {
		[helpstring("Least significant 16-bit integer value.")] short LoWord;
		[helpstring("Most significant 16-bit integer value.")]  short HiWord;
	} DWord;

	[helpstring("A 32-bit dword represented by an array of two integers.")]
	typedef struct DWordArray {
		[helpstring("Two integer representing one 32-bit dword.")] short Words[2];
	} DWordArray;


	// ============================================================================
	// 64-bit structures
	// ============================================================================

	[helpstring("A 64-bit qword represented by eight bytes.")]
	typedef struct OByte {
		[helpstring("Least significant 32-bit QByte value.")] QByte LoDWord;
		[helpstring("Most significant 32-bit QByte value.")]  QByte HiDWord;
	} OByte;

	[helpstring("A 64-bit qword represented by an array of eight bytes.")]
	typedef struct OByteArray {
	    [helpstring("Eight bytes representing one 64-bit qword.")] byte Bytes[8];
	} OByteArray;

	[helpstring("A 64-bit qword represented by four integers.")]
	typedef struct QWord {
		[helpstring("Least significant 32-bit DWord value.")] DWord LoDWord;
		[helpstring("Most significant 32-bit DWord value.")]  DWord HiDWord;
	} QWord;

	[helpstring("A 64-bit qword represented by an array of four integers.")]
	typedef struct QWordArray {
	    [helpstring("Four integers representing one 64-bit qword.")] short Words[4];
	} QWordArray;

	[helpstring("A 64-bit qword represented by two long integers.")]
	typedef struct DLong {
		[helpstring("Least significant 32-bit long integer value.")] long LoDWord;
		[helpstring("Most significant 32-bit long integer value.")]  long HiDWord;
	} DLong;

	[helpstring("A 64-bit qword represented by an array of two long integers.")]
	typedef struct DLongArray {
	    [helpstring("Two long integers representing one 64-bit qword.")] int Longs[2];
	} DLongArray;


	// ============================================================================
	// VBUnkDesc
	// ============================================================================
	// Regular Visual Basic objects store their reference count at the memory
	// location immediately following the VTable pointer. The GetUnkDesc function
	// declaration aliases the GetMem8 run-time function to return this information
	// for a given object in the form of the following type. The pVTable member will
	// always be valid for any COM object (per definition), but the RefCnt only
	// applies to IUnknown interface pointers of objects written in Visual Basic.

	[helpstring("Internal object descriptor pointed to by a standard Visual Basic (in-process) IUnknown object interface pointer, i.e. by object references stored in variables declared \"As IUnknown\".")]
	typedef struct VBUnkDesc {
	    [helpstring("Pointer to the object interface's VTable structure. Applies to all COM object interface pointers.")]
	    long pVTable;
	    [helpstring("Object reference count. Only applies to IUnknown interface pointers of objects with the default Visual Basic reference counting mechanism.")]
	    long RefCnt;
	} VBUnkDesc;


	// ============================================================================
	//
	//                                  Module VBVM6
	//
	// ============================================================================
	[
		dllname("msvbvm60.dll"),
		helpstring("Declarations and aliases for (undocumented) functions in the Visual Basic 6 Virtual Machine runtime library msvbvm60.dll concerning direct memory access, pointer manipulation and type casting. Warning: will throw exceptions for illegal or NULL arguments!")
	]
	module VBVM6 {


		// ========================================================================
		//
		//                                Constants
		//
		// ========================================================================

		[helpstring("Null pointer value.")]	const long vbNullPtr = 0;

		// ========================================================================
		//
		//                                Functions
		//
		// ========================================================================


		// ========================================================================
		// VarPtr aliases
		// ========================================================================
		// The VarPtr function simply returns the DWord value pushed onto the stack
		// by the caller. The assembly code looks like this:
		//
		//    mov eax, [esp+4]			; dereference the given dword pointer
		//    ret 4						; return the result
		//
		// ========================================================================


		// ========================================================================
		// Function ArrPtr
		// ========================================================================
		// VarPtr alias for obtaining a pointer to an array's SAFEARRAY structure
		// ========================================================================
	    [
	        entry("VarPtr"),
	        helpstring("Returns a pointer to the SAFEARRAY descriptor of any Visual Basic array, except string arrays due to Visual Basic's implicit Unicode/ANSI conversion. For string arrays, use StrArrPtr.")
	    ]
		long __stdcall ArrPtr([in] SAFEARRAY(void) * Ptr);


		// ========================================================================
		// Function StrArrPtr
		// ========================================================================
	    // We have to declare a special alias for string arrays using a BSTR
	    // parameter declaration, because a SAFEARRAY(void)* parameter declaration
	    // causes VB to pass in a pointer to a temporary array of ANSI converted
	    // strings. Upon return by ArrPtr, this pointer will be invalid because
	    // the temporary array will already have been destroyed. By using a
	    // SAFEARRAY(BSTR)* parameter declaration, the original string array
	    // pointer itself is being passed in and consequently returned.
		// ========================================================================
		[
		    entry("VarPtr"),
		    helpstring("Returns a pointer to the SAFEARRAY descriptor of a Visual Basic string array. No implicit ANSI/Unicode conversion.")
	    ]
		long __stdcall StrArrPtr([in] SAFEARRAY(BSTR) * Ptr);


		// ========================================================================
		// VarPtr aliases for copying and casting pointers
		// ========================================================================
		// By aliasing the VarPtr function's return value, we can construct
		// functions that return a copy of the source pointer cast to a reference
		// variable type.
		// ========================================================================


		// ========================================================================
		// AsString
		// ========================================================================
		// VB Syntax: sDest = AsString(pStr)
		[
		    entry("VarPtr"),
		    helpstring("Casts a pointer to a Visual Basic string. The returned string will reference characters at the given address, but also include the preceding DWord which will be interpreted as the string length. This function is the opposite of StrPtr and StringPtr.")
	    ]
		BSTR __stdcall AsString([in] long BSTR);


		// ========================================================================
		// Function AsObject
		// ========================================================================
		// VB Syntax: Set oDest = AsObject(pUnk)
		[
		    entry("VarPtr"),
		    helpstring("Casts a pointer to an IUnknown object. No reference counting is performed. This function is the opposite of ObjPtr and ObjectPtr.")
	    ]
		IUnknown* __stdcall AsObject([in] long Ptr);


		// ========================================================================
		// Function StringRef
		// ========================================================================
		// VB Syntax: sStolen = StringRef(sSource)
		// 			  ' sStolen and sSource now point to the same characters
		//            ' ...
		//            ' Clean up
		//            StringPtr(sStolen) = 0&
		[
		    entry("VarPtr"),
		    helpstring("Returns a second (stolen) reference to the source string. The returned string will be pointing to the same characters as the source string. The caller is responsible for clearing the stolen reference without freeing the allocated memory.")
	    ]
		BSTR __stdcall StringRef([in] BSTR BStr);


		// ========================================================================
		// Function NoAddRef
		// ========================================================================
		// VB Syntax: Set oNotCounted = NoAddRef(oSource)
		//            ' oNotCounted now contains an uncounted reference to oSource
		//            ' ...
		//            ' Clean up
		//            ObjectPtr(oNotCounted) = 0&
		[
		    entry("VarPtr"),
		    helpstring("Returns an uncounted (stolen) object reference. No reference counting is performed. The caller is responsible for keeping the object alive as long as the reference is in use and should clear the stolen reference without decreasing the reference count.")
	    ]
		IUnknown* __stdcall NoAddRef([in] void * Object);	// IUnknown* causes VB to call AddRef


		// ========================================================================
		// GetMem / PutMem aliases for direct memory access
		// ========================================================================
		// Versions are available for accessing 1, 2, 4 or 8 bytes wide values.
		//
		// The GetMem functions dereference the memory address pushed onto the
		// stack. Their general form is:
		//
		//    Sub GetMemX(ByVal Address As Long, lpValue As Long)
		//
		// The assembly code looks like this:
		//
		// GetMem1:               GetMem2:            GetMem4:
		//
		// mov eax, [esp+4]       mov eax, [esp+4]    mov eax, [esp+4]	; eax := Address
		// mov ecx, [esp+8]       mov ecx, [esp+8]    mov ecx, [esp+8]	; ecx := lpValue
		// mov al, [eax]          mov ax, [eax]       mov eax, [eax]	; eax := [BYTE|WORD|DWORD] PTR [Address]
		// mov [ecx], al          mov [ecx], ax       mov [ecx], eax	; [lpValue] := [Address]
		// xor eax, eax           xor eax, eax        xor eax, eax		; Return (HRESULT) S_OK
		// ret 8                  ret 8               ret 8
		//
		// GetMem8 copies 8 bytes from source (ByRef) to destination (ByRef) argument.
		//
		//    Sub GetMem8(ByVal Address As Long, lpValue As DWord)
		//
		// GetMem8:
		//
		// mov eax, [esp+4]		; eax := Address
		// mov ecx, [esp+8]		; ecx := lpValue
		// mov edx, [eax]		; edx := DWORD PTR [Address]
		// mov eax, [eax+4]		; eax := DWORD PTR [Address+4]
		// mov [ecx], edx		; DWORD PTR [lpValue] := DWORD PTR [Address]
		// mov [ecx+4], eax		; DWORD PTR [lpValue+4] := DWORD PTR [Address+4]
		// xor eax, eax         ; Return (HRESULT) S_OK
		// ret 8
		//
		//
		// The PutMem functions write to the memory address pushed onto the stack.
		// Their general form is:
		//
		//    Sub PutMemX(ByVal Address, ByVal NewValue)
		//
		// The assembly code looks like this:
		//
		// PutMem1:               PutMem2:            PutMem4:
		//
		// mov ecx, [esp+4]       mov ecx, [esp+4]    mov ecx, [esp+4]	; ecx = Address
		// mov al, [esp+8]        mov ax, [esp+8]     mov eax, [esp+8]	; eax = NewValue
		// mov [ecx], al          mov [ecx], ax       mov [ecx], eax	; [Address] = NewValue
		// xor eax, eax           xor eax, eax        xor eax, eax		; Return (HRESULT) S_OK
		// ret 8                  ret 8               ret 8
		//
		// PutMem8 writes an 8 byte (ByVal) argument to the destination (ByRef) argument.
		//
		//    Sub PutMem8(ByVal Address As Long, ByVal HiDWord As Long, ByVal LoDWord As Long)
		//
		// PutMem8:
		//
		// mov eax, [esp+4]		; eax = Address
		// mov ecx, [esp+8]		; ecx = LoDWord
		// mov [eax], ecx		; DWORD PTR [eax] = HiDWord
		// mov ecx, [esp+C]		; ecx = LoDWord
		// mov [eax+4], ecx		; DWORD PTR [eax+4] = LoDWord
		// xor eax, eax			; return (HRESULT) S_OK
		// ret C

		// ========================================================================
		// Note that there are more of these functions.
		// GetMemObj and GetMemEvent expect and return an object variable and call
		// Addref if the argument is not Nothing. GetMemNewObj creates an object.
		// GetMemVar and GetMemStr use OleAut32 to copy a variant/string variable.
		// In any case these are less suitable for creating usefull aliases.
		// ========================================================================
		// Read and write declarations have been combined into property get/let pairs
		// For each value size, two different property aliases are given:
		// MemX aliases use absolute addressing (expect a memory address parameter)
		// AsX  aliases use indirect addressing (expect a memory reference parameter)
		// ========================================================================
		//
	    //      Property Name            Parameter   Return                Return type  Can    Can
	    // Absolute      Indirect          Width     Type                  Description  Read  Write
	    // ----------------------------------------------------------------------------------------
	    // MemByte       AsByte              1       Byte                  1 x  8 bit     X     X
	    // MemWord       AsWord              2       Word                  1 x 16 bit     X     X
	    // MemLong       AsLong              4       Long                  1 x 32 bit     X     X
	    // MemCurr       AsCurr              8       Currency              1 x 64 bit     X     X
	    //
	    // MemDByte(Arr) AsDByte(Arr)        2       DByte                 2 x  8 bit     X     -
	    // MemQByte(Arr) AsQByte(Arr)        4       QByte                 4 x  8 bit     X     -
	    // MemDWord(Arr) AsDWord(Arr)        4       DWord                 2 x 16 bit     X     -
	    // MemOByte(Arr) AsOByte(Arr)        8       OByte                 8 x  8 bit     X     -
	    // MemQWord(Arr) AsQWord(Arr)        8       QWord                 4 x 16 bit     X     -
	    // MemDLong(Arr) AsDLong(Arr)        8       DLong                 2 x 32 bit     X     -
	    //
	    //               VariantType         2       Word                  VARIANT.vt     X     X
	    //               StringPtr           4       Long                  BSTR           X     X
	    //               SAPtr               4       Long                  pSA            X     X
	    //               ObjectPtr           4       Long                  LPUnknown      X     X
	    //               VTablePtr           4       Long                  pVTable        X     X
	    //
	    // GetUnkDesc    GetUnkDescFromPtr   8       VBUnkDesc             pVTable,RefCnt X     -
		//
		// ========================================================================


		// ========================================================================
		//
		//                               1-Byte values
		//
		// ========================================================================


		// ========================================================================
		// Property MemByte
		// ========================================================================
	    [
	    	entry("GetMem1"), propget,
	    	helpstring("Sets or returns the Byte value at the specified memory address.")
	    ]
		HRESULT __stdcall MemByte(
			[in]		    int					Address,
			[out, retval]   BYTE *				lpRetVal
		);

	    [
	    	entry("PutMem1"), propput
	    ]
		HRESULT __stdcall MemByte(
			[in]            int     			Address,
			[in]            BYTE    			NewValue
		);

		// ========================================================================
		// Property AsByte
		// ========================================================================
	    [
	    	entry("GetMem1"), propget,
	    	helpstring("Returns or sets the value referenced by the source parameter cast to a Byte.")
	    ]
		HRESULT __stdcall AsByte(
			[in]		    void *  			Ptr,
			[out, retval]   BYTE *				lpRetVal
		);

	    [
	    	entry("PutMem1"), propput,
	    ]
		HRESULT __stdcall AsByte(
			[in]            void *  			Ptr,
			[in]            BYTE    			NewValue
		);


		// ========================================================================
		//
		//                               2-Byte values
		//
		// ========================================================================


		// ========================================================================
		// Property MemWord
		// ========================================================================
	    [
	    	entry("GetMem2"), propget,
	    	helpstring("Sets or returns the 16-bit Word integer value at the specified memory address.")
	    ]
		HRESULT __stdcall MemWord(
			[in]		    int					Address,
			[out, retval]   short *				lpRetVal
		);

	    [
	    	entry("PutMem2"), propput
	    ]
		HRESULT __stdcall MemWord(
			[in]            int     			Address,
			[in]            short   			NewValue
		);

		// ========================================================================
		// Property AsWord
		// ========================================================================
	    [
	    	entry("GetMem2"), propget,
	    	helpstring("Returns or sets the value referenced by the source parameter cast to a Word.")
	    ]
		HRESULT __stdcall AsWord(
			[in]		    void *				Ptr,
			[out, retval]   short *				lpRetVal
		);

	    [
	    	entry("PutMem2"), propput
	    ]
		HRESULT __stdcall AsWord(
			[in]            void *				Ptr,
			[in]            short				NewValue
		);


		// ========================================================================
		// Function MemDByte
		// ========================================================================
	    [
	    	entry("GetMem4"),
	    	helpstring("Returns the 16-bit DByte structure at the specified memory address. (Read only)")
	    ]
		HRESULT __stdcall MemDByte(
			[in]		    int					Address,
			[out, retval]   DByte *				lpRetVal
		);


		// ========================================================================
		// Function MemDByteArr
		// ========================================================================
	    [
	    	entry("GetMem4"),
	    	helpstring("Returns the 16-bit DByteArray structure at the specified memory address. (Read only)")
	    ]
		HRESULT __stdcall MemDByteArr(
			[in]		    int					Address,
			[out, retval]   DByteArray *		lpRetVal
		);


		// ========================================================================
		// Function AsDByte
		// ========================================================================
	    [
	    	entry("GetMem4"),
	    	helpstring("Returns the value referenced by the source parameter cast to a DByte structure. (Read only)")
	    ]
		HRESULT __stdcall AsDByte(
			[in]		    void *				Ptr,
			[out, retval]   DByte *				lpRetVal
		);


		// ========================================================================
		// Function AsDByteArr
		// ========================================================================
	    [
	    	entry("GetMem4"),
	    	helpstring("Returns the value referenced by the source parameter cast to a DByteArray structure. (Read only)")
	    ]
		HRESULT __stdcall AsDByteArr(
			[in]		    void *				Ptr,
			[out, retval]   DByteArray *		lpRetVal
		);


		// ========================================================================
		// Property VariantType
		// ========================================================================
		// Special alias for accessing the vt member of a VARIANT structure
	    [
	    	entry("GetMem2"), propget,
	    	helpstring("Returns or sets the the type flags of a Variant. This property accesses the actual value, as opposed to VB's built-in VarType function that masks out certain high bits (VT_BYREF).")
	    ]
		HRESULT __stdcall VariantType(
			[in] 			VARIANT *			Variant,
			[out, retval]   short *				lpRetVal
		);

	    [
	    	entry("PutMem2"), propput,
	    ]
		HRESULT __stdcall VariantType(
			[in] 			VARIANT *			Variant,
			[in] 			short				NewValue
		);


		// ========================================================================
		//
		//                            4-Byte values
		//
		// ========================================================================


		// ========================================================================
		// Property MemLong
		// ========================================================================
	    [
	    	entry("GetMem4"), propget,
	    	helpstring("Sets or returns the 32-bit Long integer value at the specified memory address.")
	    ]
		HRESULT __stdcall MemLong(
			[in]		    int					Address,
			[out, retval]   int *				lpRetVal
		);

	    [
	    	entry("PutMem4"), propput,
	    ]
		HRESULT __stdcall MemLong(
			[in]            int					Address,
			[in]            int					NewValue
		);

		// ========================================================================
		// Property AsLong
		// ========================================================================
	    [
	    	entry("GetMem4"), propget,
	    	helpstring("Returns or sets the value referenced by the source parameter cast to a DWord Long.")
	    ]
		HRESULT __stdcall AsLong(
			[in]		    void *				Ptr,
			[out, retval]   int *				lpRetVal
		);

	    [
	    	entry("PutMem4"), propput,
	    ]
		HRESULT __stdcall AsLong(
			[in]            void *				Ptr,
			[in]            int					NewValue
		);


		// ========================================================================
		// Function MemDWord
		// ========================================================================
	    [
	    	entry("GetMem4"),
	    	helpstring("Returns the 32-bit DWord structure at the specified memory address. (Read only)")
	    ]
		HRESULT __stdcall MemDWord(
			[in]		    int					Address,
			[out, retval]   DWord *				lpRetVal
		);


		// ========================================================================
		// Function MemDWordArr
		// ========================================================================
	    [
	    	entry("GetMem4"),
	    	helpstring("Returns the 32-bit DWordArray structure at the specified memory address. (Read only)")
	    ]
		HRESULT __stdcall MemDWordArr(
			[in]		    int					Address,
			[out, retval]   DWordArray *		lpRetVal
		);


		// ========================================================================
		// Function AsDWord
		// ========================================================================
	    [
	    	entry("GetMem4"),
	    	helpstring("Returns the value referenced by the source parameter cast to a DWord structure. (Read only)")
	    ]
		HRESULT __stdcall AsDWord(
			[in]		    void *				Ptr,
			[out, retval]   DWord *				lpRetVal
		);


		// ========================================================================
		// Function AsDWordArr
		// ========================================================================
	    [
	    	entry("GetMem4"),
	    	helpstring("Returns the value referenced by the source parameter cast to a DWordArray structure. (Read only)")
	    ]
		HRESULT __stdcall AsDWordArr(
			[in]		    void *				Ptr,
			[out, retval]   DWordArray *		lpRetVal
		);


		// ========================================================================
		// Function MemQByte
		// ========================================================================
	    [
	    	entry("GetMem4"),
	    	helpstring("Returns the 32-bit QByte structure at the specified memory address. (Read only)")
	    ]
		HRESULT __stdcall MemQByte(
			[in]		    int					Address,
			[out, retval]   QByte *				lpRetVal
		);


		// ========================================================================
		// Function MemQByteArr
		// ========================================================================
	    [
	    	entry("GetMem4"),
	    	helpstring("Returns the 32-bit QByteArray structure at the specified memory address. (Read only)")
	    ]
		HRESULT __stdcall MemQByteArr(
			[in]		    int					Address,
			[out, retval]   QByteArray *		lpRetVal
		);


		// ========================================================================
		// Function AsQByte
		// ========================================================================
	    [
	    	entry("GetMem4"),
	    	helpstring("Returns the value referenced by the source parameter cast to a QByte. (Read only)")
	    ]
		HRESULT __stdcall AsQByte(
			[in]		    void *				Ptr,
			[out, retval]   QByte *				lpRetVal
		);


		// ========================================================================
		// Function AsQByteArr
		// ========================================================================
	    [
	    	entry("GetMem4"),
	    	helpstring("Returns the value referenced by the source parameter cast to a QByteArray. (Read only)")
	    ]
		HRESULT __stdcall AsQByteArr(
			[in]		    void *				Ptr,
			[out, retval]   QByteArray *		lpRetVal
		);


		// ========================================================================
		// Property StringPtr
		// ========================================================================
	    [
	    	entry("GetMem4"), propget,
	    	helpstring("Returns or sets the value of the source string's BSTR pointer. This property allows read/write access to the same value that is returned by Visual Basic's (hidden) StrPtr function.")
	    ]
		HRESULT __stdcall StringPtr(
			[in]		    BSTR *				Source,
			[out, retval]   long *				lpRetVal
		);

	    [
	    	entry("PutMem4"), propput,
	    ]
		HRESULT __stdcall StringPtr(
			[in]		    BSTR *				Source,
			[in]            long				NewValue
		);


		// ========================================================================
		// Property SAPtr
		// ========================================================================
		// Special alias for accessing SAFEARRAY descriptor pointers
	    [
	    	entry("GetMem4"), propget,
	    	helpstring("Returns or sets the value of an array's SAFEARRAY descriptor pointer. This property allows read/write access to the value referenced by the pointer returned by ArrPtr. Use StrSAPtr for string arrays to prevent the implicit ANSI/Unicode conversion.")
	    ]
		HRESULT __stdcall SAPtr(
			[in] 			SAFEARRAY(void) *	Array,
			[out, retval]   int *				lpRetVal
		);

	    [
	    	entry("PutMem4"), propput,
	    ]
		HRESULT __stdcall SAPtr(
			[in] 			SAFEARRAY(void) *	Array,
			[in] 			int					NewValue
		);


		// ========================================================================
		// Property StrSAPtr
		// ========================================================================
		// Special alias for accessing string SAFEARRAY descriptor pointers
	    [
	    	entry("GetMem4"), propget,
	    	helpstring("Returns or sets the value of the SAFEARRAY descriptor pointer of a string array. This property allows read/write access to the value referenced by the pointer returned by StrArrPtr.")
	    ]
		HRESULT __stdcall StrSAPtr(
			[in] 			SAFEARRAY(BSTR) *	Array,
			[out, retval]   int *				lpRetVal
		);

	    [
	    	entry("PutMem4"), propput,
	    ]
		HRESULT __stdcall StrSAPtr(
			[in] 			SAFEARRAY(BSTR) *	Array,
			[in] 			int					NewValue
		);


		// ========================================================================
		// Property ObjectPtr
		// ========================================================================
		// Special alias for accessing object pointers
		//
		// Note: this function could be made slightly more type-safe by declaring
		// the arguments as IUnknown** (i.e. ByRef IUnknown), but this would cause
		// VB to QueryInterface and Release the given object argument before and
		// after calling the function, unnecessarily slowing it down (a lot).
		//
		// However, because VB always supplies object pointers by reference
		// (regardless of whether the parameter is declared as 'ByVal As Object',
		// 'ByRef As Object' or 'As Any'), which is what this function expects in
		// order to return a valid result, we can safely declare the argument as
		// void* without introducing possible ambiguities.

	    [
	    	entry("GetMem4"),
	    	propget,
	    	helpstring("Expects a ByRef object argument and returns or sets the value of the object pointer. This property allows read/write access to the same value that is returned by ObjPtr.")
	    ]
		HRESULT __stdcall ObjectPtr(
			[in] 			void * 				Object,		// IUnknown **
			[out, retval]   int *				lpRetVal
		);

	    [
	    	entry("PutMem4"),
	    	propput,
	    ]
		HRESULT __stdcall ObjectPtr(
			[in] 			void * 				Object,		// IUnknown **
			[in] 			int					NewValue
		);


		// ========================================================================
		// Property VTablePtr
		// ========================================================================
		// Special alias for accessing object interface VTable pointers.
		//
		// Allows read/write access to the value at the memory location returned by
		// the ObjectPtr and VBA.Objptr functions, which contains the object
		// interface (i.e. VTable) pointer, i.e. VTablePtr(AnObject) access the
		// same value as MemLong(ObjectPtr(AnObject)).
		//
		// The IUnknown* argument causes VB to perform an AddRef and Release pair
		// on the given object argument before and after calling the function,
		// causing a slight performance hit. However we cannot declare this
		// function otherwise.
		//
		// Note that it is impossible to declare such a by value object parameter
		// in plain VB, as VB always uses pointers to objects; a parameter declared
		// as 'ByVal AnObject As Object' still causes VB to supply a pointer to an
		// object as the function argument, although it is a copy of the original
		// object pointer (so the function cannot modify the original caller's value),
		// but not the value of the pointer itself as defined by the following
		// IUnknown* idl type declaration (which VB *does* recognize as such).
	    [
	    	entry("GetMem4"),
	    	propget,
	    	helpstring("Returns or sets the value of the source object's VTable interface pointer. This property allows read/write access to the value referenced by the pointer returned by both ObjPtr and ObjectPtr. Should not be used on objects equal to Nothing.")
	    ]
		HRESULT __stdcall VTablePtr(
			[in] 			IUnknown *			Object,
			[out, retval]   int *				Value
		);

	    [
	    	entry("PutMem4"),
	    	propput,
	    ]
		HRESULT __stdcall VTablePtr(
			[in] 			IUnknown *			Object,
			[in] 			int					NewValue
		);


		// ========================================================================
		//
		//                                    8-Byte values
		//
		// ========================================================================


		// ========================================================================
		// Property MemCurr
		// ========================================================================
	    [
	    	entry("GetMem8"), propget,
	    	helpstring("Sets or returns the 64-bit Currency value at the specified memory address. The Currency type is represented by a 64-bit large integer, scaled by 10.000 to give a fixed-point number.")
	    ]
		HRESULT __stdcall MemCurr(
			[in]		    int					Address,
			[out, retval]   CURRENCY *			Value
		);

	    [
	    	entry("PutMem8"), propput,
	    ]
		HRESULT __stdcall MemCurr(
			[in]            int					Address,
			[in]            CURRENCY			NewValue
		);

		// ========================================================================
		// Property AsCurr
		// ========================================================================
	    [
	    	entry("GetMem8"), propget,
	    	helpstring("Returns or sets the value referenced by the source parameter cast to a Currency variable. The Currency type is represented by a 64-bit large integer, scaled by 10.000 to give a fixed-point number.")
	    ]
		HRESULT __stdcall AsCurr(
			[in]		    void *				Ptr,
			[out, retval]   CURRENCY *			Value
		);

	    [
	    	entry("PutMem8"), propput,
	    ]
		HRESULT __stdcall AsCurr(
			[in]            void *				Ptr,
			[in]            CURRENCY			NewValue
		);


		// ========================================================================
		// Function MemDLong
		// ========================================================================
	    [
	    	entry("GetMem8"),
	    	helpstring("Returns a copy of the 64-bit DLong structure at the specified memory address. (Read only)")
	    ]
		HRESULT __stdcall MemDLong(
			[in]		    int					Address,
			[out, retval]   DLong *				Value
		);


		// ========================================================================
		// Function MemDLongArr
		// ========================================================================
	    [
	    	entry("GetMem8"),
	    	helpstring("Returns a copy of the 64-bit DLongArray structure at the specified memory address. (Read only)")
	    ]
		HRESULT __stdcall MemDLongArr(
			[in]		    int					Address,
			[out, retval]   DLongArray *		Value
		);


		// ========================================================================
		// Function AsDLong
		// ========================================================================
	    [
	    	entry("GetMem8"),
	    	helpstring("Returns the value referenced by the source parameter cast to a DLong structure. (Read only)")
	    ]
		HRESULT __stdcall AsDLong(
			[in]		    void *				Ptr,
			[out, retval]   DLong *				Value
		);


		// ========================================================================
		// Function AsDLongArr
		// ========================================================================
	    [
	    	entry("GetMem8"),
	    	helpstring("Returns the value referenced by the source parameter cast to a DLongArray structure. (Read only)")
	    ]
		HRESULT __stdcall AsDLongArr(
			[in]		    void *				Ptr,
			[out, retval]   DLongArray *		Value
		);


		// ========================================================================
		// Function MemQWord
		// ========================================================================
	    [
	    	entry("GetMem8"),
	    	helpstring("Returns the 64-bit QWord structure at the specified memory address. (Read only)")
	    ]
		HRESULT __stdcall MemQWord(
			[in]		    int					Address,
			[out, retval]   QWord *				Value
		);


		// ========================================================================
		// Function MemQWordArr
		// ========================================================================
	    [
	    	entry("GetMem8"),
	    	helpstring("Returns the 64-bit QWordArray structure at the specified memory address. (Read only)")
	    ]
		HRESULT __stdcall MemQWordArr(
			[in]		    int					Address,
			[out, retval]   QWordArray *		Value
		);


		// ========================================================================
		// Function AsQWord
		// ========================================================================
	    [
	    	entry("GetMem8"),
	    	helpstring("Returns the value referenced by the source parameter cast to a QWord structure. (Read only)")
	    ]
		HRESULT __stdcall AsQWord(
			[in]		    void *				Ptr,
			[out, retval]   QWord *				Value
		);


		// ========================================================================
		// Function AsQWordArr
		// ========================================================================
	    [
	    	entry("GetMem8"),
	    	helpstring("Returns the value referenced by the source parameter cast to a QWordArray structure. (Read only)")
	    ]
		HRESULT __stdcall AsQWordArr(
			[in]		    void *				Ptr,
			[out, retval]   QWordArray *		Value
		);


		// ========================================================================
		// Function MemOByte
		// ========================================================================
	    [
	    	entry("GetMem8"),
	    	helpstring("Returns the 64-bit OByte structure at the specified memory address. (Read only)")
	    ]
		HRESULT __stdcall MemOByte(
			[in]		    int					Address,
			[out, retval]   OByte *				Value
		);


		// ========================================================================
		// Function MemOByteArr
		// ========================================================================
	    [
	    	entry("GetMem8"),
	    	helpstring("Returns the 64-bit OByteArraystructure at the specified memory address. (Read only)")
	    ]
		HRESULT __stdcall MemOByteArr(
			[in]		    int					Address,
			[out, retval]   OByteArray *		Value
		);


		// ========================================================================
		// Function AsOByte
		// ========================================================================
	    [
	    	entry("GetMem8"),
	    	helpstring("Returns the value referenced by the source parameter cast to a OByte structure. (Read only)")
	    ]
		HRESULT __stdcall AsOByte(
			[in]		    void *				Ptr,
			[out, retval]   OByte *				Value
		);


		// ========================================================================
		// Function AsOByteArr
		// ========================================================================
	    [
	    	entry("GetMem8"),
	    	helpstring("Returns the value referenced by the source parameter cast to a OByteArray structure. (Read only)")
	    ]
		HRESULT __stdcall AsOByteArr(
			[in]		    void *				Ptr,
			[out, retval]   OByteArray *		Value
		);


		// ========================================================================
		// Special aliases for peeking into Visual Basic objects
		// ========================================================================
		// Returns the 'IUnknown descriptor' of the given object variable.
		// Our descriptor structure is 8 bytes long, nicely fitting the GetMem8
		// and PutMem8 runtime library functions.
		// The RefCnt member is only valid if the variable supplied as the function
		// argument is actually declared 'As IUnknown'.
		// Because of the IUnknown* parameter declaration, VB will AddRef and
		// Release the given object before and after calling the function, so the
		// returned reference count will always be one more than expected!
		//
		// A typical application of this alias would be such a function:
		//
		//    Function GetRefCnt(AnObject As stdole.IUnknown) As Long
		//       ' Since all COM objects implement IUnknown,
		//       ' VB will simply call AddRef (not QueryInterface)
		//       ' on the given object argument value
		//
		//       ' Protect against NULL objects (or GetUnkDesc will GPF!)
		//       If (AnObject Is Nothing) Then Exit Sub
		//
		//       ' Subtract 2 for the AddRefs due to both function calls
		//       GetRefCnt = VBVM6.GetUnkDesc(AnObject).RefCnt - 2&
		//
		//    End Function
		//
		// Note: GetUnkDesc(AnIUnknown).VTable = VTablePtr(AnIUnknown)
		//       GetUnkDesc(AnIUnknown).RefCnt = MemLong(ObjectPtr(AnIUnknown) + 4)
		// ========================================================================


		// ========================================================================
		// GetUnkDesc
		// ========================================================================
	    [
	    	entry("GetMem8"),
	    	helpstring("Returns the descriptor of an IUnknown object. The returned reference count only applies to object variables declared \"As IUnknown\" using the default Visual Basic reference counting mechanism, and will include an extra reference because of the parameter.")
	    ]
		HRESULT __stdcall GetUnkDesc(
			[in] 			IUnknown *				Object,
			[out, retval]   VBUnkDesc *				Value
		);


		// ========================================================================
		// GetUnkDescFromPtr
		// ========================================================================
	    [
	    	entry("GetMem8"),
	    	helpstring("Returns the object descriptor structure at the specified memory address. For the result to be meaningful, the input parameter must be a valid IUnknown interface pointer. (Read only)")
		]
		HRESULT __stdcall GetUnkDescFromPtr(
			[in] 			long					Ptr,
			[out, retval]   VBUnkDesc *				Value
		);


		// ========================================================================
		//
		//                               Assignment aliases
		//
		// ========================================================================


		// ========================================================================
		// These aliases are declared using generic void * (As Any) parameters for
		// both source and destination. They assign 1, 2, 4 or 8 bytes from one
		// variable to another.
		// Note: these functions are included as a means of escape to use for
		// assignments to variables with incompatible custom types. The 'As Any'
		// type declaration and the reversed order (cf. CopyMemory) of the
		// arguments makes these functions very error-prone, though one could
		// argue this holds for the module as a whole.
		// ========================================================================


		// =====================================s===================================
		// AssignByte
		// ========================================================================
	    [
	    	entry("GetMem1"),
	    	helpstring("Assigns a byte value from the source to the destination parameter's memory location.")
	    ]
		HRESULT __stdcall AssignByte(
			[in]		void *					Source,
			[in, out]	void *					Destination
		);


		// ========================================================================
		// AssignWord
		// ========================================================================
	    [
	    	entry("GetMem2"),
	    	helpstring("Assigns a 16-bit word value from the source to the destination parameter's memory location.")
	    ]
		HRESULT __stdcall AssignWord(
			[in]		void *					Source,
			[in, out]	void *					Destination
		);


		// ========================================================================
		// AssignDWord
		// ========================================================================
	    [
	    	entry("GetMem4"),
	    	helpstring("Assigns a 32-bit dword value from the source to the destination parameter's memory location.")
	    ]
		HRESULT __stdcall AssignDWord(
			[in]		void *					Source,
			[in, out]	void *					Destination
		);


		// ========================================================================
		// AssignQWord
		// ========================================================================
	    [
	    	entry("GetMem8"),
	    	helpstring("Assigns a 64-bit qword value from the source to the destination parameter's memory location.")
	    ]
		HRESULT __stdcall AssignQWord(
			[in]		void *					Source,
			[in, out]	void *					Destination
		);


	} // Module VBVM6

} // Library VBVM6Lib

// ========================================================================
//
//                              That's all folks!
//
// ========================================================================