Interop Marshalling









  1. #pragma once
  2. #ifndef For_Pch
  3. #define For_Pch

  4. #include "Windows.h"
  5. #include "PathCch.h"
  6. #include "strsafe.h"
  7. #include "objbase.h"
  8. #include "Combaseapi.h"
  9. #include "oleauto.h"
  10. #include "propvarutil.h"
  11. #include "wtypes.h"
  12. #include "stdio.h"
  13. #include "ctime"
  14. #include "exception"
  15. #include "typeinfo"
  16. #include "shlwapi.h"
  17. #include "Psapi.h"
  18. #include "stdexcept"
  19. #include "stdarg.h"
  20. #include "comdef.h"
  21. #include <algorithm>
  22. #include <vector>
  23. #include <type_traits>
  24. #include <concepts>
  25. #include <atlbase.h>
  26. #include <atlcom.h>
  27. #include <memory>

  28. #endif // !For_Pch




  1. #pragma once
  2. #include "For_Pch.h"
  3. #ifdef _DEBUG
  4. #  define My_Configuration Debug
  5. #else
  6. #  define My_Configuration Release
  7. #endif

  8. #define Stringizing_To_raw_string_w(arg) LR#arg
  9. #define Stringizing_To_raw_string(arg)    R#arg
  10. #define Add_Deliniter_w(str) Stringizing_To_raw_string_w( ***( ## str ## )*** )
  11. #define Add_Deliniter(str)   Stringizing_To_raw_string(   ***( ## str ## )*** )
  12. #define Expand_Macro_Parameter_definition3_w(A,B,C) Add_Deliniter_w( A ## B ## C )
  13. #define Expand_Macro_Parameter_definition3(A,B,C) Add_Deliniter(     A ## B ## C )
  14. #define Expand_Macro_Parameter_definition1_w(A)     Add_Deliniter_w(A)
  15. #define Expand_Macro_Parameter_definition1(A)       Add_Deliniter(  A)

  16. #define Server_Name_w(rr,Config_be_Expanded,ss) Expand_Macro_Parameter_definition3_w(rr,Config_be_Expanded,ss)
  17. #define Server_Name(  rr,Config_be_Expanded,ss) Expand_Macro_Parameter_definition3(  rr,Config_be_Expanded,ss)
  18. #define DLL_Name_w(rr,Config_be_Expanded,ss) Expand_Macro_Parameter_definition3_w(rr,Config_be_Expanded,ss)
  19. #define DLL_Name(  rr,Config_be_Expanded,ss) Expand_Macro_Parameter_definition3(  rr,Config_be_Expanded,ss)
  20. #define Raw_string_w(str)  Expand_Macro_Parameter_definition1_w(str)
  21. #define Raw_string(str)    Expand_Macro_Parameter_definition1(str)
  22. #define Lib_Name_inside(rr,Config_be_Expanded,ss) Expand_Macro_Parameter_definition3(rr,Config_be_Expanded,ss)
  23. #define Lib_Name_outside(rr,Config_be_Expanded,ss) Expand_Macro_Parameter_definition3(rr,Config_be_Expanded,ss)

  24. #pragma comment(lib,Lib_Name_outside(..\..\StaticLib_Marshalling\x64\,My_Configuration,\StaticLib_Marshalling))
  25. #pragma comment(lib,"PathCch")

  26. __interface ICreationInstance :IDispatch
  27. {
  28.     HRESULT Get_Interface3(
  29.         _In_ PVOID AssemblyInfo_ptr,
  30.         _COM_Outptr_ PVOID* ppvid);
  31.     HRESULT GetDescription(
  32.         _In_ BSTR description);
  33.     HRESULT GetDescription2(
  34.         _Out_ BSTR* description);
  35.     HRESULT Get_Interface4(
  36.         PVOID AssemblyInfo_ptr,
  37.         VARIANT* ppVoid_object);
  38. };

  39. typedef void (*MyWriteLine)(const WCHAR* format, va_list);

  40. struct TestParameter {
  41.     MyWriteLine MyWriteLine;
  42.     PVOID ptr_to_Interface;
  43.     const WCHAR* PathRoot;
  44. };

  45. class ExportedData {
  46.     MyWriteLine MyWriteLine;
  47.     const WCHAR* start;
  48.     va_list My_va_list;
  49.     static inline ExportedData* ED_ptr = nullptr;
  50. public:
  51.     static ExportedData* const MySelf() { return ED_ptr; }
  52.     void WriteLine(const WCHAR* format, ...) {
  53.         va_start(My_va_list, format);
  54.         MyWriteLine(format, My_va_list);
  55.         va_end(My_va_list);
  56.     }
  57.     ExportedData(TestParameter* pTestParameter, const WCHAR* start) {
  58.         MyWriteLine = pTestParameter->MyWriteLine;
  59.         this->start = start;
  60.         ED_ptr = this;
  61.         WriteLine(L"====== Begin %s =======", start);
  62.     }
  63.     ~ExportedData() {
  64.         WriteLine(L"====== End %s   =======", start);
  65.         ED_ptr = nullptr;
  66.     }
  67. };


  68. #define PAUSE system("pause");
  69. #define HR_(Express,errorCode) \
  70. try { My_Message((Express),(errorCode), __FILEW__, __LINE__, __FUNCTIONW__);} \
  71. catch (const std::exception & ) { return errorCode ; }
  72. #define RETURN(retVal) return My_RETURN(retVal, __FILEW__ , __LINE__ , __FUNCTIONW__);


  73. template <class T> concept  Is_BSTR_v = std::is_convertible_v<T, BSTR>;

  74. template <class T> concept  Is_LPCOLESTR_v = std::is_convertible_v<LPCOLESTR, T>;

  75. template <typename T>
  76. struct ServerInfo_Struct {
  77.     T AssemblyPath;
  78.     T TypeFullName;
  79.     T CreationMethod;
  80.     T CLSID;
  81.     T IID;
  82.     ServerInfo_Struct(T t1, T t2, T t3, T t4, T t5) :
  83.         AssemblyPath(t1),
  84.         TypeFullName(t2),
  85.         CreationMethod(t3),
  86.         CLSID(t4),
  87.         IID(t5) {
  88.     }
  89.     ServerInfo_Struct& operator=(const ServerInfo_Struct&) = delete;
  90.     ServerInfo_Struct(const ServerInfo_Struct&) = delete;

  91.     ~ServerInfo_Struct() requires Is_BSTR_v<T> {
  92.         if (0 == strcmp(typeid(T).name(), typeid(BSTR).name())) {
  93.             printf("std::is_convertible_v< %s , %s >\n",
  94.                 typeid(T).name(), typeid(BSTR).name());
  95.         }
  96.         else printf("===> Error:%s\n", typeid(T).name());

  97.         ::SysFreeString((wchar_t*)AssemblyPath);
  98.         ::SysFreeString((wchar_t*)TypeFullName);
  99.         ::SysFreeString((wchar_t*)CreationMethod);
  100.         ::SysFreeString((wchar_t*)CLSID);
  101.         ::SysFreeString((wchar_t*)IID);
  102.     }

  103.     ~ServerInfo_Struct()requires Is_LPCOLESTR_v<T> {
  104.         puts(typeid(T).name());
  105.         if (0 == strcmp(typeid(LPCOLESTR).name(), typeid(T).name())) {
  106.             printf("std::is_convertible_v< %s , %s >\n",
  107.                 typeid(LPCOLESTR).name(), typeid(T).name());
  108.         }
  109.         else printf("===> Error:%s\n", typeid(T).name());
  110.     }
  111. };
  112. const WCHAR* AddCurlyBracket(const WCHAR* uuid);
  113. const WCHAR* ToFullPath(const WCHAR* pRoot, const WCHAR* relativePath);
  114. void My_Message(HRESULT hr2, int errorCode, LPCWSTR file_, int Line_, const wchar_t* fn);
  115. int My_RETURN(int retVal, LPCWSTR file_, int Line_, const wchar_t* fn);

  116. int Get_ServerInterface4(TestParameter* ptr,
  117.     ServerInfo_Struct<LPCOLESTR>& MyServerString, PVOID* pRetVal);
  118. int Get_ServerInterface(TestParameter* ptr,
  119.     ServerInfo_Struct<LPCOLESTR>& MyServerString, PVOID* pRetVal);
  120. int SetErrorInfo_Chen(const WCHAR* Description, const WCHAR* source);









  1. // StaticLib_Marshalling.cpp : Defines the functions for the static library.
  2. //

  3. #include "pch.h"
  4. #include "framework.h"
  5. #include "TestParameter.h"

  6. const WCHAR* AddCurlyBracket(const WCHAR* uuid) {
  7.     const size_t MAX_index = 5, Max_length = 40;
  8.     static WCHAR TempUUID[MAX_index][Max_length + 3];
  9.     static size_t index = 0;
  10.     if (++index >= MAX_index)index = 0;
  11.     WCHAR* const UUID_ = TempUUID[index];
  12.     size_t size_uuid = wcsnlen_s(uuid, Max_length);
  13.     wcsncpy_s(UUID_ + 1, Max_length, uuid, size_uuid);
  14.     UUID_[0] = L'{';                   // '\u007b';
  15.     UUID_[size_uuid + 1] = L'}';      //'\u007d';
  16.     UUID_[size_uuid + 2] = L'\u0000';  // '\0';
  17.     //wprintf(L"%s\n", UUID_);PAUSE
  18.     return TempUUID[index];
  19. }
  20. const WCHAR* ToFullPath(const WCHAR* pRoot, const WCHAR* relativePath) {
  21.     const size_t MAX_index = 5, Max_length = 4000;
  22.     static WCHAR tempFullPath[MAX_index][Max_length];
  23.     static size_t index = 0;
  24.     if (++index >= MAX_index)index = 0;
  25.     wcscpy_s<Max_length>(tempFullPath[index], pRoot);
  26.     PathCchAppend(tempFullPath[index], Max_length, relativePath);
  27.     return tempFullPath[index];
  28. }
  29. //==================================================
  30. int Get_ServerInterface(TestParameter* ptr,
  31.     ServerInfo_Struct<LPCOLESTR>& MyServerString, PVOID* pRetVal) {
  32.     ServerInfo_Struct<BSTR> My_Server{
  33.         SysAllocString(ToFullPath(ptr->PathRoot,MyServerString.AssemblyPath)),
  34.         SysAllocString(MyServerString.TypeFullName),
  35.         SysAllocString(MyServerString.CreationMethod),
  36.         SysAllocString(MyServerString.CLSID),
  37.         SysAllocString(MyServerString.IID)
  38.     };
  39.     ICreationInstance* Ptr_Creation_Instance;
  40.     IUnknown* pIUnknown;
  41.     IID myiid2;
  42.     Ptr_Creation_Instance = (ICreationInstance*)ptr->ptr_to_Interface;
  43.     HR_(Ptr_Creation_Instance->Get_Interface3(&My_Server, (PVOID*)&pIUnknown), 31)
  44.         HR_(IIDFromString(AddCurlyBracket(My_Server.IID), &myiid2), 32)
  45.         HR_(pIUnknown->QueryInterface(myiid2, pRetVal), 33)
  46.         pIUnknown->Release();
  47.     return 0;
  48. }

  49. int Get_ServerInterface4(TestParameter* ptr,
  50.     ServerInfo_Struct<LPCOLESTR>& MyServerString, PVOID* pRetVal) {
  51.     IUnknown* pIUnknown;
  52.     IDispatch* pIDispatch;
  53.     VARIANT Variant;
  54.     IID myiid;
  55.     ICreationInstance* pICreationInstance;
  56.     ServerInfo_Struct<BSTR> My_Server{
  57.         SysAllocString(ToFullPath(ptr->PathRoot,MyServerString.AssemblyPath)),
  58.         SysAllocString(MyServerString.TypeFullName),
  59.         SysAllocString(MyServerString.CreationMethod),
  60.         SysAllocString(MyServerString.CLSID),
  61.         SysAllocString(MyServerString.IID)
  62.     };
  63.     pICreationInstance = (ICreationInstance*)ptr->ptr_to_Interface;
  64.     VariantInit(&Variant);
  65.     HR_(pICreationInstance->Get_Interface4(&My_Server, &Variant), 31)
  66.         HR_(IIDFromString(AddCurlyBracket(My_Server.IID), &myiid), 32)
  67.         if (V_VT(&Variant) == VT_UNKNOWN) {
  68.             pIUnknown = V_UNKNOWN(&Variant);
  69.             HR_(pIUnknown->QueryInterface(myiid, pRetVal), 33)
  70.                 HR_(pIUnknown->QueryInterface(IID_IDispatch, (void**)&pIDispatch), 34)
  71.                 printf("V_VT(&Variant) == VT_UNKNOWN\n");
  72.         }
  73.         else if (V_VT(&Variant) == VT_DISPATCH) {
  74.             pIDispatch = V_DISPATCH(&Variant);
  75.             HR_(pIDispatch->QueryInterface(myiid, pRetVal), 35)
  76.                 HR_(pIDispatch->QueryInterface(IID_IUnknown, (void**)&pIUnknown), 36)
  77.                 printf("V_VT(&Variant) == VT_DISPATCH\n");
  78.         }
  79.         else {
  80.             printf("V_VT(&_variant)= %d\n", V_VT(&Variant));
  81.             RETURN(39);
  82.         }
  83.     printf("(pIUnknown  = %p)\n(pIDispatch = %p)\n(*pRetVal   = %p)\n",
  84.         pIUnknown, pIDispatch, *pRetVal);
  85.     printf("(%d)pIUnknown->Release()\n", pIUnknown->Release());
  86.     printf("(%d)pIDispatch->Release()\n", pIDispatch->Release());
  87.     PAUSE
  88.         return 0;
  89. }
  90. void My_Message(HRESULT hr2, int errorCode, LPCWSTR file_, int Line_, const wchar_t* fn) {
  91.     if (FAILED(hr2)) {
  92.         IErrorInfo* pIErrorInfo = NULL;
  93.         HRESULT hr = GetErrorInfo(0, &pIErrorInfo);
  94.         _com_error hr_err(hr2);
  95.         SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE | FOREGROUND_RED);
  96.         printf(" %S\n Line=%i fn=%S\n", file_, Line_, fn);
  97.         printf("hr=%x (%S)\n", unsigned(hr2), hr_err.ErrorMessage());
  98.         if (SUCCEEDED(hr) && pIErrorInfo) {
  99.             BSTR Description, source;
  100.             pIErrorInfo->GetDescription(&Description);
  101.             pIErrorInfo->GetSource(&source);
  102.             printf("Description=%S\n", Description);
  103.             printf("Source=%S\n", source);
  104.             SysFreeString(Description); SysFreeString(source);
  105.             pIErrorInfo->Release();
  106.         }
  107.         SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
  108.             FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);

  109.         throw std::exception("Exception from procedure(My_Message)");
  110.     }
  111. }
  112. int My_RETURN(int retVal, LPCWSTR file_, int Line_, const wchar_t* fn) {
  113.     SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE);
  114.     printf(" %S\n Line=%i fn=%S\n", file_, Line_, fn);
  115.     printf("return value = %i\n", retVal);
  116.     SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
  117.         FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
  118.     return retVal;
  119. };
  120. int SetErrorInfo_Chen(const WCHAR* Description,
  121.     const WCHAR* source) {

  122.     ICreateErrorInfo* pICreateErrorInfo;
  123.     IErrorInfo* pIErrorInfo;
  124.     HRESULT hr;
  125.     hr = CreateErrorInfo(&pICreateErrorInfo);
  126.     if (SUCCEEDED(hr)) {
  127.         hr = pICreateErrorInfo->QueryInterface(IID_IErrorInfo, (void**)&pIErrorInfo);
  128.         if (SUCCEEDED(hr)) {
  129.             const  size_t size_MAX = 4000;
  130.             size_t size;
  131.             WCHAR* Tmp_Str = new WCHAR[size_MAX + 1];
  132.             hr = StringCchLengthW(Description, size_MAX, &size);
  133.             if (FAILED(hr) || size >= size_MAX)return -12;
  134.             StringCchCopyW(Tmp_Str, size_MAX, Description);

  135.             pICreateErrorInfo->SetDescription(Tmp_Str);

  136.             hr = StringCchLengthW(source, size_MAX, &size);
  137.             if (FAILED(hr) || size >= size_MAX)return -13;
  138.             StringCchCopyW(Tmp_Str, size_MAX, source);
  139.             pICreateErrorInfo->SetSource(Tmp_Str);
  140.             delete[]Tmp_Str;
  141.             SetErrorInfo(0, pIErrorInfo);
  142.             pIErrorInfo->Release();
  143.         }
  144.         else return -1;
  145.         pICreateErrorInfo->Release();
  146.     }
  147.     else return -2;
  148.     return 0;
  149. }


















  1. #include <iostream>
  2. namespace Chen { int My_Console_Main(const wchar_t* comment); }

  3. int main()
  4. {
  5.     std::cout << "Hello World!\n";
  6.     return Chen::My_Console_Main(L"Startup project with =====> CPP");
  7. }




  1. #if defined(_M_X64) && defined(_WIN64) && defined(_CONSOLE) && \
  2.     _MSVC_LANG >= 201703L 

  3. #include "TestParameter.h"
  4. #pragma comment(lib,Lib_Name_inside(..\x64\,My_Configuration,\Create_dotNET_Platform))
  5. //#pragma comment(linker,Raw_string(/ENTRY:mainCRTStartup))
  6. /*
  7. #pragma comment(linker,"/LIBPATH:C:\Users\Networker")
  8.  $(SolutionDir)= C:\Users\Networker\Desktop\CPP_Main_Test_Marshalling_Project\
  9.  $(ProjectDir)=  C:\Users\Networker\Desktop\CPP_Main_Test_Marshalling_Project\CPP_Main_Test_Marshalling_Project\
  10.  $(TargetDir)=   C:\Users\Networker\Desktop\CPP_Main_Test_Marshalling_Project\x64\Debug\
  11.  $(USERPROFIL)=  C:\Users\Networker
  12.  $(HOMEPATH)=      \Users\Networker
  13.  %(AdditionalLibraryDirectories)
  14. */


  15. #define AfxLoadLibrary  LoadLibraryW
  16. #define AfxFreeLibrary  FreeLibrary   

  17. #define CreationInstance_clsid  OLESTR("91DD12FD-4DBD-4B83-AC40-439E3B6393A1")
  18. #define CreationInstance_iid    OLESTR("85927839-0BB2-423B-97D6-89A2D4002519")
  19. #define LeadingLibrary_clsid    OLESTR("2B6E5DB5-CF45-40B8-8091-55027E408231")
  20. #define LeadingLibrary_IID      OLESTR("16142434-D1CF-4DC8-BD7B-7E5091058490")

  21. namespace Chen {
  22.     int My_Console_Main(const wchar_t* comment);

  23.     LPCWSTR LeadingLibraryRelativePath = Server_Name_w(LeadingLibraryForLoadingDLL\LeadingLibraryForLoadingDLL\bin\x64\,
  24.         My_Configuration, \net9.0\LeadingLibraryForLoadingDLL.dll);

  25.     LPCWSTR MyDll_CSharp = DLL_Name_w(CPP_DLL_Test_CSharp_Server\x64\,
  26.         My_Configuration, \CPP_DLL_Test_CSharp_Server.dll);

  27.     LPCWSTR MyDllname2_dotNET = DLL_Name_w(CPP_Dll_Test_Marshalling_dotNET\x64\,
  28.         My_Configuration, \CPP_Dll_Test_Marshalling_dotNET.dll);

  29.     LPCWSTR MyDllname3_dotNET = DLL_Name_w(CPP_DLL_Test_Multi_Interface\x64\,
  30.         My_Configuration, \CPP_DLL_Test_Multi_Interface.dll);

  31. #ifdef _DEBUG
  32.     LPCWSTR MyDllname =
  33.         Raw_string_w(MFC_DLL_Test_Marshalling\x64\Debug\MFCDLLTestMarshalling.dll);

  34.     LPCWSTR MyDllname2 =
  35.         Raw_string_w(CPP_Dll_Test_Marshalling\x64\Debug\CPP_Dll_Test_Marshalling.dll);

  36. #else
  37.     LPCWSTR MyDllname =
  38.         L"MFC_DLL_Test_Marshalling\\x64\\Release\\MFCDLLTestMarshalling.dll";

  39.     LPCWSTR MyDllname2 =
  40.         L"CPP_Dll_Test_Marshalling\\x64\\Release\\CPP_Dll_Test_Marshalling.dll";

  41. #endif // DEBUG

  42.     typedef struct {
  43.         LPCWSTR DLL_Path;
  44.         LPCSTR ProcName;
  45.         BOOL   MFC_DLL;
  46.         HMODULE hModule;
  47.     } ClientInfo_Struct;

  48.     ClientInfo_Struct ClientInfo_dotNET[]{
  49.        {
  50.            MyDll_CSharp,
  51.            "CPP_DLL_Test_CSharp_Server",
  52.            false
  53.        },{
  54.            MyDllname3_dotNET,
  55.            "CPP_DLL_Test_MultiInterface",
  56.            false
  57.        },{
  58.            MyDllname2_dotNET,
  59.            "CPP_DLL_Test_UnregisteredServer1",
  60.            false
  61.        },{
  62.            MyDllname2_dotNET,
  63.            "CPP_DLL_Test_UnregisteredServer2",
  64.            false
  65.        },{
  66.            MyDllname2_dotNET,
  67.            "CPP_DLL_Test_IXXXX",
  68.            false
  69.        }
  70.     };

  71.     ClientInfo_Struct ClientInfo[]{
  72.        {
  73.            MyDllname,
  74.            "MFC_DLL_Test_UnregisteredServer1",
  75.            true
  76.        },{
  77.            MyDllname,
  78.            "MFC_DLL_Test_UnregisteredServer2",
  79.            true
  80.        },{
  81.            MyDllname,
  82.            "MFC_DLL_Test_IXXXX",
  83.            true
  84.        },{
  85.            MyDllname2,
  86.            "CPP_DLL_Test_UnregisteredServer1",
  87.            false
  88.        },{
  89.            MyDllname2,
  90.            "CPP_DLL_Test_UnregisteredServer2",
  91.            false
  92.        },{
  93.            MyDllname2,
  94.            "CPP_DLL_Test_IXXXX",
  95.            false
  96.        }
  97.     };
  98.     int Get_CreationInstance_To_Create_FollowingServer(
  99.         LPCOLESTR LeadingLibrary_AbsolutePath,
  100.         LPCOLESTR CLSID_String,
  101.         LPCOLESTR IID_String);
  102.     void Get_CreationInstance_To_Create_UnregisteredServer(
  103.         LPCOLESTR CLSID_String,
  104.         LPCOLESTR IID_String);
  105.     int My_Test_Function_dotNET();
  106.     int My_Test_Function();
  107.     void MyEnumModules();
  108.     void ReleaseResource_dotNET();
  109.     void ReleaseResource();
  110.     void ErrorMessage(const CHAR* ERR_MSG);
  111.     namespace Debug_namespace {
  112.         inline namespace FileForDebug_namespace {
  113.             const size_t BufferSize_File = 5UI64 << 20;
  114.             class FileForDebug {
  115.                 bool OnDebug;
  116.                 bool IsSave;
  117.                 bool TooLarge;
  118.                 WCHAR  previousCHAR[BufferSize_File];
  119.                 WCHAR* pStart_Previous;
  120.                 size_t ReadSize, WriteSize;

  121.             public:
  122.                 FileForDebug();
  123.                 void compareData(const wchar_t* pStart, int size);
  124.                 void Save();
  125.             };
  126.             FileForDebug* MyFileForDebug;
  127.         }

  128.         inline namespace ExportedData_namespace {

  129.             const size_t BufferSize_Line = 1500UI64;
  130.             WCHAR MyLine[BufferSize_Line + 3];
  131.             size_t size;
  132.             va_list My_va_list;
  133.             void OutputFunction(const WCHAR* str, int size) {
  134.                 wprintf(L"%s", str);
  135.                 MyFileForDebug->compareData(str, size);
  136.             }
  137.             void Ellipsis() {
  138.                 size = BufferSize_Line - 1;
  139.                 *(MyLine + size++) = L'.';
  140.                 *(MyLine + size++) = L'.';
  141.                 *(MyLine + size++) = L'.';
  142.                 *(MyLine + size) = L'\0';
  143.                 OutputFunction(MyLine, (int)size);
  144.                 // printf("size= %I64u   BufferSize_Line=%I64u\n", 
  145.                 //  size, BufferSize_Line);system("pause");
  146.             }
  147.             void AppendNewline() {
  148.                 *(MyLine + size++) = L'\r';
  149.                 *(MyLine + size++) = L'\n';
  150.                 *(MyLine + size) = L'\0';
  151.                 OutputFunction(MyLine, (int)size);
  152.             }
  153.             void My_Write_Line(const WCHAR* format, va_list va_list) {
  154.                 size = _vsnwprintf_s(MyLine, BufferSize_Line, _TRUNCATE, format, va_list);
  155.                 if (size >= BufferSize_Line) Ellipsis();
  156.                 else AppendNewline();
  157.             }
  158.             void  MyWriteLine(const WCHAR* format, ...) {
  159.                 va_start(My_va_list, format);
  160.                 My_Write_Line(format, My_va_list);
  161.                 va_end(My_va_list);
  162.             }
  163.             void My_Write(const WCHAR* format, va_list va_list) {
  164.                 size = _vsnwprintf_s(MyLine, BufferSize_Line, _TRUNCATE, format, va_list);
  165.                 if (size >= BufferSize_Line) Ellipsis();
  166.                 else  OutputFunction(MyLine, (int)size);
  167.             }
  168.             void  MyWrite(const WCHAR* format, ...) {
  169.                 va_start(My_va_list, format);
  170.                 My_Write(format, My_va_list);
  171.                 va_end(My_va_list);
  172.             }
  173.         }


  174.     }
  175.     using Debug_namespace::MyWriteLine;
  176.     using Debug_namespace::MyFileForDebug;
  177.     using Debug_namespace::FileForDebug;

  178.     class MyException : public std::exception {
  179.         const char* ExceptionString;
  180.     public:
  181.         int errorNo;
  182.         MyException(const char* Exception_MSG, int errorNo) :
  183.             ExceptionString(Exception_MSG), errorNo(errorNo) {
  184.         }
  185.         virtual const char* what()const;
  186.     };
  187.     const char* MyException::what()const { return ExceptionString; }
  188. #define NTFS_MAX_PATH ( 32llu <<10)
  189.     WCHAR Current_Directory[NTFS_MAX_PATH];
  190.     WCHAR ProcessImageFileName[NTFS_MAX_PATH];
  191.     WCHAR ModuleFileName[NTFS_MAX_PATH];
  192.     WCHAR APP_Dir[NTFS_MAX_PATH];
  193.     WCHAR MyPathRoot[NTFS_MAX_PATH];
  194.     size_t MyPathRoot_Len;
  195.     HANDLE hThread;
  196.     DWORD ProcessID;
  197.     HANDLE hProcess;
  198.     IUnknown* pIUnknown_dotNET;
  199.     ICreationInstance* pICreationInstance_dotNET;
  200.     IUnknown* pIUnknown;
  201.     ICreationInstance* pICreationInstance;
  202.     const bool b_FreeLibrary = false;   //true;

  203.     void MyEnumModules() {
  204.         struct Modules
  205.         {
  206.             std::wstring Name;
  207.             HMODULE hModule;
  208.         };
  209.         const size_t hModuleSize = 1000;
  210.         static HMODULE hModule_Chen[hModuleSize];
  211.         static WCHAR ModuleName[NTFS_MAX_PATH];
  212.         if (!hProcess) return;

  213.         DWORD cbNeeded = 0;
  214.         std::vector<struct Modules> MyModules;
  215.         std::vector<struct Modules> Modules_system;
  216.         auto GetAllModules = [&] {
  217.             MyModules.clear(); Modules_system.clear();
  218.             if (!K32EnumProcessModules(hProcess, hModule_Chen,
  219.                 DWORD(hModuleSize * sizeof(HMODULE)), &cbNeeded)) {
  220.                 ErrorMessage("error: K32EnumProcessModules "); return;
  221.             }
  222.             int32_t CountOfModules = cbNeeded / sizeof(HMODULE);
  223.             for (int i = 0; i < CountOfModules; i++) {
  224.                 HMODULE hModule = hModule_Chen[i];
  225.                 GetModuleFileNameExW(hProcess, hModule, ModuleName, NTFS_MAX_PATH);
  226.                 if (_wcsnicmp(ModuleName, MyPathRoot, MyPathRoot_Len) == 0)
  227.                     MyModules.push_back(Modules(ModuleName, hModule));
  228.                 else Modules_system.push_back(Modules(ModuleName, hModule));
  229.             }
  230.             std::sort(MyModules.begin(), MyModules.end(), [](Modules A, Modules B)
  231.                 {return A.hModule < B.hModule; });
  232.             std::sort(Modules_system.begin(), Modules_system.end(), [](Modules A, Modules B)
  233.                 {return _wcsicmp(A.Name.c_str(), B.Name.c_str()) < 0; });
  234.             };
  235.         auto FreeLib = [&] {
  236.             for (int aa = 0; aa < ARRAYSIZE(ClientInfo_dotNET); aa++) {
  237.                 BOOL FreeLib_OK = (ClientInfo_dotNET[aa].MFC_DLL ?
  238.                     AfxFreeLibrary : FreeLibrary)(ClientInfo_dotNET[aa].hModule);
  239.                 LPCWSTR DLL_Name = ClientInfo_dotNET[aa].DLL_Path;
  240.                 if (FreeLib_OK)
  241.                     MyWriteLine(L"  FreeLibrary OK %s\n", DLL_Name);
  242.                 else
  243.                     MyWriteLine(L" error: FreeLibrary %s\n", DLL_Name);
  244.             }
  245.             for (int aa = 0; aa < ARRAYSIZE(ClientInfo); aa++) {
  246.                 BOOL FreeLib_OK = (ClientInfo[aa].MFC_DLL ?
  247.                     AfxFreeLibrary : FreeLibrary)(ClientInfo[aa].hModule);
  248.                 LPCWSTR DLL_Name = ClientInfo[aa].DLL_Path;
  249.                 if (FreeLib_OK)
  250.                     MyWriteLine(L"  FreeLibrary OK %s\n", DLL_Name);
  251.                 else
  252.                     MyWriteLine(L" error: FreeLibrary %s\n", DLL_Name);
  253.             }
  254.             };
  255.         auto DisplayModules = [&] {
  256.             auto SimplePtr = [](HMODULE xptr) { return UINT64(xptr) >> 16; };
  257.             int count = 0;
  258.             for (int j = 0; j < Modules_system.size(); j++) {
  259.                 Modules& t = Modules_system.at(j);
  260.                 printf("%2i %12llX %S\n", ++count, SimplePtr(t.hModule), t.Name.c_str());
  261.             }
  262.             for (int j = 0; j < MyModules.size(); j++) {
  263.                 Modules& t = MyModules.at(j);
  264.                 printf("%2i %12I64X %S\n", ++count, SimplePtr(t.hModule), t.Name.c_str() + MyPathRoot_Len);
  265.             }
  266.             printf("========= Count(%I32i) ==========\n", count);
  267.             };
  268.         GetAllModules();
  269.         FreeLib();
  270.         DisplayModules();
  271.         GetAllModules();
  272.         DisplayModules();
  273.     }
  274.     int AppInitialize() {
  275. #define MyFMT "\t%S\n"
  276.         GetCurrentDirectoryW(NTFS_MAX_PATH, Current_Directory);
  277.         printf("CurrentDir =" MyFMT, Current_Directory);
  278.         hThread = GetCurrentThread();
  279.         ProcessID = GetProcessIdOfThread(hThread);
  280.         hProcess = OpenProcess(
  281.             PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, ProcessID);
  282.         DWORD size = NTFS_MAX_PATH;
  283.         if (!QueryFullProcessImageNameW(hProcess, 0, ProcessImageFileName, &size))
  284.             throw MyException("QueryFullProcessImageNameW", -1004);
  285.         printf("APPFullName=" MyFMT, ProcessImageFileName);
  286.         if (GetModuleFileNameW(NULL, ModuleFileName, NTFS_MAX_PATH) >= NTFS_MAX_PATH)
  287.             throw MyException("GetModuleFileNameW", -1001);
  288.         printf("ModuleFileName=" MyFMT, ModuleFileName);
  289.         wcscpy_s(APP_Dir, NTFS_MAX_PATH, ProcessImageFileName);
  290.         PathCchRemoveFileSpec(APP_Dir, NTFS_MAX_PATH);
  291.         printf("APP_Dir=    " MyFMT, APP_Dir);
  292.         HR_(PathCchCombine(MyPathRoot, NTFS_MAX_PATH, APP_Dir, L"..\\..\\..\\"), 1002)
  293.             PathCchAddBackslash(MyPathRoot, NTFS_MAX_PATH);
  294.         printf("MyPathRoot=" MyFMT, MyPathRoot);
  295.         HR_(StringCchLengthW(MyPathRoot, NTFS_MAX_PATH, &MyPathRoot_Len), 1003)

  296.             // ---> For debug 
  297.             printf("RelativePath=\t%100S\n", LeadingLibraryRelativePath);
  298.         const WCHAR* pFullPath = ToFullPath(MyPathRoot, LeadingLibraryRelativePath);
  299.         if (PathFileExistsW(pFullPath))
  300.             printf("    FullPath= \t%100S\n", pFullPath);
  301.         else  printf("file not exist\t%100S\n", LeadingLibraryRelativePath);
  302.         // ---> For debug 
  303.         PAUSE
  304.             return 0;
  305.     }
  306.     int My_Console_Main(const wchar_t* comment) {
  307.         int rv;
  308.         printf("%S\n", comment);
  309.         printf("CommandLine=%S\n", GetCommandLineW());
  310.         if (AppInitialize())return -1;
  311.         try {
  312.             MyFileForDebug = new FileForDebug();
  313.             //HR_(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE), 1)
  314.             //HR_(OleInitialize(NULL), 2)

  315.             if (rv = Get_CreationInstance_To_Create_FollowingServer(
  316.                 ToFullPath(MyPathRoot, LeadingLibraryRelativePath),
  317.                 LeadingLibrary_clsid, LeadingLibrary_IID))return rv;
  318.             if (rv = My_Test_Function_dotNET())return rv;

  319.             printf("http://cheninnjer.blogspot.com\n");
  320.             system("pause");
  321.             Get_CreationInstance_To_Create_UnregisteredServer(
  322.                 CreationInstance_clsid, CreationInstance_iid);
  323.             if (rv = My_Test_Function())return rv;

  324.             system("pause");
  325.             MyEnumModules();
  326.             system("pause");
  327.             ReleaseResource_dotNET();
  328.             ReleaseResource();
  329.             system("pause");
  330.             //OleUninitialize();
  331.             //CoUninitialize();
  332.             MyFileForDebug->Save();
  333.         }
  334.         catch (const MyException& ex) {
  335.             printf("errorNo=%d\n", ex.errorNo);
  336.             ErrorMessage(ex.what());
  337.             return ex.errorNo;
  338.         }
  339.         catch (const std::exception& ex) {
  340.             ErrorMessage(ex.what());
  341.             return -1000;
  342.         }
  343.         return 0;
  344.     }

  345.     int Get_CreationInstance_To_Create_FollowingServer(
  346.         LPCOLESTR LeadingLibrary_AbsolutePath,
  347.         LPCOLESTR CLSID_String, LPCOLESTR IID_String) {
  348.         HRESULT CreateLeadingLibrary(
  349.             const wchar_t* LeadingLibrary_FullPath,
  350.             const wchar_t* param_LeadingLibrary_clsid, void** ppvoid);
  351.         HR_(CreateLeadingLibrary(LeadingLibrary_AbsolutePath,
  352.             CLSID_String, (void**)&pIUnknown_dotNET), 12)
  353.             IID MyIID;
  354.         HR_(IIDFromString(AddCurlyBracket(IID_String), &MyIID), 13)
  355.             HR_(pIUnknown_dotNET->QueryInterface(MyIID, (void**)&pICreationInstance_dotNET), 14)

  356.             if (pIUnknown_dotNET + 1 != pICreationInstance_dotNET)
  357.                 ErrorMessage("pIUnknown_dotNET + 1 != pICreationInstance_dotNET");
  358.         BSTR Description = NULL;
  359.         HR_(pICreationInstance_dotNET->GetDescription2(&Description), 17)
  360.             MyWriteLine(L"%s", Description);
  361.         ::SysFreeString(Description);
  362.         return 0;
  363.     }

  364.     void Get_CreationInstance_To_Create_UnregisteredServer(
  365.         LPCOLESTR CLSID_String, LPCOLESTR IID_String) {
  366.         HRESULT hr;
  367.         CLSID MyClsid;
  368.         hr = CLSIDFromString(AddCurlyBracket(CLSID_String), &MyClsid);
  369.         if (FAILED(hr))throw MyException("CLSIDFromString", -11);
  370.         hr = CoCreateInstance(MyClsid, NULL, CLSCTX_INPROC_SERVER,
  371.             IID_IUnknown, (LPVOID*)&pIUnknown);
  372.         if (FAILED(hr))throw MyException("CoCreateInstance", -12);
  373.         IID MyIID;
  374.         hr = IIDFromString(AddCurlyBracket(IID_String), &MyIID);
  375.         if (FAILED(hr))throw MyException("IIDFromString", -13);
  376.         hr = pIUnknown->QueryInterface(MyIID, (void**)&pICreationInstance);
  377.         if (FAILED(hr))throw MyException("QueryInterface", -14);

  378.         if (pIUnknown + 1 != pICreationInstance) {
  379.             ErrorMessage("pIUnknown + 1 ");
  380.         }
  381.         BSTR Description = ::SysAllocStringByteLen("", 5000);
  382.         if (!Description)throw MyException("SysAllocStringLen", -15);
  383.         hr = pICreationInstance->GetDescription(Description);
  384.         if (FAILED(hr)) {
  385.             ::SysFreeString(Description);
  386.             throw MyException("GetDescription", -16);
  387.         }
  388.         // printf("%d", (*(INT32*)Description));
  389.         MyWriteLine(L"%s", Description + 2);
  390.         ::SysFreeString(Description);
  391.         hr = pICreationInstance->GetDescription2(&Description);
  392.         if (FAILED(hr)) throw MyException("GetDescription2", -17);
  393.         MyWriteLine(L"%s", Description);
  394.         ::SysFreeString(Description);
  395.     }

  396.     int My_Test_Function_dotNET() {
  397.         int length = ARRAYSIZE(ClientInfo_dotNET);
  398.         for (int aa = 0; aa < length; aa++) {
  399.             HMODULE& hModule = ClientInfo_dotNET[aa].hModule;
  400.             const WCHAR* DLL_Absolute_Path = ToFullPath(MyPathRoot, ClientInfo_dotNET[aa].DLL_Path);
  401.             hModule = ClientInfo_dotNET[aa].MFC_DLL ?
  402.                 AfxLoadLibrary(DLL_Absolute_Path) : LoadLibraryW(DLL_Absolute_Path);
  403.             if (!hModule) {
  404.                 printf("Error: %S\n", DLL_Absolute_Path);
  405.                 RETURN(21)
  406.             }
  407.             using Test_UnregisteredServer = int (*)(TestParameter*);
  408.             Test_UnregisteredServer FunctionPointer =
  409.                 (Test_UnregisteredServer)GetProcAddress(hModule, ClientInfo_dotNET[aa].ProcName);
  410.             if (!FunctionPointer) {
  411.                 if (b_FreeLibrary) {
  412.                     ClientInfo_dotNET[aa].MFC_DLL ?
  413.                         AfxFreeLibrary(hModule) : FreeLibrary(hModule);
  414.                     hModule = NULL;
  415.                 }
  416.                 RETURN(22)
  417.             }
  418.             TestParameter MyParameter = {
  419.                  Debug_namespace::My_Write_Line,
  420.                  pICreationInstance_dotNET ,
  421.                  MyPathRoot
  422.             };
  423.             int rv = FunctionPointer(&MyParameter);
  424.             if (b_FreeLibrary) {
  425.                 ClientInfo_dotNET[aa].MFC_DLL ?
  426.                     AfxFreeLibrary(hModule) : FreeLibrary(hModule);
  427.                 hModule = NULL;
  428.             }
  429.             if (rv)RETURN(rv)
  430.         }
  431.         return 0;
  432.     }

  433.     int My_Test_Function() {
  434.         int length = ARRAYSIZE(ClientInfo);
  435.         for (int aa = 0; aa < length; aa++) {
  436.             HMODULE& hModule = ClientInfo[aa].hModule;
  437.             const WCHAR* DLL_Absolute_Path = ToFullPath(MyPathRoot, ClientInfo[aa].DLL_Path);
  438.             hModule = ClientInfo[aa].MFC_DLL ?
  439.                 AfxLoadLibrary(DLL_Absolute_Path) : LoadLibraryW(DLL_Absolute_Path);
  440.             if (!hModule) {
  441.                 printf("Error: %S\n", DLL_Absolute_Path);
  442.                 RETURN(21)
  443.             }
  444.             using Test_UnregisteredServer = int (*)(TestParameter*);
  445.             Test_UnregisteredServer FunctionPointer =
  446.                 (Test_UnregisteredServer)GetProcAddress(hModule, ClientInfo[aa].ProcName);
  447.             if (!FunctionPointer) {
  448.                 if (b_FreeLibrary) {
  449.                     ClientInfo[aa].MFC_DLL ?
  450.                         AfxFreeLibrary(hModule) : FreeLibrary(hModule);
  451.                     hModule = NULL;
  452.                 }
  453.                 RETURN(22)
  454.             }
  455.             TestParameter MyParameter = {
  456.                  Debug_namespace::My_Write_Line,
  457.                  pICreationInstance ,
  458.                  MyPathRoot
  459.             };
  460.             int rv = FunctionPointer(&MyParameter);
  461.             if (b_FreeLibrary) {
  462.                 ClientInfo[aa].MFC_DLL ?
  463.                     AfxFreeLibrary(hModule) : FreeLibrary(hModule);
  464.                 hModule = NULL;
  465.             }
  466.             if (rv)RETURN(rv);
  467.         }
  468.         return 0;
  469.     }
  470.     void ReleaseResource_dotNET() {
  471.         if (!pIUnknown_dotNET || !pICreationInstance_dotNET)return;
  472.         HRESULT hr;

  473.         IDispatch* pIDispatch_dotNET;
  474.         hr = pIUnknown_dotNET->QueryInterface(IID_IDispatch, (void**)&pIDispatch_dotNET);
  475.         if (FAILED(hr))
  476.             ErrorMessage("QueryInterface (IID_IDispatch) ");
  477.         else
  478.             printf("   %p(%d)pIDispatch_dotNET\n", pIDispatch_dotNET, pIDispatch_dotNET->Release());
  479.         printf("   %p(%d)pIUnknown_dotNET\n", pIUnknown_dotNET, pIUnknown_dotNET->Release());
  480.         printf("   %p(%d)pICreationInstance_dotNET\n", pICreationInstance_dotNET,
  481.             pICreationInstance_dotNET->Release());
  482.     }

  483.     void ReleaseResource() {
  484.         if (!pIUnknown || !pICreationInstance)return;
  485.         HRESULT hr;
  486.         IDispatch* pIDispatch;
  487.         hr = pIUnknown->QueryInterface(IID_IDispatch, (void**)&pIDispatch);
  488.         if (FAILED(hr))
  489.             ErrorMessage("QueryInterface (IID_IDispatch) ");
  490.         else
  491.             printf("   %p(%d)pIDispatch\n", pIDispatch, pIDispatch->Release());
  492.         printf("   %p(%d)pIUnknown\n", pIUnknown, pIUnknown->Release());
  493.         printf("   %p(%d)pICreationInstance\n", pICreationInstance,
  494.             pICreationInstance->Release());
  495.     }
  496.     void ErrorMessage(const CHAR* ERR_MSG) {
  497.         MessageBeep(MB_ICONERROR);
  498.         HANDLE herr = GetStdHandle(STD_ERROR_HANDLE);
  499.         CONSOLE_SCREEN_BUFFER_INFO Screen_Buf;
  500.         GetConsoleScreenBufferInfo(herr, &Screen_Buf);
  501.         SetConsoleTextAttribute(herr, FOREGROUND_RED);
  502.         fprintf(stderr, "%s\n", ERR_MSG);

  503.         SetConsoleTextAttribute(herr, FOREGROUND_GREEN);
  504.         int NoOpenStream = _flushall();//printf("No=%d\n", NoOpenStream);
  505.         PAUSE
  506.             SetConsoleTextAttribute(herr, Screen_Buf.wAttributes);
  507.     }

  508. #define MyDebugFilename "MyFileForDebug.txt"
  509. #define _WMyDebugFilename OLESTR("MyFileForDebug.txt")
  510.     Debug_namespace::FileForDebug::FileForDebug() :
  511.         IsSave(false),
  512.         OnDebug(false),
  513.         TooLarge(false),
  514.         previousCHAR{}, WriteSize(0), ReadSize(0),
  515.         pStart_Previous(previousCHAR)
  516.     {
  517.         FILE* _Stream = NULL;
  518.         errno_t errNo = _wfopen_s(&_Stream, ToFullPath(APP_Dir, _WMyDebugFilename), L"r,ccs=UNICODE");
  519.         if (!_Stream || errNo) {
  520.             ErrorMessage("Unable to open " MyDebugFilename);
  521.             return;
  522.         }
  523.         ReadSize = fread_s(previousCHAR, sizeof(previousCHAR),
  524.             sizeof(previousCHAR[0]), BufferSize_File, _Stream);
  525.         fclose(_Stream);
  526.         OnDebug = true;
  527.         printf("BufferSize_File=%lluMB ReadFileSize=%llu\n", (BufferSize_File >> 20), ReadSize);
  528.         system("pause");
  529.     }
  530.     void Debug_namespace::FileForDebug::Save() {
  531.         if (IsSave || OnDebug) return;
  532.         FILE* _Stream = NULL;
  533.         errno_t errNo = _wfopen_s(&_Stream, ToFullPath(APP_Dir, _WMyDebugFilename), L"w,ccs=UNICODE");
  534.         if (_Stream && !errNo) {
  535.             WriteSize = fwrite(previousCHAR, sizeof(previousCHAR[0]),
  536.                 pStart_Previous - previousCHAR, _Stream);
  537.             fclose(_Stream);
  538.             IsSave = true;
  539.             printf("BufferSize_File=%I64u  ReadFileSize= %I64u\n", BufferSize_File, ReadSize);
  540.             printf("BufferSize_File=%I64u  WriteFileSize=%I64u\n", BufferSize_File, WriteSize);
  541.             PAUSE
  542.         }
  543.     }
  544.     void  Debug_namespace::FileForDebug::compareData(const wchar_t* pStart, int size) {
  545.         if (TooLarge)return;
  546.         if (pStart_Previous + size > previousCHAR + BufferSize_File) {
  547.             TooLarge = true;
  548.             ErrorMessage("Output data Too Large in compareData");
  549.             return;
  550.         }
  551.         if (OnDebug) {
  552.             int ret = memcmp(pStart, pStart_Previous, sizeof(wchar_t) * size);
  553.             if (ret) {
  554.                 OnDebug = false;
  555.                 ErrorMessage("The output is not consistent with previous one");
  556.             }
  557.             else { pStart_Previous += size; return; }
  558.         }
  559.         if (memcpy_s(pStart_Previous, size * sizeof(wchar_t),
  560.             pStart, size * sizeof(wchar_t))) {
  561.             ErrorMessage("memcpy_s");
  562.         }
  563.         pStart_Previous += size;
  564.     }

  565. };
  566. #endif 


















  1. #pragma once

  2. using namespace System;

  3. namespace CreatedotNETPlatform {
  4. public ref class Class1
  5. {
  6. // TODO: Add your methods for this class here.
  7. void MyInspection(void);
  8. String^ LeadingLibPath;
  9. Reflection::Assembly^ Assembly_Leading_Library;
  10. Type^ clsid_type;
  11. public:
  12. long Create_dotNET_Platform(
  13. const wchar_t* LeadingLib,
  14. const wchar_t* clsid,
  15. void** pIUnknown);
  16. };
  17. }


  1. #include "pch.h"

  2. #include "TestParameter.h"
  3. #include "Create_dotNET_Platform.h"

  4. __declspec(dllexport) HRESULT CreateLeadingLibrary(
  5. const wchar_t* LeadingLibPath,
  6. const wchar_t* clsid_Str,
  7. void** pIUnknown)
  8. {

  9. long errorCode = (
  10. gcnew CreatedotNETPlatform::Class1()
  11. )->Create_dotNET_Platform(LeadingLibPath, clsid_Str, pIUnknown);
  12. if (errorCode)return (HRESULT)(errorCode + (7 << 29));
  13. return S_OK;
  14. }

  15. using namespace System::Reflection;
  16. using namespace System::Runtime::InteropServices;
  17. namespace CreatedotNETPlatform {
  18. long Class1::Create_dotNET_Platform(
  19. const wchar_t* Leading_Library_Path,
  20. const wchar_t* clsid_str,
  21. void** pIunknown)
  22. {
  23. size_t String_Len;
  24. try {
  25. //throw gcnew System::FormatException("MyTest");
  26. if (FAILED(StringCchLengthW(Leading_Library_Path, 4000, &String_Len))) return 1;
  27. LeadingLibPath = gcnew String(Leading_Library_Path, 0, (int)String_Len);
  28. Assembly_Leading_Library = Reflection::Assembly::LoadFrom(LeadingLibPath);
  29. if (FAILED(StringCchLengthW(clsid_str, 200, &String_Len))) return 2;
  30. Guid clsid = Guid::Parse(gcnew String(clsid_str, 0, (int)String_Len));
  31. Collections::Generic::IEnumerable<Type^>^ IEnumateType =
  32. Assembly_Leading_Library->ExportedTypes;
  33. for each (clsid_type in IEnumateType)
  34. if (clsid_type->GUID == clsid) {
  35. MyInspection();
  36. Object^ obj = Activator::CreateInstance(clsid_type);
  37. if (obj) {
  38. *pIunknown = Marshal::GetIUnknownForObject(obj).ToPointer();
  39. return 0;
  40. }
  41. else return 0X9;
  42. }
  43. return 0xb;
  44. }
  45. catch (System::IO::FileNotFoundException^ const f) {
  46. System::String^ des = L" FileNotFound ->" + f->FileName;
  47. System::IntPtr ptr = Marshal::StringToHGlobalUni(des);
  48. SetErrorInfo_Chen((const WCHAR*)ptr.ToInt64(), __FUNCTIONW__);
  49. Marshal::FreeHGlobal(ptr);
  50. return 0x100;
  51. }
  52. catch (System::Exception^ const ex) {
  53. System::String^ des = L" Exception Message ->" + ex->Message;
  54. System::IntPtr ptr = Marshal::StringToHGlobalUni(des);
  55. SetErrorInfo_Chen((const WCHAR*)ptr.ToInt64(), __FUNCTIONW__);
  56. Marshal::FreeHGlobal(ptr);
  57. return 0x333;
  58. }
  59. }
  60. void Class1::MyInspection(void) {
  61. MethodInfo^ Get_Interface3;
  62. array<ParameterInfo^>^ MyParams;
  63. //throw gcnew Exception("My Exception");
  64. Console::WriteLine("*************************");
  65. Console::WriteLine("__cplusplus_cli = " + __cplusplus_cli);
  66. Console::WriteLine(__func__);
  67. Console::WriteLine(" __FUNCSIG__ =      "  __FUNCSIG__);
  68. Console::WriteLine(
  69. "FrameworkDescription is " +
  70. Runtime::InteropServices::RuntimeInformation::FrameworkDescription
  71. );
  72. Console::WriteLine("Leading Library path = " + LeadingLibPath);
  73. if (!clsid_type)goto out;
  74. Console::WriteLine("CLSID    = " + clsid_type->GUID);
  75. Console::WriteLine("FullName = " + clsid_type->FullName);
  76. Get_Interface3 = clsid_type->GetMethod("Get_Interface3");
  77. if (!Get_Interface3) goto out;
  78. Console::WriteLine("Get_Interface3");
  79. MyParams = Get_Interface3->GetParameters();
  80. for each (ParameterInfo ^ MyParam in MyParams) {
  81. Console::WriteLine("Position:" + MyParam->Position.ToString() +
  82. "  TypeName(" + MyParam->ParameterType->Name + ")");
  83. }
  84. out:
  85. Console::WriteLine("*************************");
  86. Console::ReadKey();
  87. }
  88. }






















  1. #If TARGET = "library" And PLATFORM = "x64" Then
  2. Option Strict On
  3. Imports System.Reflection
  4. Imports System.Runtime.InteropServices
  5. Imports System.Text

  6. <ComClass(LeadingLibrary.ClassId, LeadingLibrary.IID_LeadingLibrary)>
  7. Public Class LeadingLibrary

  8.     Public Const ClassId As String = "2B6E5DB5-CF45-40B8-8091-55027E408231"
  9.     Public Const IID_LeadingLibrary As String = "16142434-D1CF-4DC8-BD7B-7E5091058490"

  10.     Sub Get_Interface3(<[In]> AssemblyInfo_ptr As IntPtr,
  11.                        <Out> ByRef ppVoid As IntPtr)
  12.         'Throw New MyException(&HE0000004, "Don't use Get_Interface3")
  13.         Try
  14.             MyAssemblyInfo =
  15.               Marshal.PtrToStructure(Of AssemblyInfo_Struct)(AssemblyInfo_ptr)
  16.             AssemblyPath =
  17.               Marshal.PtrToStringBSTR(MyAssemblyInfo.AssemblyPath)
  18.             UnregisteredServerAssembly = Assembly.LoadFrom(AssemblyPath)
  19.             InvokeCreationMethod()
  20.             ppVoid = Marshal.ReadIntPtr(ppvoid_temp)
  21.         Catch ex As IO.FileNotFoundException
  22.             Throw New MyException(ex.HResult, AssemblyPath & " Cannot be found")
  23.         Catch ex As Exception
  24.             Throw New MyException(ex.HResult, "Unknown Exception -->" & ex.Message)
  25.         End Try
  26.         If ppVoid = IntPtr.Zero Then
  27.             Throw New MyException(&HE0000222, "ppVoid = ZERO")
  28.         End If
  29.     End Sub
  30.     Sub GetDescription(Description As IntPtr)
  31.         Dim Source As New StringBuilder(
  32.          "This is a  leadingLibrary")
  33.         Source.AppendLine()
  34.         Source.AppendLine("HRESULT value reference : winerror.h")
  35.         Source.AppendLine(
  36.            "My location is " &
  37.                System.Reflection.Assembly.GetExecutingAssembly.Location)
  38.         Source.AppendLine(
  39.            "FrameworkDescription is " &
  40.         System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription
  41.         )

  42.         Dim MainType As Type = GetType(LeadingLibrary)
  43.         Dim ThisModule As Reflection.Module = MainType.Module
  44.         Dim peKind As PortableExecutableKinds
  45.         Dim machine As ImageFileMachine
  46.         ThisModule.GetPEKind(peKind, machine)
  47.         Source.AppendFormat("machine={0:G} peKind={1:G}", machine, peKind)
  48.         Source.Append(ChrW(0))
  49.         Dim BufferSize As Int32 = Marshal.ReadInt32(Description - 4)
  50.         If BufferSize < (4 + Source.Length * 2) Then
  51.             Marshal.WriteInt32(Description, 0)
  52.         End If
  53.         Marshal.Copy(Source.ToString().ToCharArray(), 0,
  54.                      Description + 4, Source.Length)
  55.         Marshal.WriteInt32(Description, (Source.Length - 1) * 2)
  56.     End Sub
  57.     Sub GetDescription2(<Out> ByRef Description As String)
  58.         Dim MainType As Type = GetType(LeadingLibrary)
  59.         Dim ThisModule As Reflection.Module = MainType.Module
  60.         Dim peKind As PortableExecutableKinds
  61.         Dim machine As ImageFileMachine
  62.         ThisModule.GetPEKind(peKind, machine)
  63.         Dim Source As New StringBuilder()
  64.         Source.AppendLine("This is a LeadingLibrary")
  65.         Source.AppendLine("HRESULT value reference : winerror.h")
  66.         Source.AppendLine("My location is " &
  67.      System.Reflection.Assembly.GetExecutingAssembly.Location)
  68.         Source.AppendLine("FrameworkDescription is " &
  69.      System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription)
  70.         Source.Append($"machine={machine} peKind={peKind}")
  71.         Description = Source.ToString()
  72.     End Sub

  73.     Sub Get_Interface4(<[In]> AssemblyInfo_ptr As IntPtr,
  74.                        <Out> ByRef ppVoid_object As Object)
  75.         Try
  76.             MyAssemblyInfo =
  77.               Marshal.PtrToStructure(Of AssemblyInfo_Struct)(AssemblyInfo_ptr)
  78.             AssemblyPath =
  79.               Marshal.PtrToStringBSTR(MyAssemblyInfo.AssemblyPath)
  80.             UnregisteredServerAssembly = Assembly.LoadFrom(AssemblyPath)
  81.             InvokeCreationMethod4()
  82.             ppVoid_object = ppvoid_temp_object
  83.         Catch ex As IO.FileNotFoundException
  84.             Throw New MyException(ex.HResult, AssemblyPath & " Cannot be found")
  85.         Catch ex As Exception
  86.             Throw New MyException(ex.HResult, "Unknown Exception -->" & ex.Message)
  87.         End Try
  88.         If ppVoid_object Is Nothing Then
  89.             Throw New MyException(&HE0000222, "ppVoid_object Is Nothing")
  90.         End If
  91.     End Sub

  92.     '============================================================
  93.     Public Sub New()
  94.         MyBase.New()
  95.         ppvoid_temp = Marshal.AllocCoTaskMem(12)
  96.     End Sub
  97.     Protected Sub Finallize()
  98.         Marshal.FreeCoTaskMem(ppvoid_temp)
  99.     End Sub
  100.     Private Class MyException
  101.         Inherits Exception
  102.         Sub New(errorcode As Int32, Message As String)
  103.             MyBase.New(Message)
  104.             HResult = errorcode
  105.         End Sub
  106.     End Class
  107.     Dim MyAssemblyInfo As AssemblyInfo_Struct
  108.     Private Structure AssemblyInfo_Struct
  109.         Public AssemblyPath As IntPtr
  110.         Public TypeFullname As IntPtr
  111.         Public CreationMethod As IntPtr
  112.         Public CLSID As IntPtr
  113.         Public IID As IntPtr
  114.     End Structure
  115.     Dim AssemblyPath As String
  116.     Dim TypeFullname As String
  117.     Dim CreationMethod As String
  118.     Dim CLSID_string As String
  119.     Dim IID_string As String
  120.     ReadOnly ppvoid_temp As IntPtr
  121.     Dim ppvoid_temp_object As Object
  122.     Dim UnregisteredServerAssembly As Assembly
  123.     Dim IEnumateType As IEnumerable(Of Type)
  124.     Private Sub InvokeCreationMethod()
  125.         Dim Type_CLSID As Guid
  126.         CLSID_string =
  127.          Marshal.PtrToStringBSTR(MyAssemblyInfo.CLSID)
  128.         If Not Guid.TryParse(CLSID_string, Type_CLSID) Then
  129.             Throw New Exception($"Error:CLSID({CLSID_string})")
  130.         End If
  131.         IEnumateType = UnregisteredServerAssembly.ExportedTypes
  132.         For Each MyTypeInfo As TypeInfo In IEnumateType
  133.             If Type_CLSID <> MyTypeInfo.GUID Then Continue For
  134.             TypeFullname = Marshal.PtrToStringBSTR(MyAssemblyInfo.TypeFullname)
  135.             If TypeFullname <> MyTypeInfo.FullName Then
  136.                 Dim FG As ConsoleColor = Console.ForegroundColor
  137.                 Console.ForegroundColor = ConsoleColor.Green
  138.                 Console.WriteLine("In     :" & TypeFullname)
  139.                 Console.WriteLine("MyType :" & MyTypeInfo.FullName)
  140.                 Console.ForegroundColor = FG
  141.             End If
  142.             Dim UnregisteredServerType As Type = MyTypeInfo.AsType
  143.             CreationMethod =
  144.                 Marshal.PtrToStringBSTR(MyAssemblyInfo.CreationMethod)
  145.             Dim CreateObject_Chen As MethodInfo =
  146.                   UnregisteredServerType.GetMethod(CreationMethod)
  147.             If CreateObject_Chen Is Nothing Then
  148.                 Throw New Exception($"Error:CreateMethod({CreationMethod})")
  149.             End If
  150.             IID_string = Marshal.PtrToStringBSTR(MyAssemblyInfo.IID)
  151.             Dim Interface_IID As Guid
  152.             If Not Guid.TryParse(IID_string, Interface_IID) Then
  153.                 Throw New Exception($"Error:Interface_IID({IID_string})")
  154.             End If
  155.             Dim args() As Object = {Interface_IID, ppvoid_temp, New IntPtr(12345)}
  156.             CreateObject_Chen.Invoke(Nothing, args)
  157.             Exit Sub
  158.         Next
  159.         Throw New Exception("Error:CLSID not found")
  160.     End Sub
  161.     Private Sub InvokeCreationMethod4()
  162.         ' Console.WriteLine("InvokeCreationMethod4()")
  163.         Dim Type_CLSID As Guid
  164.         CLSID_string = Marshal.PtrToStringBSTR(MyAssemblyInfo.CLSID)
  165.         If Not Guid.TryParse(CLSID_string, Type_CLSID) Then
  166.             Throw New Exception($"Error:CLSID({CLSID_string})")
  167.         End If
  168.         IEnumateType = UnregisteredServerAssembly.ExportedTypes
  169.         For Each MyTypeInfo As TypeInfo In IEnumateType
  170.             If Type_CLSID <> MyTypeInfo.GUID Then Continue For
  171.             TypeFullname = Marshal.PtrToStringBSTR(MyAssemblyInfo.TypeFullname)
  172.             If TypeFullname <> MyTypeInfo.FullName Then
  173.                 Dim FG As ConsoleColor = Console.ForegroundColor
  174.                 Console.ForegroundColor = ConsoleColor.Green
  175.                 Console.WriteLine("In     :" & TypeFullname)
  176.                 Console.WriteLine("MyType :" & MyTypeInfo.FullName)
  177.                 Console.ForegroundColor = FG
  178.             End If
  179.             Dim UnregisteredServerType As Type = MyTypeInfo.AsType
  180.             CreationMethod = Marshal.PtrToStringBSTR(MyAssemblyInfo.CreationMethod)
  181.             Dim CreateObject4_Chen As MethodInfo =
  182.                   UnregisteredServerType.GetMethod(CreationMethod)
  183.             If CreateObject4_Chen Is Nothing Then
  184.                 Throw New Exception($"Err:CreateObject4_Chen Is Nothing({CreationMethod})")
  185.             End If
  186.             IID_string = Marshal.PtrToStringBSTR(MyAssemblyInfo.IID)
  187.             Dim Interface_IID As Guid
  188.             If Not Guid.TryParse(IID_string, Interface_IID) Then
  189.                 Throw New Exception($"Error:Interface_IID({IID_string})")
  190.             End If
  191.             Dim args() As Object = {Interface_IID, New IntPtr(12345)}
  192.             ppvoid_temp_object = CreateObject4_Chen.Invoke(Nothing, args)
  193.             Exit Sub
  194.         Next MyTypeInfo
  195.         Throw New Exception("Error:CLSID not found")
  196.     End Sub

  197. End Class
  198. #End If






















  1. #include "pch.h"

  2. #if defined(_M_X64) && defined(_WIN64) && defined(_WINDOWS) && \
  3.      _MSVC_LANG >= 202002L &&  defined(_USRDLL)
  4. #include "TestParameter.h"    

  5. LPCOLESTR MyServerName = Server_Name_w(
  6.     CSharp_Server_For_Testing\CSharp_Server_For_Testing\bin\x64\,
  7.     My_Configuration, \net9.0\CSharp_Server_For_Testing.dll);

  8. __interface IMyTest : IDispatch {
  9.     HRESULT Hello(INT32 id, BSTR str);
  10. };

  11. __interface IMyTest2 : IDispatch {
  12.     HRESULT Hello2(BSTR* str);
  13.     HRESULT Test_in_out_ref(
  14.         INT32* ref_int32,
  15.         INT32 int32_2,
  16.         INT32* out_int32,
  17.         void* ptr);
  18.     HRESULT Test_ref_readonly(INT32* ref_int32, void* ptr);
  19. };

  20. __interface IMyTest3 : IDispatch {
  21.     HRESULT Hello3(BSTR* str);
  22. };

  23. HRESULT pfnDeferredFillIn(EXCEPINFO* pEx) {
  24.     for (int aa = 1; aa < 20; aa++) printf("Description\n");
  25.     PAUSE
  26.         //printf("Description=%S\n", pEx->bstrDescription);
  27.         return S_OK;
  28. }
  29. int Invoke_Hello_method(ExportedData& ED, IMyTest* pIMyTest) {
  30.     CComBSTR str = SysAllocString(L"=========== Hello method ==========");

  31.     HRESULT hr;
  32.     auto  Invoke_Hello = [&](int ID) {
  33.         hr = pIMyTest->Hello(ID, str);
  34.         ED.WriteLine(L"hr = 0X%X", hr);
  35.         CComPtr<IErrorInfo> MypError;
  36.         hr = GetErrorInfo(0, &MypError);
  37.         if (SUCCEEDED(hr)) {
  38.             CComBSTR Description, source;
  39.             MypError->GetDescription(&Description);
  40.             MypError->GetSource(&source);
  41.             ED.WriteLine(L"Description=%s", Description);
  42.             ED.WriteLine(L"Source=%s", source);
  43.         }
  44.         };
  45.     Invoke_Hello(1);
  46.     Invoke_Hello(222);
  47.     DISPID dispid_Hello;
  48.     LPCOLESTR names = L"Hello";
  49.     HR_(pIMyTest->GetIDsOfNames(IID_NULL, const_cast<LPOLESTR*>(&names), 1,
  50.         LOCALE_USER_DEFAULT, &dispid_Hello), -1234)
  51.         ED.WriteLine(L"========== DISPID=%d ===========\n", dispid_Hello);


  52.     for (int ID = 111; ID <= 222; ID += 111) {
  53.         VARIANTARG varg[2], pRetValue;
  54.         UINT puArgErr = 0;
  55.         DISPPARAMS DispParams{
  56.           .rgvarg = varg,
  57.           .rgdispidNamedArgs = new DISPID[]{ },
  58.           .cArgs = 2,
  59.           .cNamedArgs = 0,
  60.         };
  61.         VariantInit(varg);
  62.         V_VT(varg) = VT_BSTR; V_BSTR(varg) = str; //in reverse order
  63.         VariantInit(varg + 1);
  64.         V_VT(varg + 1) = VT_I4; V_I4(varg + 1) = ID;
  65.         VariantInit(&pRetValue);
  66.         V_VT(&pRetValue) = VT_I4;
  67.         EXCEPINFO ex = {
  68.             .pfnDeferredFillIn = pfnDeferredFillIn,
  69.             .scode = (LONG)0XE0012345
  70.         };
  71.         hr = pIMyTest->Invoke(dispid_Hello,
  72.             IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD,
  73.             &DispParams, &pRetValue, &ex, &puArgErr);
  74.         printf("puArgErr=%d MyHRESULT=0x%x\n", puArgErr, hr);
  75.         if (V_VT(&pRetValue) != VT_EMPTY)
  76.             printf(" type=%d RetValue=0x%x\n", V_VT(&pRetValue), V_I4(&pRetValue));

  77.         if (hr == DISP_E_EXCEPTION) {
  78.             printf("ex.wCode=%d ex.scode=0X%X \n", ex.wCode, ex.scode);
  79.             printf("ex.bstrSource: %S  \n", ex.bstrSource);
  80.             hr = ex.scode;
  81.         }
  82.         ED.WriteLine(L"hr = 0X%X", hr);
  83.     }
  84.     return 0;
  85. }
  86. class MyEventTestClass :public IDispatch
  87. {
  88.     LONG refCount;
  89. public:
  90.     MyEventTestClass() : refCount(0) {}
  91.     HRESULT QueryInterface(REFIID iid, void** ppvoid) {
  92.         printf("QueryInterface\n");
  93.         LPOLESTR  iid_str;
  94.         HR_(StringFromIID(iid, &iid_str), -1212)
  95.             printf("IID=%S\n", iid_str);
  96.         CoTaskMemFree(iid_str);
  97.         PAUSE
  98.             if (iid == IID_IUnknown) {
  99.                 printf(" IID_IUnknown\n");
  100.                 *ppvoid = dynamic_cast<IUnknown*>(this);
  101.                 refCount++;
  102.                 return S_OK;
  103.             }
  104.         if (iid == IID_INoMarshal) {
  105.             printf(" IID_INoMarshal\n");
  106.             return E_NOINTERFACE;
  107.         }
  108.         if (iid == IID_IAgileObject) {
  109.             printf(" IID_IAgileObject\n");
  110.             return E_NOINTERFACE;
  111.         }
  112.         if (iid == IID_IMarshal) {
  113.             printf(" IID_IMarshal\n");
  114.             return E_NOINTERFACE;
  115.         }
  116.         printf("  QueryInterface error\n");
  117.         return S_FALSE;
  118.     }
  119.     ULONG  AddRef() {
  120.         refCount++;
  121.         printf("AddRef(%d) \n", refCount);
  122.         PAUSE
  123.             return refCount;
  124.     }
  125.     ULONG Release() {
  126.         refCount--;
  127.         printf("Release(%d) \n", refCount);
  128.         PAUSE
  129.             return refCount;
  130.     }
  131.     HRESULT GetTypeInfoCount(UINT* pctInfo) {
  132.         printf("GetTypeInfoCount\n");
  133.         PAUSE

  134.             if (!pctInfo)return E_POINTER;
  135.         ITypeInfo* pITypeInfo;
  136.         //TYPEINfoHelp
  137.         *pctInfo = 0;
  138.         return S_FALSE;
  139.     }
  140.     HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) {
  141.         printf("GetTypeInfo\n");
  142.         PAUSE
  143.             return 0;
  144.     }
  145.     HRESULT GetIDsOfNames(REFIID iid, LPOLESTR* str,
  146.         UINT cNames, LCID lcid, DISPID* rgDispID) {
  147.         printf("GetIDsOfNames\n");
  148.         PAUSE
  149.             return S_OK;
  150.     }
  151.     HRESULT Invoke(DISPID dispidMember, REFIID iid, LCID lcid, WORD flag,
  152.         DISPPARAMS* dispParam,
  153.         VARIANT* pVariant, EXCEPINFO* pExcepInfo, UINT* puArg) {
  154.         printf("Invoke\n");
  155.         PAUSE
  156.             return 0;
  157.     }
  158. };
  159. __interface  IClass1Events : IDispatch {};
  160. static int Test_Event(IMyTest* pIMyTest) {
  161.     HRESULT hr;
  162.     LPCOLESTR IDD_Event = (LPCOLESTR)OLESTR("3AAEFAB5-6DC7-49FD-A658-44A8DEF91F02");
  163.     IClass1Events* pIClass1Events = NULL;
  164.     IID myiid2;
  165.     HR_(IIDFromString(AddCurlyBracket(IDD_Event), &myiid2), -32)
  166.         HR_(pIMyTest->QueryInterface(myiid2, (void**)&pIClass1Events), -33)
  167.         printf("------------ Event -------------\n");
  168.     DISPID DispID_add_MyTestFun;
  169.     LPCOLESTR names = L"add_Event_MyTestFun";
  170.     HR_(pIClass1Events->GetIDsOfNames(IID_NULL, (LPOLESTR*)&names, 1,
  171.         LOCALE_USER_DEFAULT, &DispID_add_MyTestFun), -333)
  172.         printf("DispID_add_MyTestFun = 0X%X\n", DispID_add_MyTestFun);
  173.     VARIANTARG varg[2], pRetValue;
  174.     DISPPARAMS DispParams{};
  175.     DispParams.cArgs = 1;
  176.     DispParams.rgvarg = varg;
  177.     VariantInit(varg);
  178.     std::unique_ptr<MyEventTestClass> pkkk(new MyEventTestClass);
  179.     V_VT(varg) = VT_UNKNOWN;
  180.     V_UNKNOWN(varg) = static_cast<IUnknown*>(pkkk.get());
  181.     V_UNKNOWN(varg) = NULL;
  182.     VariantInit(&pRetValue);
  183.     UINT puArgErr = 0;
  184.     EXCEPINFO ex{};
  185.     hr = pIClass1Events->Invoke(DispID_add_MyTestFun,
  186.         IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,
  187.         &DispParams, &pRetValue, &ex, &puArgErr);
  188.     if (FAILED(hr))
  189.         if (DISP_E_TYPEMISMATCH == hr)  printf("Type mismatch\n");
  190.         else if (E_INVALIDARG == hr)         printf("One or more arguments are invalid\n");
  191.         else if (DISP_E_BADPARAMCOUNT == hr) printf("Invalid number of parameter\n");
  192.         else {
  193.             printf("pRetValue=0X%X\n", V_I4(&pRetValue));
  194.             printf("hr=0X%X puArgErr=%d\n", hr, puArgErr);
  195.         }
  196.     printf("------------ Event -------------(%d)\n", pIClass1Events->Release());
  197.     return 0;
  198. }
  199. struct My_Struct {
  200.     INT32 A;
  201.     INT32 B;
  202.     INT32 C;
  203. };
  204. extern "C" __declspec(dllexport)
  205. int CPP_DLL_Test_CSharp_Server(TestParameter* ptr) {
  206.     ExportedData ED(ptr, L"DLL_Test_CSharp_Server");
  207.     int rv;
  208.     IMyTest* pIMyTest;
  209.     ServerInfo_Struct<LPCOLESTR> My_Server_string = {
  210.               MyServerName,
  211.               (LPCOLESTR)OLESTR("CSharp_Server_For_Testing.Class1"),
  212.               (LPCOLESTR)OLESTR("CreateObject4_Chen"),
  213.               (LPCOLESTR)OLESTR("6E0C1B45-7569-47DA-AE26-4BE21F323923"),
  214.               (LPCOLESTR)OLESTR("FECA0AEE-FF0F-4897-8CB9-27B44BB97765")
  215.     };
  216.     rv = Get_ServerInterface4(ptr, My_Server_string, (PVOID*)&pIMyTest);
  217.     if (rv)return rv;
  218.     if (Invoke_Hello_method(ED, pIMyTest))return -1000;
  219.     if (Test_Event(pIMyTest))return -10001;
  220.     printf("(%d)pIMyTest->Release  %p\n", pIMyTest->Release(), pIMyTest);
  221.     PAUSE

  222.         IMyTest2* pIMyTest2 = NULL;
  223.     My_Server_string.IID = (LPCOLESTR)OLESTR("C8439959-322C-4FE3-AC66-24B062A77152");
  224.     rv = Get_ServerInterface4(ptr, My_Server_string, (PVOID*)&pIMyTest2);
  225.     if (rv)return rv;
  226.     CComBSTR str2 = NULL;
  227.     HR_(pIMyTest2->Hello2(&str2), -3456)
  228.         ED.WriteLine(L"str2(%s)", str2);
  229.     INT32 ref_int32, out_int32;
  230.     My_Struct s{ 11,2,3 };
  231.     pIMyTest2->Test_in_out_ref(&ref_int32, 34, &out_int32, (void*)&s);
  232.     ED.WriteLine(L"ref_int32 = %d  out_int32=%d", ref_int32, out_int32);
  233.     pIMyTest2->Test_ref_readonly(&ref_int32, (void*)&s);
  234.     ED.WriteLine(L"ref_readonly_int32 = %d %d", ref_int32, s.A);
  235.     printf("(%d)pIMyTest2->Release  %p\n", pIMyTest2->Release(), pIMyTest2);
  236.     PAUSE

  237.         IMyTest3* pIMyTest3 = NULL;
  238.     My_Server_string.IID = (LPCOLESTR)OLESTR("731D1161-8436-4827-AB75-F334A112B2F1");
  239.     rv = Get_ServerInterface4(ptr, My_Server_string, (PVOID*)&pIMyTest3);
  240.     if (rv)return rv;
  241.     printf("(pIMyTest3  = %p)\n", pIMyTest3);
  242.     str2.Empty();
  243.     HR_(pIMyTest3->Hello3(&str2), -34563)
  244.         ED.WriteLine(L"str2(%s)", str2);
  245.     ED.WriteLine(L"(%d)pIMyTest3->Release  ", pIMyTest3->Release());
  246.     PAUSE
  247.         return 0;
  248. }
  249. #endif

















  1. using System.Runtime.InteropServices;
  2. namespace CSharp_Server_For_Testing
  3. {
  4.     [Guid(Class1.IMyTest_IID)]
  5.     [ComVisible(true)]
  6.     public interface IMyTest
  7.     {
  8.         [DispId(8)] void Hello(Int32 id, String str);
  9.     }

  10.     [Guid(clsid)]
  11.     [ClassInterface(ClassInterfaceType.None)]
  12.     public partial class Class1 : IMyTest
  13.     {
  14.         public const String clsid = "6E0C1B45-7569-47DA-AE26-4BE21F323923";
  15.         public const String IMyTest_IID = "FECA0AEE-FF0F-4897-8CB9-27B44BB97765";
  16.         void IMyTest.Hello(Int32 id, String str)
  17.         {
  18.             Console.WriteLine(str + $" id = {id}");
  19.             EventHandler_MyTestFun?.Invoke(this, EventArgs.Empty);
  20.             Console.WriteLine("************** Hello world *****************");
  21.             if (id == 111) return;
  22.             else if (id == 222) System.Reflection.Assembly.LoadFrom("");
  23.             else throw new Exception() { HResult = (0XE << 28) | 0X12345 };
  24.         }
  25.         public static object? CreateObject4_Chen(ref Guid IID, IntPtr Not_Used)
  26.         {
  27.             if (IID == Guid.Parse(Class1.IMyTest_IID))
  28.             {
  29.                 return new Class1();
  30.             }

  31.             Object? MyReturnObj = null;
  32.             Console.WriteLine($"{IID}  ------Enter MyMethod_Next_Interface2");
  33.             MyMethod_Next_Interface2(in IID, ref MyReturnObj);
  34.             Console.WriteLine($"{IID}  ------Exit  MyMethod_Next_Interface2");
  35.             Console.ReadKey();

  36.             if (MyReturnObj != null) return MyReturnObj;
  37.             return null;
  38.         }
  39.         static partial void MyMethod_Next_Interface2(in Guid IID, ref object? MyReturnObj);
  40.     }
  41. }









  1. using System.Runtime.InteropServices;

  2. namespace CSharp_Server_For_Testing
  3. {
  4.     public struct MyStruct
  5.     {
  6.         public Int32 A;
  7.         public Int32 B;
  8.         public Int32 C;
  9.     };
  10.     [Guid(Class1.IMyTest2_IID)]
  11.     [ComVisible(true)]
  12.     public interface IMyTest2
  13.     {
  14.         [DispId(0x33)] void Hello2(ref String str);
  15.         [DispId(0x34)]
  16.         void
  17.          Test_in_out_ref(ref Int32 ref_int32,
  18.                              Int32 int32_2,
  19.                          out Int32 out_int32,
  20.                           in MyStruct s);
  21.         [DispId(0x35)]
  22.         void Test_readonly_ref(ref readonly Int32 ref_int32,
  23.                                 ref readonly MyStruct s);

  24.     }
  25.     public partial class Class1 : IMyTest2
  26.     {
  27.         public const String IMyTest2_IID = "C8439959-322C-4FE3-AC66-24B062A77152";
  28.         void IMyTest2.Hello2(ref String str)
  29.         {
  30.             Console.WriteLine("************** Hello world -2 *****************");
  31.             str = $"=== void IMyTest2.Hello2(ref String str) === <<-- ";
  32.         }
  33.         void IMyTest2.Test_in_out_ref(ref Int32 ref_int32, Int32 int32_2,
  34.                  out Int32 out_int32, in MyStruct s)
  35.         {
  36.             ref_int32 = 10000 + int32_2;
  37.             out_int32 = 1110000;
  38.             out_int32 += s.A;
  39.             Console.WriteLine($"out_int32 = {out_int32}");
  40.         }
  41.         void IMyTest2.Test_readonly_ref(ref readonly Int32 ref_readonly_int32,
  42.                                         ref readonly MyStruct s)
  43.         {
  44.             Console.WriteLine($"ref_readonly_int32 = {ref_readonly_int32}");
  45.             Console.WriteLine($"ref_readonly s.A= {s.A}");
  46.         }

  47.         static partial void MyMethod_Next_Interface2(in Guid IID, ref object? MyReturnObj)
  48.         {
  49.             if (IID == Guid.Parse(Class1.IMyTest2_IID))
  50.             {
  51.                 Console.WriteLine($"{IID}  MyMethod_Next_Interface2");
  52.                 Console.ReadKey();
  53.                 MyReturnObj = new Class1();
  54.             }
  55.             else
  56.             {
  57.                 Console.WriteLine($"{IID}  ------Enter MyMethod_Next_Interface3");
  58.                 MyMethod_Next_Interface3(in IID, ref MyReturnObj);
  59.                 Console.WriteLine($"{IID}  ------Exit  MyMethod_Next_Interface3");
  60.             }
  61.         }
  62.         static partial void MyMethod_Next_Interface3(in Guid IID, ref object? MyReturnObj);
  63.     }
  64. }




  1. using System.Runtime.InteropServices;

  2. namespace CSharp_Server_For_Testing
  3. {
  4.     [Guid(Class1.IMyTest3_IID)]
  5.     [ComVisible(true)]
  6.     public interface IMyTest3
  7.     {
  8.         [DispId(333)] void Hello3(ref String str);
  9.     }
  10.     public partial class Class1 : IMyTest3
  11.     {
  12.         public const String IMyTest3_IID = "731D1161-8436-4827-AB75-F334A112B2F1";
  13.         void IMyTest3.Hello3(ref String str)
  14.         {
  15.             Console.WriteLine("=======************** Hello world -3 *****************");
  16.             GC.Collect();
  17.             GC.WaitForPendingFinalizers();
  18.             str = $"=== void IMyTest3.Hello3(ref String str) ===";
  19.         }
  20.         void Destructor()
  21.         {
  22.             Console.WriteLine();
  23.             Console.WriteLine("~Class1()  Destructor()  -------------");
  24.             Console.Beep();
  25.             Console.WriteLine("------------- ~Class1()  Destructor() ");
  26.         }
  27.         ~Class1()
  28.         {
  29.             Destructor();
  30.         }
  31.         static Class1 MyClass1_obj = new Class1();
  32.         static partial void MyMethod_Next_Interface3(in Guid IID, ref object? MyReturnObj)
  33.         {
  34.             if (IID == Guid.Parse(Class1.IMyTest3_IID))
  35.             {
  36.                 Console.WriteLine($"{IID}  MyMethod_Next_Interface3");
  37.                 MyReturnObj = MyClass1_obj;
  38.                 Console.WriteLine(" MyReturnObj = new Class1();");
  39.                 Console.ReadKey();
  40.             }
  41.             else
  42.             {
  43.                 Console.WriteLine($"{IID}  ------Enter MyMethod_Next_Interface4");
  44.                 MyMethod_Next_Interface4(in IID, ref MyReturnObj);
  45.                 Console.WriteLine($"{IID}  ------Exit  MyMethod_Next_Interface4");
  46.             }
  47.         }
  48.         static partial void MyMethod_Next_Interface4(in Guid IID, ref object? MyReturnObj);
  49.     }
  50. }



  1. using System.Runtime.InteropServices;

  2. namespace CSharp_Server_For_Testing
  3. {
  4.     [Guid(Class1.IMyTest_Event_IID)]
  5.     [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
  6.     [ComVisible(true)]
  7.     public interface IClass1Events
  8.     {
  9.         event EventHandler Event_MyTestFun;
  10.     }

  11.     [ComSourceInterfaces(typeof(IClass1Events))]
  12.     [ProgId("MyTest_Chen.ProgId")]
  13.     public partial class Class1 : IClass1Events
  14.     {
  15.         public const String IMyTest_Event_IID = "3AAEFAB5-6DC7-49FD-A658-44A8DEF91F02";
  16.         private event EventHandler? EventHandler_MyTestFun;
  17.         public event EventHandler? Event_MyTestFun
  18.         {
  19.             add
  20.             {
  21.                 Console.WriteLine($" add MyTestFun {value?.GetType().FullName}");
  22.                 Console.WriteLine($" value is null = {value is null}");
  23.                 Console.ReadKey();
  24.                 if (value is not null) EventHandler_MyTestFun += value;
  25.             }
  26.             remove
  27.             {
  28.                 Console.WriteLine("remove MyTestFun ");
  29.                 Console.ReadKey();
  30.                 if (value is not null) EventHandler_MyTestFun -= value;
  31.             }
  32.         }
  33.     }
  34. }













  1. #include "pch.h"

  2. #if defined(_M_X64) && defined(_WIN64) && defined(_WINDOWS) && \
  3.      _MSVC_LANG >= 202002L &&  defined(_USRDLL)
  4. #include "TestParameter.h"

  5. LPCOLESTR MyServerName = (LPCOLESTR)Server_Name_w(MultiInface_VB_NET\MultiInface_VB_NET\bin\x64\,
  6.     My_Configuration, \net9.0\MultiInface_VB_NET.dll);

  7. struct Microsoft_Example_Struct;
  8. typedef INT32(*VB_Fun_Type)(LPSTR* str, LPWSTR* wstr);
  9. typedef HRESULT(*CPP_Fun_Type)(PWSTR lpString, int nMaxCount);
  10. typedef void  (*std_fun_ptr)(void);
  11. __interface _MultiInterface : IDispatch {
  12.     HRESULT Array_in(BSTR* result, SAFEARRAY* long_64_bit, SAFEARRAY* pDouble);
  13.     HRESULT Array_In_Out(BSTR str, double* Double1, SAFEARRAY** DoubleArrary, SAFEARRAY** Lock);
  14.     HRESULT Property_Get_Array(BSTR str, SAFEARRAY** pRetVal);
  15.     HRESULT ArraysWithinStructures(Microsoft_Example_Struct P1, Microsoft_Example_Struct* P2);
  16. };
  17. __interface IMyTest2 : IDispatch {
  18.     HRESULT Map_HRESULTs_and_Exceptions_1(long ID);
  19.     HRESULT Map_HRESULTs_and_Exceptions_2(long ID);
  20. };
  21. __interface IMyTest3 : IDispatch {
  22.     HRESULT TestFunctionPointer(CPP_Fun_Type CPP_Func, VB_Fun_Type* VB_Func);
  23.     HRESULT Test_Delegate(std_fun_ptr CPP_Func);
  24. };

  25. class SafeArrayPtr {
  26.     SAFEARRAY* ptr;
  27. public:
  28.     SafeArrayPtr(VARTYPE vt, UINT cDim, ULONG cElement1, ULONG cElement2 = 0) {
  29.         SAFEARRAYBOUND SafeArrayBound[2] = { {cElement1,0},{cElement2,0} };
  30.         ptr = SafeArrayCreate(vt, cDim, SafeArrayBound);
  31.         if (!ptr)throw "SafeArrayCreate";
  32.     }
  33.     ~SafeArrayPtr() {
  34.         SafeArrayDestroy(ptr);
  35.         ptr = NULL;
  36.     }
  37.     ULONG CountOfElement(int Dim) { return ptr->rgsabound[Dim].cElements; }
  38.     SAFEARRAY* operator->() { return ptr; }
  39.     SafeArrayPtr& operator =(SAFEARRAY* ptr) { this->ptr = ptr; return *this; }
  40.     SAFEARRAY** operator&() { return &ptr; }
  41.     operator SAFEARRAY* () { return ptr; }
  42. };
  43. void MultiInterface_Array_in(ExportedData& ED, _MultiInterface* p_MultiInterface) {
  44.     HRESULT hr;
  45.     const int Count_Of_dim1 = 12;
  46.     SafeArrayPtr pSafeArray_Double(VT_R8, 1, Count_Of_dim1);
  47.     SafeArrayPtr pSafeArray_LongLong(VT_I8, 1, Count_Of_dim1);
  48.     double* pdouble = NULL;
  49.     long long* ptr_LongLong = NULL;
  50.     if (SUCCEEDED(SafeArrayAccessData(pSafeArray_Double, (void**)&pdouble)) &&
  51.         SUCCEEDED(SafeArrayAccessData(pSafeArray_LongLong, (void**)&ptr_LongLong)))
  52.     {
  53.         for (int ii = 0; ii < pSafeArray_Double.CountOfElement(0); ii++) {
  54.             pdouble[ii] = ii * 10 + 5;
  55.             ptr_LongLong[ii] = 100 * ii + 7;
  56.         }
  57.         SafeArrayUnaccessData(pSafeArray_Double);
  58.         SafeArrayUnaccessData(pSafeArray_LongLong);
  59.         BSTR str = NULL;
  60.         hr = p_MultiInterface->Array_in(&str, pSafeArray_LongLong, pSafeArray_Double);
  61.         if (SUCCEEDED(hr)) ED.WriteLine(L"%s", str);
  62.         //if (SUCCEEDED(hr)) printf("%S",str);
  63.         else    ED.WriteLine(L"error: p_MultiInterface->Array_in hr=%X", hr);
  64.         ::SysFreeString(str);
  65.     }
  66. }
  67. void MultiInterface_Array_In_Out(ExportedData& ED, _MultiInterface* p_MultiInterface) {
  68.     HRESULT hr;

  69.     SafeArrayPtr  pSafeArray_In_Out_Lock(VT_R8, 1, 500000);
  70.     SAFEARRAY* pSafeArray_In_Out_Lock_Original = pSafeArray_In_Out_Lock;
  71.     SafeArrayLock(pSafeArray_In_Out_Lock);
  72.     double* pDouble_in_Lock, * pDouble_out_Lock;
  73.     SafeArrayAccessData(pSafeArray_In_Out_Lock, (void**)&pDouble_in_Lock);
  74.     SafeArrayUnaccessData(pSafeArray_In_Out_Lock);
  75.     //--------------------------------------------------
  76.     SafeArrayPtr  pMy_SafeArray(VT_R8, 1, 500);
  77.     double* pDouble_in, * pDouble_out;
  78.     double Double1 = 123.456789;
  79.     SafeArrayAccessData(pMy_SafeArray, (void**)&pDouble_in);
  80.     pDouble_in[1] = 111.111;
  81.     SafeArrayUnaccessData(pMy_SafeArray);
  82.     BSTR str2 = SysAllocString(L"MultiInterface_Array_In_Out");
  83.     hr = p_MultiInterface->Array_In_Out(str2, &Double1, &pMy_SafeArray, &pSafeArray_In_Out_Lock);
  84.     ::SysFreeString(str2);
  85.     if (SUCCEEDED(hr)) {
  86.         wprintf(L"Double1      = %f\n", Double1);
  87.         SafeArrayAccessData(pMy_SafeArray, (void**)&pDouble_out);
  88.         wprintf(L"pDouble2[1]  = %f\n", pDouble_out[1]);
  89.         wprintf(L"pDouble2[33] = %f\n", pDouble_out[33]);
  90.         SafeArrayUnaccessData(pMy_SafeArray);
  91.         if (pDouble_in != pDouble_out) {
  92.             wprintf(L"pDouble_in   (%p)\n", pDouble_in);
  93.             wprintf(L"pDouble_out  (%p)\n", pDouble_out);
  94.         }
  95.         //-------------------------------------------------
  96.         SafeArrayAccessData(pSafeArray_In_Out_Lock, (void**)&pDouble_out_Lock);
  97.         wprintf(L"pDouble_out_Lock[22]   (%f)\n", pDouble_out_Lock[22]);
  98.         SafeArrayUnaccessData(pSafeArray_In_Out_Lock);
  99.         if (pDouble_in_Lock != pDouble_out_Lock) {
  100.             wprintf(L"pDouble_in_Lock != pDouble_out_Lock\n");
  101.         }
  102.         if (pSafeArray_In_Out_Lock != pSafeArray_In_Out_Lock_Original) {
  103.             wprintf(L"pSafeArray_In_Out_Lock != pSafeArray_In_Out_Lock_Original\n");
  104.             SafeArrayDestroy(pSafeArray_In_Out_Lock);
  105.             pSafeArray_In_Out_Lock = pSafeArray_In_Out_Lock_Original;
  106.         }
  107.     }
  108.     SafeArrayUnlock(pSafeArray_In_Out_Lock);
  109. }
  110. void MultiInterface_Property_Get_Array(ExportedData& ED, _MultiInterface* p_MultiInterface) {
  111.     HRESULT hr;
  112.     SAFEARRAY* pSafeArray = NULL;
  113.     BSTR str2 = SysAllocString(L"MultiInterface_Property_Get_Array");
  114.     hr = p_MultiInterface->Property_Get_Array(str2, &pSafeArray);
  115.     ::SysFreeString(str2);
  116.     if (SUCCEEDED(hr)) {
  117.         double* pDouble;
  118.         SafeArrayLock(pSafeArray);
  119.         hr = SafeArrayAccessData(pSafeArray, (void**)&pDouble);
  120.         if (SUCCEEDED(hr)) {
  121.             LONG LowerBound;
  122.             SafeArrayGetLBound(pSafeArray, 1, &LowerBound);
  123.             LONG UpperBound;
  124.             SafeArrayGetUBound(pSafeArray, 1, &UpperBound);
  125.             for (int aa = LowerBound; aa <= UpperBound; aa++) {
  126.                 ED.WriteLine(L"Property_Get_Array pDouble(%d) = %f", aa, pDouble[aa]);
  127.             }
  128.             SafeArrayUnaccessData(pSafeArray);
  129.         }
  130.         SafeArrayUnlock(pSafeArray);
  131.         SafeArrayDestroy(pSafeArray);
  132.     }
  133. }
  134. struct Microsoft_Example_Struct {
  135.     short s1[128];
  136.     WCHAR* f1;
  137.     WCHAR f2[256];
  138.     BSTR f3;
  139. };
  140. void MultiInterface_ArraysWithinStructures(ExportedData& ED, _MultiInterface* p_MultiInterface) {
  141.     HRESULT hr;
  142.     WCHAR* f_1 = const_cast<WCHAR*>(L"ABCDEF");
  143.     BSTR f_3 = ::SysAllocString(L"CPP_f3");
  144.     Microsoft_Example_Struct P1{ {},f_1,L"CPP_f2",f_3 }, P2{ {},NULL,{},NULL };
  145.     P1.s1[10] = 4444;
  146.     P2.s1[10] = 5555;
  147.     hr = p_MultiInterface->ArraysWithinStructures(P1, &P2);
  148.     ::SysFreeString(f_3);
  149.     if (SUCCEEDED(hr)) {
  150.         ED.WriteLine(L"P1.s1[10]=%d", P1.s1[10]);
  151.         ED.WriteLine(L"P2.s1[10]=%d", P2.s1[10]);
  152.         PAUSE
  153.     }
  154. }

  155. void IMyTest2_Map_HRESULTs_and_Exceptions_1(ExportedData& ED, IMyTest2* pIMyTest2) {
  156.     for (int id = 0X234; id < 0X238; id++)
  157.     {
  158.         HRESULT hr;
  159.         hr = pIMyTest2->Map_HRESULTs_and_Exceptions_1(id);
  160.         if (FAILED(hr)) {
  161.             ED.WriteLine(L"hr=%X", hr);
  162.             IErrorInfo* pError;
  163.             hr = GetErrorInfo(0, &pError);
  164.             if (SUCCEEDED(hr)) {
  165.                 BSTR Description, source;
  166.                 pError->GetDescription(&Description);
  167.                 pError->GetSource(&source);
  168.                 ED.WriteLine(L"Description=%s", Description);
  169.                 ED.WriteLine(L"Source=%s", source);
  170.                 SysFreeString(Description); SysFreeString(source);
  171.                 pError->Release();
  172.             }
  173.         }
  174.     }
  175. }
  176. void IMyTest2_Map_HRESULTs_and_Exceptions_2(ExportedData& ED, IMyTest2* pIMyTest2) {
  177.     for (int ID = 1; ID <= 5; ID++) {
  178.         HRESULT hr;
  179.         hr = pIMyTest2->Map_HRESULTs_and_Exceptions_2(ID);
  180.         if (FAILED(hr)) ED.WriteLine(L"hr=%X", hr);
  181.         hr = [=]()->HRESULT {
  182.             HR_(pIMyTest2->Map_HRESULTs_and_Exceptions_2(ID), 334455)
  183.                 return S_OK;
  184.             }();
  185.         ED.WriteLine(L"rerurnValue=%d", hr);
  186.     }
  187.     PAUSE
  188. }
  189. HRESULT Fixed_length_string_buffer(PWSTR lpString, int nMaxCount) {
  190.     printf("\nCPP_Function\n");
  191.     StringCchCopyW(lpString, nMaxCount, L"Fixed_length_string_buffer");
  192.     return S_OK;
  193. }

  194. void IMyTest3_TestFunctionPointer(ExportedData& ED, IMyTest3* pIMyTest3) {
  195.     VB_Fun_Type VB_Fun;
  196.     HRESULT hr;

  197.     hr = pIMyTest3->TestFunctionPointer(Fixed_length_string_buffer, &VB_Fun);
  198.     if (FAILED(hr)) ED.WriteLine(L"Error: hr=%X in IMyTest3_TestFunctionPointer", hr);
  199.     INT32 retVal;
  200.     for (int64_t aa = 0; aa < 3; aa++) {
  201.         LPSTR str = NULL;
  202.         LPWSTR wstr = NULL;
  203.         retVal = VB_Fun(&str, &wstr);
  204.         printf("(%s) retVal=%d\n", str, retVal);
  205.         printf("(%S)\n", wstr);
  206.     }
  207. }

  208. void IMyTest3_Test_Delegate(ExportedData& ED, IMyTest3* pIMyTest3) {
  209.     HRESULT hr;

  210.     hr = pIMyTest3->Test_Delegate((std_fun_ptr)Fixed_length_string_buffer);
  211.     if (FAILED(hr)) ED.WriteLine(L" ->hr=%X in IMyTest3_Test_Delegate", hr);
  212. }
  213. #define LOOP1(xx) for(int64_t aaa =0 ; aaa < xx ; aaa++)

  214. extern "C"
  215. int CPP_DLL_Test_MultiInterface(TestParameter* ptr) {
  216.     ExportedData ED(ptr, L"CPP_DLL_Test_MultiInterface");
  217.     int rv = 0;
  218.     try
  219.     {
  220.         IMyTest3* pIMyTest3;
  221.         _MultiInterface* p_MultiInterface;
  222.         IMyTest2* pIMyTest2;
  223.         [&]() {
  224.             ServerInfo_Struct<LPCOLESTR> My_Server_string = {
  225.               MyServerName,
  226.               (LPCOLESTR)OLESTR("MultiInface_VB_NET.MultiInterface"),
  227.               (LPCOLESTR)OLESTR("CreateObject4_Chen"),
  228.               (LPCOLESTR)OLESTR("77381cf4-badb-4ee7-b51f-9090fe145c39"),
  229.               (LPCOLESTR)OLESTR("636B8701-78D1-482C-9A2A-E7259C23AEB5")
  230.             };
  231.             rv = Get_ServerInterface4(ptr, My_Server_string, (PVOID*)&p_MultiInterface);
  232.             if (rv)throw std::exception("Get_ServerInterface", rv);
  233.             LOOP1(2) MultiInterface_Array_in(ED, p_MultiInterface);
  234.             //PAUSE
  235.             LOOP1(2) MultiInterface_Array_In_Out(ED, p_MultiInterface);
  236.             //PAUSE
  237.             MultiInterface_Property_Get_Array(ED, p_MultiInterface);
  238.             MultiInterface_ArraysWithinStructures(ED, p_MultiInterface);
  239.             }();
  240.         [&]() {
  241.             ServerInfo_Struct<LPCOLESTR> My_Server_string = {
  242.               MyServerName,
  243.               (LPCOLESTR)OLESTR("MultiInface_VB_NET.MultiInterface"),
  244.               (LPCOLESTR)OLESTR("CreateObject4_Chen"),
  245.               (LPCOLESTR)OLESTR("77381cf4-badb-4ee7-b51f-9090fe145c39"),
  246.               (LPCOLESTR)OLESTR("31D53FF8-4768-4A77-95E3-DC28DEBB375F")
  247.             };
  248.             rv = Get_ServerInterface4(ptr, My_Server_string, (PVOID*)&pIMyTest2);
  249.             if (rv)throw std::exception("Get_ServerInterface", rv);
  250.             IMyTest2_Map_HRESULTs_and_Exceptions_1(ED, pIMyTest2);
  251.             IMyTest2_Map_HRESULTs_and_Exceptions_2(ED, pIMyTest2);
  252.             }();
  253.         [&]() {
  254.             ServerInfo_Struct<LPCOLESTR> My_Server_string = {
  255.               MyServerName,
  256.               (LPCOLESTR)OLESTR("MultiInface_VB_NET.MultiInterface"),
  257.               (LPCOLESTR)OLESTR("CreateObject4_Chen"),
  258.               (LPCOLESTR)OLESTR("77381cf4-badb-4ee7-b51f-9090fe145c39"),
  259.               (LPCOLESTR)OLESTR("9E7F18F8-3B02-4AE0-89A9-DD35240BF509")
  260.             };
  261.             rv = Get_ServerInterface4(ptr, My_Server_string, (PVOID*)&pIMyTest3);
  262.             if (rv)throw std::exception("Get_ServerInterface", rv);
  263.             IMyTest3_TestFunctionPointer(ED, pIMyTest3);
  264.             IMyTest3_Test_Delegate(ED, pIMyTest3);
  265.             //PAUSE
  266.             }();

  267.         wprintf(L"%p(%d)p_MultiInterface\n", p_MultiInterface, p_MultiInterface->Release());
  268.         wprintf(L"%p(%d)pIMyTest2       \n", pIMyTest2, pIMyTest2->Release());
  269.         wprintf(L"%p(%d)pIMyTest3       \n", pIMyTest3, pIMyTest3->Release());
  270.         PAUSE
  271.     }
  272.     catch (const std::exception& ex)
  273.     {
  274.         printf("exception:(%s) in multi-Interface \n", ex.what());
  275.     }
  276.     return rv;
  277. }
  278. #endif 












  1. LIBRARY
  2. EXPORTS
  3. CPP_DLL_Test_MultiInterface @1










  1. Imports System.Buffers
  2. Imports System.Reflection
  3. Imports System.Runtime.InteropServices
  4. Imports System.Runtime.InteropServices.Marshalling
  5. Imports System.Text

  6. <ComClass(MultiInterface.MultiInterface_CLSID, MultiInterface.I_MultiInterface_IID, MultiInterface.EventsId)>
  7. Public Class MultiInterface : Implements IMyTest2, IMyTest3
  8. #Region "COM GUIDs"
  9.     ' These  GUIDs provide the COM identity for this class 
  10.     ' and its COM interfaces. If you change them, existing 
  11.     ' clients will no longer be able to access the class.
  12.     Public Const MultiInterface_CLSID As String = "77381cf4-badb-4ee7-b51f-9090fe145c39"
  13.     Public Const I_MultiInterface_IID As String = "636b8701-78d1-482c-9a2a-e7259c23aeb5"
  14.     Public Const IMyTest2_IID As String = "31D53FF8-4768-4A77-95E3-DC28DEBB375F"
  15.     Public Const IMyTest3_IID As String = "9E7F18F8-3B02-4AE0-89A9-DD35240BF509"
  16.     Public Const EventsId As String = "c340a1eb-b81b-4553-bc5c-db85fdd3cfc0"
  17. #End Region

  18.     Public Sub New()
  19.         MyBase.New()
  20.         MyStringBuilder = New StringBuilder()
  21.     End Sub
  22.     Dim MyStringBuilder As StringBuilder
  23.     Sub Array_in(<Out> ByRef str As String, <[In]> long_64_bit As Long(),
  24.            <[In]> pDouble As Double())
  25.         MyStringBuilder.Clear()
  26.         MyStringBuilder.AppendLine("Array_in *** IN")
  27.         MyStringBuilder.AppendLine($"LowerBound= {pDouble.GetLowerBound(0)} UpperBound={pDouble.GetUpperBound(0)}")
  28.         For ii As Int32 = pDouble.GetLowerBound(0) To pDouble.GetUpperBound(0)
  29.             MyStringBuilder.AppendLine($"{ii:d2}: {pDouble(ii):F2}{vbTab} {long_64_bit(ii)}")
  30.         Next
  31.         MyStringBuilder.AppendLine("Array_in *** OUT")
  32.         str = MyStringBuilder.ToString()
  33.     End Sub

  34.     Sub Array_In_Out(<[In]> str As String,
  35.       <[In], Out> ByRef Double1 As Double,
  36.       <[In], Out> ByRef DoubleArray_inOut As Double(),
  37.       <[In], Out> ByRef DoubleArray_In_Out_Lock As Double()
  38.                      )
  39.         Dim Len As Integer = DoubleArray_inOut.GetLength(0)
  40.         Console.WriteLine(str)
  41.         Console.WriteLine($"Length of DoubleArray = {Len} --- .NET")
  42.         Console.WriteLine($"Double1               = {Double1} -- .NET")
  43.         Console.WriteLine($"DoubleArray(1)        ={DoubleArray_inOut(1)} --- .NET")

  44.         Double1 = 987.654321
  45.         DoubleArray_inOut(33) = 33.33
  46.         DoubleArray_In_Out_Lock(22) = 22.22
  47.     End Sub
  48.     Dim _DoubleArray(8) As Double
  49.     ReadOnly Property Property_Get_Array(<[In]> str As String) _
  50.       As <MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VarEnum.VT_R8)> Double()
  51.         Get
  52.             Console.WriteLine(str)
  53.             Dim Len As Integer = _DoubleArray.GetLength(0)
  54.             Console.WriteLine($"Property_Get_Array ---  Length = {Len}")
  55.             For aa As Integer = _DoubleArray.GetLowerBound(0) To _DoubleArray.GetUpperBound(0)
  56.                 _DoubleArray(aa) = aa * 200 + 7
  57.             Next
  58.             Return _DoubleArray
  59.         End Get
  60.     End Property
  61.     Sub ArraysWithinStructures(<[In]> P1 As Microsoft_Example_Struct,
  62.                                <[In], Out> ByRef P2 As Microsoft_Example_Struct)
  63.         Console.WriteLine($"P1.f1={P1.f1}         -- .NET")
  64.         Console.WriteLine($"P1.f2={P1.f2}         -- .NET")
  65.         Console.WriteLine($"P1.f3={P1.f3}         -- .NET")
  66.         If P1.f2 <> "CPP_f2" Then
  67.             Throw New Exception("P1.f2 <> CPP_f2")
  68.         End If
  69.         Console.WriteLine($"P1.s1(10)={P1.s1(10)} -- .NET")
  70.         Console.WriteLine($"P2.s1(10)={P2.s1(10)} -- .NET")
  71.         P1.s1(10) = -987
  72.         P2.s1(10) = 1010
  73.         Console.ReadKey()
  74.     End Sub
  75.     '================ IMyTest2 =======================
  76.     Private Sub Map_HRESULTs_and_Exceptions_1(ID As Int32) Implements IMyTest2.Map_HRESULTs_and_Exceptions_1
  77.         Dim ApplicationException As New ApplicationException("My description in MyTest1")
  78.         ApplicationException.HResult = (7 << 29) Or ID
  79.         ApplicationException.Source = "MyTest1"
  80.         Console.WriteLine($"hr={ApplicationException.HResult:X} -- MyTest1")
  81.         Throw ApplicationException
  82.     End Sub
  83.     Private Sub Map_HRESULTs_and_Exceptions_2(ID As Int32) Implements IMyTest2.Map_HRESULTs_and_Exceptions_2
  84.         Select Case ID
  85.             Case 1
  86.                 Try
  87.                     Assembly.LoadFrom("")
  88.                 Catch ex As Exception
  89.                     Dim What_is_this As New ArgumentException
  90.                     Console.WriteLine(
  91.                         $"hr={ex.HResult:X} == {What_is_this.HResult:X} {What_is_this}")
  92.                 End Try
  93.                 Assembly.LoadFrom("")
  94.             Case 2
  95.                 Dim _INT64 As Int64
  96.                 Try
  97.                     _INT64 = 2 / (ID - 2)
  98.                 Catch ex As Exception
  99.                     Dim What_is_this As New OverflowException
  100.                     Console.WriteLine(
  101.                         $"hr={ex.HResult:X} == {What_is_this.HResult:X} {What_is_this}")
  102.                 End Try
  103.                 _INT64 = 2 / (ID - 2)
  104.             Case 5
  105.             Case Else
  106.                 Dim MyException As New Exception With {
  107.                       .HResult = (7 << 29) Or ID}
  108.                 Throw MyException
  109.         End Select
  110.     End Sub
  111.     Protected Delegate Function MyFunction_CPP(<Out> lpString() As Char, nMaxCount As Integer) As Int32
  112.     Protected Delegate Function MyFunction_VB(<[In], Out> ByRef str As String,
  113.                <[In], Out, MarshalAs(UnmanagedType.LPWStr)> ByRef wstr As String) As Int32
  114.     Shared Function VB_Func1(<[In], Out> ByRef str As String,
  115.                <[In], Out, MarshalAs(UnmanagedType.LPWStr)> ByRef wstr As String) As Int32
  116.         str = "Shared Function VB_Func1(<[In], Out> ByRef str As String,....) As Int32"
  117.         wstr = "Shared Function VB_Func1(...,  <[In], Out, MarshalAs(UnmanagedType.LPWStr)> ByRef wstr As String) As Int32"
  118.         Return 34567
  119.     End Function
  120.     '================ IMyTest2 =======================

  121.     '================ IMyTest3 =======================
  122.     Private Sub TestFunctionPointer(<[In]> CPP_FuncPtr As IntPtr,
  123.                                     <[In], Out> ByRef VB_Func As IntPtr
  124.          ) Implements IMyTest3.TestFunctionPointer
  125.         Dim temp_Delegate As [Delegate] = [Delegate].CreateDelegate(GetType(MyFunction_VB),
  126.                   GetType(MultiInterface).GetMethod("VB_Func1"))
  127.         VB_Func = Marshal.GetFunctionPointerForDelegate(Of MyFunction_VB)(
  128.                   CType(temp_Delegate, MyFunction_VB))
  129.         '---------------
  130.         Dim CPP_Func As MyFunction_CPP =
  131.             Marshal.GetDelegateForFunctionPointer(Of MyFunction_CPP)(CPP_FuncPtr)
  132.         Const Length As Int32 = 256
  133.         Dim buffer() As Char = ArrayPool(Of Char).Shared.Rent(Length)
  134.         Dim hResult As Int32 = CPP_Func.Invoke(buffer, Length)
  135.         Dim str As New String(buffer)
  136.         Console.WriteLine($"hResult={hResult}  {str}")
  137.         ArrayPool(Of Char).Shared.Return(buffer)
  138.         'Console.ReadKey()
  139.     End Sub
  140.     Private Sub Test_Delegate(<[In]> CPP_FuncPtr As IntPtr) Implements IMyTest3.Test_Delegate
  141.         Dim hResult As Int32
  142.         Const Length As Int32 = 256
  143.         Dim buffer() As Char = ArrayPool(Of Char).Shared.Rent(Length)
  144.         Dim ParamList As Object() = {buffer, Length}
  145.         Dim CPP_Func As MyFunction_CPP
  146.         Try
  147.             CPP_Func = Marshal.GetDelegateForFunctionPointer(Of MyFunction_CPP)(CPP_FuncPtr)
  148.             hResult = CPP_Func.DynamicInvoke(ParamList)
  149.         Catch ex As Exception
  150.             Console.WriteLine($"Error: {ex.Message} ")
  151.             Console.ReadKey()
  152.         End Try
  153.         Console.WriteLine($"Test_Delegate ---hResult={hResult}  {New String(buffer)}")
  154.         ArrayPool(Of Char).Shared.Return(buffer)
  155.     End Sub
  156.     '================ IMyTest3 =======================

  157.     Shared MyMultiInterface_Object As MultiInterface

  158.     Shared Function CreateObject4_Chen(ByRef IID As Guid,
  159.         Not_Used As IntPtr) As Object
  160.         If MyMultiInterface_Object Is Nothing Then
  161.             MyMultiInterface_Object = New MultiInterface
  162.         End If

  163.         Dim MyIID As Guid = Guid.Parse(I_MultiInterface_IID)
  164.         Dim MyIID2 As Guid = Guid.Parse(IMyTest2_IID)
  165.         Dim MyIID3 As Guid = Guid.Parse(IMyTest3_IID)
  166.         If MyIID = IID OrElse MyIID2 = IID OrElse MyIID3 = IID Then
  167.             'Console.WriteLine("CreateObject4_Chen ---Object")
  168.             Return MyMultiInterface_Object
  169.         End If
  170.         'Console.WriteLine("CreateObject4_Chen Nothing")
  171.         Return Nothing
  172.     End Function

  173. End Class

  174. <Guid(MultiInterface.IMyTest3_IID)>
  175. Public Interface IMyTest3
  176.     Sub TestFunctionPointer(<[In]> MyFunc As IntPtr, <[In], Out> ByRef VB_Func As IntPtr)
  177.     Sub Test_Delegate(<[In]> MyFunc As IntPtr)
  178. End Interface

  179. <Guid(MultiInterface.IMyTest2_IID)>
  180. Public Interface IMyTest2
  181.     Sub Map_HRESULTs_and_Exceptions_1(ID As Int32)
  182.     Sub Map_HRESULTs_and_Exceptions_2(ID As Int32)
  183. End Interface

  184. <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
  185. Public Structure Microsoft_Example_Struct
  186.     <MarshalAs(UnmanagedType.ByValArray, SizeConst:=128)> Public s1() As Int16
  187.     <MarshalAs(UnmanagedType.LPWStr)> Public f1 As String
  188.     <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> Public f2 As String
  189.     <MarshalAs(UnmanagedType.BStr)> Public f3 As String
  190. End Structure
  191. Public Structure RetValue4
  192.     Public ppvoid As Object
  193. End Structure

  194. <GeneratedComInterface>
  195. <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
  196. Interface IMyTest_1
  197.     Sub MyTest1(ID As Int32)
  198.     Sub MyTest2(ID As Int32)
  199. End Interface

  200. <GeneratedComInterface>
  201. <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
  202. Interface IMyTest_2 : Inherits IMyTest_1
  203.     Sub MyTest3(<[In]> MyFunc As IntPtr)
  204. End Interface
  205. ' If you do not have a type library for an interface
  206. ' you can redeclare it using ComImportAttribute.

  207. ' This is how the interface would look in an idl file.

  208. '[
  209. 'object,
  210. 'uuid("73EB4AF8-BE9C-4b49-B3A4-24F4FF657B26"),
  211. 'dual, helpstring("IMyStorage Interface"),
  212. 'pointer_default(unique)
  213. ']
  214. 'interface IMyStorage : IDispatch
  215. '{
  216. ' [id(1)]
  217. ' HRESULT GetItem([in] BSTR bstrName, [out, retval] IDispatch ** ppItem);
  218. ' [id(2)]
  219. ' HRESULT GetItems([in] BSTR bstrLocation, [out] SAFEARRAY(VARIANT)* pItems);
  220. ' [id(3)]
  221. ' HRESULT GetItemDescriptions([in] BSTR bstrLocation, [out] SAFEARRAY(VARIANT) ** ppItems);
  222. ' [id(4), propget]
  223. ' HRESULT get_IsEmpty([out, retval] BOOL * pfEmpty);
  224. '};

  225. ' This is the managed declaration.

  226. <ComImport(), Guid("73EB4AF8-BE9C-4b49-B3A4-24F4FF657B26")>
  227. Public Interface IMyStorage
  228.     <DispId(1)>
  229.     Function GetItem(<InAttribute(), MarshalAs(UnmanagedType.BStr)> ByVal bstrName As String) _
  230.            As <MarshalAs(UnmanagedType.Interface)> Object

  231.     <DispId(2)>
  232.     Function GetItems(<InAttribute(), MarshalAs(UnmanagedType.BStr)> ByVal bstrLocation As String,
  233.            <OutAttribute(), MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VarEnum.VT_VARIANT)>
  234.                                       ByVal Items() As Object)

  235.     <DispId(3)>
  236.     Function GetItemDescriptions(<InAttribute()> ByVal bstrLocation As String,
  237.            <InAttribute(), OutAttribute(),
  238.                       MarshalAs(UnmanagedType.SafeArray)> ByRef varDescriptions() As Object)

  239.     <DispId(4)>
  240.     ReadOnly Property IsEmpty(<MarshalAs(UnmanagedType.VariantBool)> ByVal bEmpty As Boolean)

  241. End Interface



















  1. LIBRARY
  2. EXPORTS
  3. CPP_DLL_Test_UnregisteredServer1          @1
  4. CPP_DLL_Test_UnregisteredServer2          @2
  5. CPP_DLL_Test_IXXXX                              @3



  1. #include "pch.h"

  2. #if defined(_M_X64) && defined(_WIN64) && defined(_WINDOWS) && \
  3.      _MSVC_LANG >= 202002L &&  defined(_USRDLL)
  4. #include "TestParameter.h"

  5. extern "C" /* exported functions */ {
  6.     int CPP_DLL_Test_UnregisteredServer1(TestParameter*);
  7.     int CPP_DLL_Test_UnregisteredServer2(TestParameter*);
  8.     int CPP_DLL_Test_IXXXX(TestParameter*);
  9. }

  10. LPCOLESTR MyServerName = Server_Name_w(dotNET_ClassLibrary\dotNET_ClassLibrary\bin\x64\,
  11.     My_Configuration, \net9.0\dotNET_ClassLibrary.dll);

  12. ServerInfo_Struct<LPCOLESTR> My_Server_string[] = {
  13.   {
  14.      MyServerName,
  15.      (LPCOLESTR)OLESTR("DotNet_ClassLibrary.MyUnregisterServer1"),
  16.      (LPCOLESTR)OLESTR("CreateObject4_Chen"),
  17.      (LPCOLESTR)OLESTR("04D9F530-CE0C-4232-8F3F-6E0A3244C715"),
  18.      (LPCOLESTR)OLESTR("31D53FF8-4768-4A77-95E3-DC28DEBB375F")
  19.   },{
  20.      MyServerName,
  21.      (LPCOLESTR)OLESTR("DotNet_ClassLibrary.MyUnregisterServer2"),
  22.      (LPCOLESTR)OLESTR("CreateObject3_Chen"),
  23.      (LPCOLESTR)OLESTR("7FDF74B5-2E5D-4B72-B3A3-5BA424645F0D"),
  24.      (LPCOLESTR)OLESTR("FDD5D79A-386E-49D0-AF60-81222A990055")
  25.   },{
  26.      MyServerName,
  27.      (LPCOLESTR)OLESTR("DotNet_ClassLibrary.MyUnregisterServer2"),
  28.      (LPCOLESTR)OLESTR("CreateObject4_Chen"),
  29.      (LPCOLESTR)OLESTR("7FDF74B5-2E5D-4B72-B3A3-5BA424645F0D"),
  30.      (LPCOLESTR)OLESTR("FDD5D79A-386E-49D0-AF60-81222A990055")
  31.   }
  32. };
  33. /* Begin CPP_DLL_Test_UnregisteredServer1 */
  34. void This_Delegate_will_be_called_While_RaiseEvent(VARIANTARG VAR) {
  35.     ExportedData::MySelf()->WriteLine(L"This_Delegate_will_be_called_While_RaiseEvent(VT_BSTR=%d V_VT(&VAR)=%d)",
  36.         VT_BSTR, V_VT(&VAR));
  37.     ExportedData::MySelf()->WriteLine(L"<@%s@>", V_BSTR(&VAR));
  38. }
  39. __interface IUnregisteredServer1 :IDispatch
  40. {
  41.     HRESULT Get_Interface(PVOID*);
  42.     HRESULT Get_Interface2(long, VARIANTARG*);
  43.     HRESULT Register_Event(void (*)(VARIANT), BSTR, INT32* ID);
  44.     HRESULT RemoveEvent(INT32 ID);
  45.     HRESULT Raise_Event(LONG64);
  46.     HRESULT Get_MyProperty(INT32*);
  47.     HRESULT Put_MyProperty(INT32 pRetVal);
  48.     HRESULT GetTraceMessage(BSTR*);
  49. };
  50. int CPP_DLL_Test_UnregisteredServer1(TestParameter* ptr) {
  51.     HRESULT hr;
  52.     ExportedData ED(ptr, L"Test_UnregisteredServer1 CPP_DLL");
  53.     IUnregisteredServer1* pIUnregisteredServer1 = NULL;
  54.     int rv = Get_ServerInterface4(ptr, My_Server_string[0], (PVOID*)&pIUnregisteredServer1);
  55.     if (rv)return rv;

  56.     INT32 _INT32 = 777;
  57.     ED.WriteLine(L"(%d)", _INT32);
  58.     pIUnregisteredServer1->Get_MyProperty(&_INT32);
  59.     ED.WriteLine(L"(%d)", _INT32);

  60.     INT32 EventID[3]{};
  61.     BSTR MyString_BSTR = SysAllocString(L"Register_Event(&This_Delegate_will_be_called_While_RaiseEvent, MyString_BSTR)");
  62.     for (INT64 aa = 21; aa < 25; aa++) {
  63.         for (INT32 bb = 0; bb < sizeof(EventID) / sizeof(EventID[0]); bb++) {
  64.             pIUnregisteredServer1->Register_Event(&This_Delegate_will_be_called_While_RaiseEvent,
  65.                 MyString_BSTR, &EventID[bb]);
  66.         }
  67.         pIUnregisteredServer1->Raise_Event(aa);
  68.         for (INT32 bb = 0; bb < sizeof(EventID) / sizeof(EventID[0]); bb++) {
  69.             pIUnregisteredServer1->RemoveEvent(EventID[bb]);
  70.         }
  71.     }
  72.     ::SysFreeString(MyString_BSTR);

  73.     int errorCode = 0;
  74.     IUnknown* ptr_IUnknown1 = NULL;
  75.     IUnknown* ptr_IUnknown2 = NULL;
  76.     IUnknown* ptr_IUnknown3 = NULL;
  77.     IDispatch* ptr_IDispatch = NULL;
  78.     hr = pIUnregisteredServer1->Get_Interface((PVOID*)&ptr_IUnknown1);
  79.     if (FAILED(hr)) {
  80.         ED.WriteLine(L"error: pIUnregisteredServer1->Get_Interface hr=%X", hr);
  81.     }
  82.     VARIANT _variant;
  83.     VariantInit(&_variant);
  84.     hr = pIUnregisteredServer1->Get_Interface2(2, &_variant);
  85.     if (FAILED(hr)) {
  86.         ED.WriteLine(L"error: pIUnregisteredServer1->Get_Interface2 hr=%X", hr);
  87.     }

  88.     if (V_VT(&_variant) == VT_UNKNOWN) {
  89.         ptr_IUnknown2 = V_UNKNOWN(&_variant);
  90.         if (ptr_IUnknown2 != ptr_IUnknown1) errorCode = 1;
  91.     }
  92.     else if (V_VT(&_variant) == VT_DISPATCH) {
  93.         ptr_IDispatch = V_DISPATCH(&_variant);
  94.         if (ptr_IUnknown1 + 1 != ptr_IDispatch) errorCode = 2;
  95.     }
  96.     else errorCode = 3;
  97.     if (errorCode) {
  98.         pIUnregisteredServer1->QueryInterface(IID_IUnknown, (void**)&ptr_IUnknown3);
  99.         printf("         ptr_IUnknown3=%p\n", ptr_IUnknown3);
  100.         printf("         ptr_IUnknown2=%p\n", ptr_IUnknown2);
  101.         printf("         ptr_IUnknown1=%p\n", ptr_IUnknown1);
  102.         printf("         ptr_IDispatch=%p\n", ptr_IDispatch);
  103.         printf(" pIUnregisteredServer1=%p\n", pIUnregisteredServer1);
  104.         ED.WriteLine(
  105.             L"error: V_VT(&_variant)=%d VT_DISPATCH:%d VT_UNKNOWN=%d errorCode=%d",
  106.             V_VT(&_variant), VT_DISPATCH, VT_UNKNOWN, errorCode
  107.         );
  108.     }

  109.     BSTR MyMessage = NULL;
  110.     pIUnregisteredServer1->GetTraceMessage(&MyMessage);
  111.     ED.WriteLine(L"GetTraceMessage");
  112.     ED.WriteLine(L"%s", MyMessage);
  113.     SysFreeString(MyMessage);
  114.     return 0;
  115. }
  116. /* End  CPP_DLL_Test_UnregisteredServer1 */
  117. // 1 ======================================================= 2
  118. /* Begin CPP_DLL_Test_UnregisteredServer2 */
  119. __interface IUnregisteredServer2_CPP :public IDispatch
  120. {
  121. public:
  122.     HRESULT DefaultMarshallingForObject(VARIANT* v, VARIANT* v2, VARIANT* v3);
  123.     HRESULT Map_HResultAndException(BSTR* display);
  124.     HRESULT Hello_world3(
  125.         DECIMAL decimal2,
  126.         GUID guid2,
  127.         BSTR* outputResult
  128.     );

  129.     virtual HRESULT STDMETHODCALLTYPE QueryInterface2(
  130.         /* [in] */ REFIID riid,
  131.         /* [annotation][iid_is][out] */
  132.         _COM_Outptr_  void** ppvObject) = 0;

  133.     virtual ULONG STDMETHODCALLTYPE AddRef2(void) = 0;

  134.     virtual ULONG STDMETHODCALLTYPE Release2(void) = 0;

  135.     virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount2(
  136.         /* [out] */ __RPC__out UINT* pctinfo) = 0;

  137.     virtual HRESULT STDMETHODCALLTYPE GetTypeInfo2(
  138.         /* [in] */ UINT iTInfo,
  139.         /* [in] */ LCID lcid,
  140.         /* [out] */ __RPC__deref_out_opt ITypeInfo** ppTInfo) = 0;

  141.     virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames2(
  142.         /* [in] */ __RPC__in REFIID riid,
  143.         /* [size_is][in] */ __RPC__in_ecount_full(cNames) LPOLESTR* rgszNames,
  144.         /* [range][in] */ __RPC__in_range(0, 16384) UINT cNames,
  145.         /* [in] */ LCID lcid,
  146.         /* [size_is][out] */ __RPC__out_ecount_full(cNames) DISPID* rgDispId) = 0;

  147.     virtual /* [local] */ HRESULT STDMETHODCALLTYPE Invoke2(
  148.         /* [annotation][in] */
  149.         _In_  DISPID dispIdMember,
  150.         /* [annotation][in] */
  151.         _In_  REFIID riid,
  152.         /* [annotation][in] */
  153.         _In_  LCID lcid,
  154.         /* [annotation][in] */
  155.         _In_  WORD wFlags,
  156.         /* [annotation][out][in] */
  157.         _In_  DISPPARAMS* pDispParams,
  158.         /* [annotation][out] */
  159.         _Out_opt_  VARIANT* pVarResult,
  160.         /* [annotation][out] */
  161.         _Out_opt_  EXCEPINFO* pExcepInfo,
  162.         /* [annotation][out] */
  163.         _Out_opt_  UINT* puArgErr) = 0;

  164.     virtual HRESULT STDMETHODCALLTYPE GetTraceMessage(BSTR*) = 0;
  165. };
  166. extern "C" {
  167.     /* [unique][uuid][object] */
  168.     typedef interface IUnregisteredServer2_C IUnregisteredServer2_C;

  169.     typedef struct IUnregisteredServer2_CVtbl
  170.     {
  171.         BEGIN_INTERFACE

  172.             HRESULT(STDMETHODCALLTYPE* QueryInterface)(
  173.                 __RPC__in IDispatch* This,
  174.                 /* [in] */ __RPC__in REFIID riid,
  175.                 /* [annotation][iid_is][out] */
  176.                 _COM_Outptr_  void** ppvObject);

  177.         ULONG(STDMETHODCALLTYPE* AddRef)(
  178.             __RPC__in IUnregisteredServer2_C* This);

  179.         ULONG(STDMETHODCALLTYPE* Release)(
  180.             __RPC__in IUnregisteredServer2_C* This);

  181.         HRESULT(STDMETHODCALLTYPE* GetTypeInfoCount)(
  182.             __RPC__in IUnregisteredServer2_C* This,
  183.             /* [out] */ __RPC__out UINT* pctinfo);

  184.         HRESULT(STDMETHODCALLTYPE* GetTypeInfo)(
  185.             __RPC__in IUnregisteredServer2_C* This,
  186.             /* [in] */ UINT iTInfo,
  187.             /* [in] */ LCID lcid,
  188.             /* [out] */ __RPC__deref_out_opt ITypeInfo** ppTInfo);

  189.         HRESULT(STDMETHODCALLTYPE* GetIDsOfNames)(
  190.             __RPC__in IUnregisteredServer2_C* This,
  191.             /* [in] */ __RPC__in REFIID riid,
  192.             /* [size_is][in] */ __RPC__in_ecount_full(cNames) LPOLESTR* rgszNames,
  193.             /* [range][in] */ __RPC__in_range(0, 16384) UINT cNames,
  194.             /* [in] */ LCID lcid,
  195.             /* [size_is][out] */ __RPC__out_ecount_full(cNames) DISPID* rgDispId);

  196.         /* [local] */ HRESULT(STDMETHODCALLTYPE* Invoke)(
  197.             IUnregisteredServer2_C* This,
  198.             /* [annotation][in] */
  199.             _In_  DISPID dispIdMember,
  200.             /* [annotation][in] */
  201.             _In_  REFIID riid,
  202.             /* [annotation][in] */
  203.             _In_  LCID lcid,
  204.             /* [annotation][in] */
  205.             _In_  WORD wFlags,
  206.             /* [annotation][out][in] */
  207.             _In_  DISPPARAMS* pDispParams,
  208.             /* [annotation][out] */
  209.             _Out_opt_  VARIANT* pVarResult,
  210.             /* [annotation][out] */
  211.             _Out_opt_  EXCEPINFO* pExcepInfo,
  212.             /* [annotation][out] */
  213.             _Out_opt_  UINT* puArgErr);

  214.         /* [local] */ HRESULT(STDMETHODCALLTYPE* DefaultMarshallingForObject)(
  215.             __RPC__in IUnregisteredServer2_C* This,
  216.             VARIANT* v,
  217.             VARIANT* v2,
  218.             VARIANT* v3
  219.             );
  220.         /* [local] */ HRESULT(STDMETHODCALLTYPE* Map_HResultAndException)(
  221.             __RPC__in IUnregisteredServer2_C* This, BSTR* Display
  222.             );
  223.         /* [local] */ HRESULT(STDMETHODCALLTYPE* Hello_world3)(
  224.             __RPC__in IUnregisteredServer2_C* This,
  225.             DECIMAL decimal2,
  226.             GUID guid2,
  227.             BSTR* outputResult
  228.             );

  229.         HRESULT(STDMETHODCALLTYPE* QueryInterface2)(
  230.             __RPC__in IDispatch* This,
  231.             /* [in] */ __RPC__in REFIID riid,
  232.             /* [annotation][iid_is][out] */
  233.             _COM_Outptr_  void** ppvObject);

  234.         ULONG(STDMETHODCALLTYPE* AddRef2)(
  235.             __RPC__in IUnregisteredServer2_C* This);

  236.         ULONG(STDMETHODCALLTYPE* Release2)(
  237.             __RPC__in IUnregisteredServer2_C* This);

  238.         HRESULT(STDMETHODCALLTYPE* GetTypeInfoCount2)(
  239.             __RPC__in IUnregisteredServer2_C* This,
  240.             /* [out] */ __RPC__out UINT* pctinfo);

  241.         HRESULT(STDMETHODCALLTYPE* GetTypeInfo2)(
  242.             __RPC__in IUnregisteredServer2_C* This,
  243.             /* [in] */ UINT iTInfo,
  244.             /* [in] */ LCID lcid,
  245.             /* [out] */ __RPC__deref_out_opt ITypeInfo** ppTInfo);

  246.         HRESULT(STDMETHODCALLTYPE* GetIDsOfNames2)(
  247.             __RPC__in IUnregisteredServer2_C* This,
  248.             /* [in] */ __RPC__in REFIID riid,
  249.             /* [size_is][in] */ __RPC__in_ecount_full(cNames) LPOLESTR* rgszNames,
  250.             /* [range][in] */ __RPC__in_range(0, 16384) UINT cNames,
  251.             /* [in] */ LCID lcid,
  252.             /* [size_is][out] */ __RPC__out_ecount_full(cNames) DISPID* rgDispId);

  253.         /* [local] */ HRESULT(STDMETHODCALLTYPE* Invoke2)(
  254.             IUnregisteredServer2_C* This,
  255.             /* [annotation][in] */
  256.             _In_  DISPID dispIdMember,
  257.             /* [annotation][in] */
  258.             _In_  REFIID riid,
  259.             /* [annotation][in] */
  260.             _In_  LCID lcid,
  261.             /* [annotation][in] */
  262.             _In_  WORD wFlags,
  263.             /* [annotation][out][in] */
  264.             _In_  DISPPARAMS* pDispParams,
  265.             /* [annotation][out] */
  266.             _Out_opt_  VARIANT* pVarResult,
  267.             /* [annotation][out] */
  268.             _Out_opt_  EXCEPINFO* pExcepInfo,
  269.             /* [annotation][out] */
  270.             _Out_opt_  UINT* puArgErr);

  271.         /* [local] */ HRESULT(STDMETHODCALLTYPE* GetTraceMessage)(
  272.             __RPC__in IUnregisteredServer2_C* This, BSTR*
  273.             );
  274.         END_INTERFACE
  275.     } IUnregisteredServer2_CVtbl;

  276.     interface IUnregisteredServer2_C
  277.     {
  278.         CONST_VTBL struct IUnregisteredServer2_CVtbl* lpVtbl;
  279.     };

  280. #define IUnregisteredServer2_C_QueryInterface(This,riid,ppvObject) \
  281.     ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) 

  282. #define IUnregisteredServer2_C_AddRef(This) \
  283.     ( (This)->lpVtbl -> AddRef(This) ) 

  284. #define IUnregisteredServer2_C_Release(This) \
  285.     ( (This)->lpVtbl -> Release(This) ) 


  286. #define IUnregisteredServer2_C_GetTypeInfoCount(This,pctinfo) \
  287.     ( (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) ) 

  288. #define IUnregisteredServer2_C_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
  289.     ( (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) ) 

  290. #define IUnregisteredServer2_C_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \
  291.     ( (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) ) 

  292. #define IUnregisteredServer2_C_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \
  293.     ( (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) ) 

  294. #define IUnregisteredServer2_C_DefaultMarshallingForObject(This,variant,v2,v3) \
  295.     ( (This)->lpVtbl -> DefaultMarshallingForObject(This,variant,v2,v3) ) 

  296. }
  297. int CPP_DLL_Test_UnregisteredServer2(TestParameter* ptr) {
  298.     HRESULT hr;
  299.     ExportedData ED(ptr, L"Test_UnregisteredServer2 CPP_DLL");
  300.     IUnregisteredServer2_CPP* pIUnregisteredServer2_CPP;
  301.     int rv = Get_ServerInterface(ptr, My_Server_string[1], (PVOID*)&pIUnregisteredServer2_CPP);
  302.     if (rv)return rv;

  303.     VARIANT v, v2, v3;
  304.     VariantInit(&v); VariantInit(&v2); VariantInit(&v3);
  305.     InitVariantFromInt32(0x12345, &v);
  306.     ED.WriteLine(L"V_VT(&v)=%d %X", V_VT(&v), V_I8(&v));
  307.     pIUnregisteredServer2_CPP->DefaultMarshallingForObject(&v, &v2, &v3);
  308.     if (V_VT(&v) != VT_I8) return -3005;
  309.     ED.WriteLine(L"V_VT(&v)=%d %X ", V_VT(&v), V_I8(&v));
  310.     ED.WriteLine(L"V_VT(&v2)=%d %f ", V_VT(&v2), V_R8(&v2));

  311.     DECIMAL d{ };
  312.     GUID g;
  313.     d.Lo32 = 6666666; d.scale = 3;

  314.     hr = CLSIDFromString(OLESTR("{45A82A95-6446-43F0-83B9-71E7469E14D2}"),
  315.         &g);
  316.     if (FAILED(hr)) return  -3008;
  317.     BSTR outputResult = NULL;
  318.     pIUnregisteredServer2_CPP->Hello_world3(d, g,
  319.         &outputResult);
  320.     ED.WriteLine(L"outputResult %s", outputResult);
  321.     ::SysFreeString(outputResult);

  322.     IUnregisteredServer2_C* pIUnregisteredServer2_C =
  323.         (IUnregisteredServer2_C*)pIUnregisteredServer2_CPP;
  324.     if ((void*)pIUnregisteredServer2_CPP != (void*)pIUnregisteredServer2_C) {
  325.         ED.WriteLine(L"pIUnregisteredServer2_CPP=%p", pIUnregisteredServer2_CPP);
  326.         ED.WriteLine(L"pIUnregisteredServer2_C  =%p", pIUnregisteredServer2_C);
  327.     }

  328.     VariantInit(&v);
  329.     VariantInit(&v2);
  330.     VariantInit(&v3);
  331.     InitVariantFromInt32(321, &v);
  332.     for (int aa = 0; aa < 1; aa++) {
  333.         IUnregisteredServer2_C_DefaultMarshallingForObject(
  334.             pIUnregisteredServer2_C, &v, &v2, &v3);
  335.         ED.WriteLine(L"V_VT(&v)=%d %X", V_VT(&v), V_I8(&v));
  336.     }

  337.     BSTR Display = NULL;
  338.     hr = pIUnregisteredServer2_C->lpVtbl->Map_HResultAndException(
  339.         pIUnregisteredServer2_C, &Display);
  340.     ED.WriteLine(L"hr=0X%X", hr);
  341.     ED.WriteLine(L"Display=%s", Display);
  342.     if (Display)  ::SysFreeString(Display);
  343.     ED.WriteLine(L"sizeof(lpVtbl)=%d", sizeof(pIUnregisteredServer2_C->lpVtbl));


  344.     BSTR MyMessage = NULL;
  345.     pIUnregisteredServer2_C->lpVtbl->GetTraceMessage(
  346.         pIUnregisteredServer2_C, &MyMessage);
  347.     ED.WriteLine(L"GetTraceMessage");
  348.     ED.WriteLine(L"%s", MyMessage);
  349.     SysFreeString(MyMessage);
  350.     return 0;
  351. }
  352. /* End  CPP_DLL_Test_UnregisteredServer2 */
  353. // 2 ================================================= 3
  354. /* Begin CPP_DLL_Test_IXXXX */
  355. __interface IXXXX :public IUnregisteredServer2_CPP
  356. {
  357.     HRESULT YYYY(INT64*);
  358.     HRESULT YYYY1(BSTR*);
  359. };

  360. int CPP_DLL_Test_IXXXX(TestParameter* ptr) {
  361.     ExportedData ED(ptr, L"Test_IXXXX CPP_DLL");
  362.     IXXXX* pIXXXX;
  363.     int rv = Get_ServerInterface4(ptr, My_Server_string[2], (PVOID*)&pIXXXX);
  364.     if (rv)return rv;
  365.     INT64 aaa;
  366.     pIXXXX->YYYY(&aaa);
  367.     ED.WriteLine(L"aaa = %d", aaa);

  368.     BSTR comment = ::SysAllocString(L" ABC ");
  369.     pIXXXX->YYYY1(&comment);
  370.     ED.WriteLine(L"comment=%s", comment);
  371.     ::SysFreeString(comment);

  372.     BSTR Trace = NULL;
  373.     pIXXXX->GetTraceMessage(&Trace);
  374.     ED.WriteLine(L"%s", Trace);
  375.     ::SysFreeString(Trace);
  376.     return 0;
  377. }
  378. /* End CPP_DLL_Test_IXXXX */
  379. #endif 




















  1. #If TARGET = "library" And PLATFORM = "x64" Then
  2. Option Strict On
  3. Imports System.Runtime.InteropServices

  4. <ComClass(MyUnregisterServer1.ClassId, MyUnregisterServer1.InterfaceId)>
  5. Public Class MyUnregisterServer1
  6.     Public Const ClassId As String = "04D9F530-CE0C-4232-8F3F-6E0A3244C715"
  7.     Public Const InterfaceId As String = "31D53FF8-4768-4A77-95E3-DC28DEBB375F"
  8.     ReadOnly Property Get_Interface() As <MarshalAs(UnmanagedType.IUnknown)> Object
  9.         Get
  10.             MyTrace("Get_Interface")
  11.             Return CreateObject_Chen()
  12.         End Get
  13.     End Property
  14.     Sub Get_Interface2(Interface_ID As Int32,
  15.           <Out> ByRef ppVoid As Object)
  16.         MyTrace("Get_Interface2")
  17.         ppVoid = CreateObject_Chen()
  18.     End Sub
  19.     Sub Register_Event(
  20.      <[In]> FunctionPointer As IntPtr,
  21.      <[In], MarshalAs(UnmanagedType.BStr)> BSTR_String As String,
  22.      <Out> ByRef ID As Int32)

  23.         CppEventClassObj.Register_Event(FunctionPointer, BSTR_String, ID)
  24.         MyTrace($"Register_Event {ID}")
  25.     End Sub
  26.     Sub RemoveEvent(<[In]> ID As Int32)
  27.         MyTrace($"RemoveEvent {ID}")
  28.         CppEventClassObj.RemoveEvent(ID)
  29.     End Sub
  30.     Sub Raise_Event(MyTestParameter As Int64)
  31.         MyTrace($"Raise_Event {MyTestParameter}")
  32.         CppEventClassObj.RaiseEventParameter = MyTestParameter
  33.         RaiseEvent Cpp_Event(Me, CppEventClassObj)
  34.     End Sub
  35.     Dim _MyProperty As Int32 = 222
  36.     Property MyProperty As Int32
  37.         Get
  38.             MyTrace($"Get MyProperty {_MyProperty + 111}")
  39.             Return _MyProperty + 111
  40.         End Get
  41.         Set(value As Int32)
  42.             MyTrace($"Set MyProperty value= {value}")
  43.             _MyProperty = value
  44.         End Set
  45.     End Property
  46.     ReadOnly Property TraceMessage As String
  47.         Get
  48.             TraceMessage = Environment.NewLine &
  49.              "==== TraceMessage(Chen Inn-Jer) ======" &
  50.              Environment.NewLine & _TraceMessage.ToString() &
  51.              "==== TraceMessage(Chen Inn-Jer) ======" &
  52.              Environment.NewLine
  53.             _TraceMessage.Clear() : TraceSteps = 0
  54.         End Get
  55.     End Property
  56.     '1----------------------------------------------------

  57.     Private Class CppEventClass : Inherits EventArgs
  58.         Public RaiseEventParameter As Int64
  59.         Private EventCount As Int32
  60.         Private Delegate Sub DelegateForFunctionPointer(
  61.                        ByRef obj As System.Object)
  62.         Private Structure RegisterEvent_Struct
  63.             Dim FunctionPtr As IntPtr
  64.             Dim InputString As String
  65.             Dim ID As Int32
  66.         End Structure
  67.         Dim ObjectOwnCppEvent As MyUnregisterServer1
  68.         ReadOnly RegisterEventList As List(Of RegisterEvent_Struct)
  69.         Sub New(ObjectOwnCppEvent As MyUnregisterServer1)
  70.             Me.ObjectOwnCppEvent = ObjectOwnCppEvent
  71.             RegisterEventList = New List(Of RegisterEvent_Struct)
  72.         End Sub
  73.         Sub Register_Event(FunctionPointer As IntPtr,
  74.               BSTR_String As String, ByRef ID As Int32)
  75.             EventCount += 1
  76.             ID = EventCount
  77.             RegisterEventList.Add(New RegisterEvent_Struct With {
  78.             .FunctionPtr = FunctionPointer,
  79.             .InputString = BSTR_String,
  80.             .ID = ID
  81.             })
  82.             If RegisterEventList.Count = 1 Then
  83.                 AddHandler ObjectOwnCppEvent.Cpp_Event,
  84.                  AddressOf Handler_For_Cpp_Event
  85.             End If
  86.         End Sub
  87.         Sub RemoveEvent(ID As Int32)
  88.             For Each myitem As RegisterEvent_Struct In RegisterEventList
  89.                 If myitem.ID = ID Then
  90.                     If RegisterEventList.Count = 1 Then
  91.                         RemoveHandler ObjectOwnCppEvent.Cpp_Event,
  92.                             AddressOf Handler_For_Cpp_Event
  93.                     End If
  94.                     RegisterEventList.Remove(myitem)
  95.                     Exit Sub
  96.                 End If
  97.             Next
  98.             Throw New MyException(&HA0010002, "Error:RemoveEvent")
  99.         End Sub
  100.         Private Sub Handler_For_Cpp_Event(sender As Object, e As EventArgs)
  101.             For Each MyItem As RegisterEvent_Struct In RegisterEventList
  102.                 Dim DelegateForFunPtr As DelegateForFunctionPointer = CType(
  103.                       Marshal.GetDelegateForFunctionPointer(
  104.                       MyItem.FunctionPtr, GetType(DelegateForFunctionPointer)),
  105.                        DelegateForFunctionPointer)
  106.                 If DelegateForFunPtr Is Nothing Then
  107.                     'MsgBox("DelegateForFunPtr Is Nothing")
  108.                 Else
  109.                     DelegateForFunPtr.Invoke(
  110.                       $"({RaiseEventParameter})" &
  111.                       "Sub Handler_For_Cpp_Event" &
  112.                       Environment.NewLine & MyItem.InputString)
  113.                 End If
  114.             Next
  115.         End Sub
  116.     End Class
  117.     Private ReadOnly CppEventClassObj As CppEventClass
  118.     Private Event Cpp_Event As EventHandler

  119.     Shared Function CreateObject_Chen() As MyUnregisterServer1
  120.         If MyUnregisterServer1_Object Is Nothing Then
  121.             MyUnregisterServer1_Object = New MyUnregisterServer1
  122.         End If
  123.         Return MyUnregisterServer1_Object
  124.     End Function
  125.     Shared MyUnregisterServer1_Object As MyUnregisterServer1
  126.     Shared Sub CreateObject3_Chen(ByRef IID As Guid,
  127.        ppvoid_temp As IntPtr, Not_Used As IntPtr)
  128.         If MyUnregisterServer1_Object Is Nothing Then
  129.             MyUnregisterServer1_Object = New MyUnregisterServer1
  130.         End If

  131.         MyUnregisterServer1_Object.MyTrace(
  132.           $"MyUnregisterServer1 IID={IID}  Not_Used = {Not_Used}")
  133.         Dim ppVoid As IntPtr
  134.         Dim MyIID As Guid = Guid.Parse(InterfaceId)
  135.         If MyIID = IID Then
  136.             ppVoid = Marshal.GetIUnknownForObject(MyUnregisterServer1_Object)
  137.         Else
  138.             ppVoid = IntPtr.Zero
  139.         End If
  140.         Marshal.WriteIntPtr(ppvoid_temp, ppVoid)
  141.     End Sub
  142.     Shared Function CreateObject4_Chen(ByRef IID As Guid,
  143.         Not_Used As IntPtr) As Object
  144.         If MyUnregisterServer1_Object Is Nothing Then
  145.             MyUnregisterServer1_Object = New MyUnregisterServer1()
  146.         End If
  147.         MyUnregisterServer1_Object.MyTrace(
  148.           $"MyUnregisterServer1 IID={IID}  Not_Used = {Not_Used}")

  149.         Dim MyIID As Guid = Guid.Parse(InterfaceId)
  150.         If MyIID = IID Then
  151.             'Console.WriteLine("CreateObject4_Chen ---Object")
  152.             Return MyUnregisterServer1_Object
  153.         End If
  154.         'Console.WriteLine("CreateObject4_Chen Nothing")
  155.         Return Nothing
  156.     End Function

  157.     Sub New()
  158.         MyBase.New()
  159.         CppEventClassObj = New CppEventClass(Me)
  160.         _TraceMessage = New Text.StringBuilder
  161.         TraceSteps = 0
  162.     End Sub
  163.     Private Class MyException
  164.         Inherits Exception
  165.         Sub New(errorcode As Int32, Message As String)
  166.             MyBase.New(Message)
  167.             HResult = errorcode
  168.         End Sub
  169.     End Class
  170.     Private TraceSteps As Int32
  171.     Private ReadOnly _TraceMessage As Text.StringBuilder
  172.     Private Sub MyTrace(msg As String)
  173.         TraceSteps += 1
  174.         _TraceMessage.AppendLine($"{TraceSteps:d2} : {msg}")
  175.     End Sub
  176. End Class
  177. '1 ================================================== 2


  178. <ComClass(MyUnregisterServer2.ClassId, MyUnregisterServer2.InterfaceId)>
  179. Public Class MyUnregisterServer2
  180.     Public Const ClassId As String = "7FDF74B5-2E5D-4B72-B3A3-5BA424645F0D"
  181.     Public Const InterfaceId As String = "FDD5D79A-386E-49D0-AF60-81222A990055"
  182.     Sub DefaultMarshallingForObject(ByRef obj As Object,
  183.                                          ByRef obj2 As Object,
  184.                                          ByRef obj3 As Object
  185.                                            )
  186.         MyTrace($"({obj})DefaultMarshallingForObject-->&H999L")
  187.         obj = &H999L
  188.         'obj2 = New System.Decimal(666666)
  189.         obj2 = 666.6666
  190.     End Sub
  191.     Sub Map_HResultAndException(
  192.        <Out, MarshalAs(UnmanagedType.BStr)>
  193.        ByRef Display As String
  194.      )
  195.         MyTrace("Map_HResultAndException")
  196.         'Beep()
  197.         Try
  198.             Marshal.ThrowExceptionForHR(&H80040154)
  199.         Catch ex As Exception
  200.             Display = $"msg={ex.Message}"
  201.             MyTrace(Display)
  202.             Throw New MyException(&HA1110000, ex.Message & " -- Chen")
  203.         End Try
  204.     End Sub
  205.     Sub Hello_world3(
  206.         decimal2 As System.Decimal,
  207.         guid As System.Guid,
  208.      <Out, MarshalAs(UnmanagedType.BStr)> ByRef outputResult As String
  209.         )
  210.         outputResult =
  211.          $" decimal= {decimal2} guid= {guid}"
  212.     End Sub
  213.     Sub QueryInterface2(
  214.      <[In](), MarshalAs(UnmanagedType.LPStruct)> REFIID_riid As Guid,
  215.      <Out, MarshalAs(UnmanagedType.IUnknown)> ByRef ppVoid As Object)
  216.     End Sub
  217.     Sub AddRef2()

  218.     End Sub
  219.     Sub Release2()

  220.     End Sub
  221.     Sub GetTypeInfoCount2(
  222.        <Out> ByRef out_UINT_pctinfo As UInt32)
  223.     End Sub
  224.     Sub GetTypeInfo2(
  225.         itinfo As UInt32, lcid As UInt32,
  226.       <Out, MarshalAs(UnmanagedType.Interface)> ByRef ppTInfo As Object
  227.    )
  228.     End Sub
  229.     Sub GetIDsOfNames2(
  230.       <[In](), MarshalAs(UnmanagedType.LPStruct)> REFIID_riid As Guid,
  231.       <[In](), MarshalAs(UnmanagedType.LPStr)> LPOLESTR_rgszNames As String,
  232.       <[In]()> cNames As UInt32,
  233.       <[In]()> LCID_lcid As UInt32,
  234.       <Out> ByRef rgDispId As Int32)
  235.     End Sub
  236.     Sub Invoke2(
  237.        <[In]()> _In_DISPID_dispIdMember As Int32,
  238.        <[In](), MarshalAs(UnmanagedType.LPStruct)> _In_REFIIDriid As Guid,
  239.        <[In]()> _In_LCID_lcid As UInt32,
  240.        <[In]()> _In_WORD_wFlags As UInt16,
  241.        <[In]()> _In_pDispParams As IntPtr,
  242.        <Out> ByRef _Out_opt_VARIANT_pVarResult As Object,
  243.        <Out> ByRef _Out_opt_pExcepInfo As IntPtr,
  244.        <Out> ByRef _Out_opt_puArgErr As UInt32)
  245.     End Sub
  246.     ReadOnly Property TraceMessage As String
  247.         Get
  248.             TraceMessage = Environment.NewLine &
  249.              "==== TraceMessage(Chen Inn-Jer) 2 ======" &
  250.              Environment.NewLine & _TraceMessage.ToString() &
  251.              "==== TraceMessage(Chen Inn-Jer) 2 ======" &
  252.              Environment.NewLine
  253.             _TraceMessage.Clear() : TraceSteps = 0
  254.         End Get
  255.     End Property
  256.     Sub YYYY(<Out> ByRef intptr_obj As IntPtr)
  257.         intptr_obj = New IntPtr(12345678)
  258.         MyTrace($"YYYY({intptr_obj})")
  259.     End Sub
  260.     Sub YYYY1(<[In], Out, MarshalAs(UnmanagedType.BStr)> ByRef Comment As String)
  261.         MyTrace($"YYYY1 {Comment}")
  262.         Dim MainType As Type = GetType(MyUnregisterServer2)
  263.         Dim ThisModule As Reflection.Module = MainType.Module
  264.         Dim peKind As Reflection.PortableExecutableKinds
  265.         Dim machine As Reflection.ImageFileMachine
  266.         ThisModule.GetPEKind(peKind, machine)
  267.         Comment = "This is YYYY1 in MyUnregisterServer1" &
  268.         Environment.NewLine & "MyLocation is " &
  269.          Reflection.Assembly.GetExecutingAssembly.Location &
  270.         Environment.NewLine & "FrameworkDescription is " &
  271.           Runtime.InteropServices.RuntimeInformation.FrameworkDescription &
  272.         Environment.NewLine & $"machine={machine} peKind={peKind}" &
  273.         Environment.NewLine

  274.     End Sub
  275.     '2------------------------------------------------
  276.     Shared MyUnregisterServer2_Object As MyUnregisterServer2
  277.     Shared Sub CreateObject3_Chen(ByRef IID As Guid,
  278.         ppvoid_temp As IntPtr, Not_Used As IntPtr)
  279.         If MyUnregisterServer2_Object Is Nothing Then
  280.             MyUnregisterServer2_Object = New MyUnregisterServer2()
  281.         End If
  282.         MyUnregisterServer2_Object.MyTrace(
  283.           $"MyUnregisterServer2 IID={IID}  Not_Used = {Not_Used}")

  284.         Dim ppvoid As IntPtr
  285.         Dim MyIID As Guid = Guid.Parse(InterfaceId)
  286.         If MyIID = IID Then
  287.             ppvoid = Marshal.GetIUnknownForObject(MyUnregisterServer2_Object)
  288.         Else
  289.             ppvoid = IntPtr.Zero
  290.         End If
  291.         Marshal.WriteIntPtr(ppvoid_temp, ppvoid)
  292.     End Sub
  293.     Shared Function CreateObject4_Chen(ByRef IID As Guid,
  294.         Not_Used As IntPtr) As Object
  295.         If MyUnregisterServer2_Object Is Nothing Then
  296.             MyUnregisterServer2_Object = New MyUnregisterServer2()
  297.         End If
  298.         MyUnregisterServer2_Object.MyTrace(
  299.           $"MyUnregisterServer2 IID={IID}  Not_Used = {Not_Used}")

  300.         Dim MyIID As Guid = Guid.Parse(InterfaceId)
  301.         If MyIID = IID Then
  302.             'Console.WriteLine("CreateObject4_Chen ---Object")
  303.             Return MyUnregisterServer2_Object
  304.         End If
  305.         'Console.WriteLine("CreateObject4_Chen Nothing")
  306.         Return Nothing
  307.     End Function

  308.     Sub New()
  309.         MyBase.New()
  310.         _TraceMessage = New Text.StringBuilder(5 << 20)
  311.         TraceSteps = 0
  312.     End Sub
  313.     Private Class MyException
  314.         Inherits Exception
  315.         Sub New(errorcode As Int32, Message As String)
  316.             MyBase.New(Message)
  317.             HResult = errorcode
  318.         End Sub
  319.     End Class
  320.     Dim TraceSteps As Int32
  321.     Dim _TraceMessage As Text.StringBuilder
  322.     Private Sub MyTrace(msg As String)
  323.         TraceSteps += 1
  324.         _TraceMessage.AppendLine($"{TraceSteps:d2} : {msg}")
  325.     End Sub

  326. End Class
  327. #End If
























留言

這個網誌中的熱門文章

Marshalling

Calling a C# WPF library from C++

Marshalling II