COM in please, how to make out-of-process COM server work? (fixed) - com

I have difficult to make an out-of-process COM server work properly. My steps are
1. define idl (classic.idl)
import "objidlbase.idl";
[
uuid(CF86E2E0-B12D-4C6A-9C5A-D7AA65101E91),
]
coclass CClassic
{
[default] interface IClassic;
}
[
object,
uuid(CF86E2E0-B12D-4C6A-9C5A-D7AA65101E90),
pointer_default(unique)
]
interface IClassic : IUnknown
{
HRESULT Hello();
}
2. generate the proxy/stub files
midl /nologo /out classic /I"D:\EWDK\Program Files\Windows Kits\10\Include\10.0.19041.0\um" /I"D:\EWDK\Program Files\Windows Kits\10\Include\10.0.19041.0\shared" classic.idl
3. implement the interface (comobj.cpp)
#include <atlbase.h>
#include <atlcom.h>
#include "classic/classic.h"
CComModule _Module;
extern "C" CLSID CLSID_CClassic;
struct Toast : CComObjectRoot,CComCoClass<Toast,&CLSID_CClassic>,IClassic
{
DECLARE_REGISTRY(CLSID_CClassic,"Toaster.1.0","Toaster","Toast Server",THREADFLAGS_BOTH);
DECLARE_CLASSFACTORY();
DECLARE_OBJECT_DESCRIPTION("Toast Server");
BEGIN_COM_MAP(Toast)
COM_INTERFACE_ENTRY(IClassic)
END_COM_MAP();
HRESULT STDMETHODCALLTYPE Hello( void)
{
printf("Hello\n");
return S_OK;
}
};
OBJECT_ENTRY_AUTO(CLSID_CClassic,Toast);
4. write the out-of-process module (comexe.cpp)
#include <atlbase.h>
#include <atlcom.h>
struct MyModule : CAtlExeModuleT<MyModule>
{
};
MyModule mod;
int main(int argc, char *args[])
{
mod.WinMain(SW_HIDE);
}
5. compile the module
cl /nologo /EHsc comexe.cpp comobj.cpp classic/classic_i.c /link /debug
6. compile the proxy/stub
cl /nologo /EHsc /DREGISTER_PROXY_DLL /DPROXY_CLSID=CLSID_CClassic classic/classic_p.c classic/classic_i.c classic/dlldata.c /link /dll /out:comproxy.dll /export:DllGetClassObject /export:DllCanUnloadNow /export:DllRegisterServer /export:DllUnregisterServer /export:GetProxyDllInfo rpcrt4.lib
7. register server (with sysadmin account)
comexe /RegServer
8. register proxy/stub (with sysadmin account)
regsvr32 comproxy.dll
7 and 8 are on the same machine
9. write a test client (test.cpp)
#include <Unknwn.h>
#include <stdio.h>
#include "classic\classic.h"
#pragma comment(lib, "ole32")
extern "C" CLSID CLSID_CClassic;
int main(int argc, char *args[])
{
CoInitialize(nullptr);
IClassic *ifc = nullptr;
HRESULT hr;
if(argc<2) return 1;
switch(args[1][0])
{
case 'I':
case 'i':
hr = CoCreateInstance(CLSID_CClassic,nullptr,CLSCTX_INPROC_SERVER,IID_IClassic,(void**)&ifc);
break;
case 'O':
case 'o':
hr = CoCreateInstance(CLSID_CClassic,nullptr,CLSCTX_LOCAL_SERVER,IID_IClassic,(void**)&ifc);
default:
;
}
printf("0x%x\n",hr);
}
10. compile the test
cl /nologo /std:c++latest /EHsc test.cpp classic/classic_i.c /link /debug
11. run the test
on the same machine
test O
0x80004002
test I
0x80004002
Please help. Many thanks!!!
Update
Finally, I found in the step 6 I should use PROXY_CLSID_IS instead of PROXY_CLSID to define the CLSID for the proxy/stub which must different from CLSID_CClassic, that is:
cl /nologo /EHsc /DREGISTER_PROXY_DLL /DPROXY_CLSID_IS={0xCF86E2E0,0xB12D,0x4C6A,{0x9C,0x5A,0xD7,0xAA,0x65,0x10,0x1E,0x93}} classic/classic_p.c classic/classic_i.c classic/dlldata.c /link /dll /out:comproxy.dll /export:DllGetClassObject /export:DllCanUnloadNow /export:DllRegisterServer /export:DllUnregisterServer /export:GetProxyDllInfo rpcrt4.lib
and this time
test O
0x0
and test I still failed, but I think it is not the right way to call an out-of-process server.

Related

Segmentation Fault when i use std::packaged_task?

these code complie success but running error. like
#include <thread>
#include <future>
#include <functional>
#include <memory>
int func(int x, int y)
{
return x + y;
}
void main()
{
std::packaged_task<int()> task(std::bind(func, 2, 11));
std::future<int> ret = task.get_future();
task();
std::cout << ret.get() << std::endl;
}
segment infomation :
#1 0x56cdb624 in std::__future_base::_State_baseV2::_M_set_result(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>, bool) (this=0x578a814c, __res=..., __ignore_failure=false) at /opt/buildtools/gcc-7.3.0/include/c++/7.3.0/future:401
#2 0x56cde1bc in std::__future_base::_Task_state<std::_Bind<int (*(int, int))(int, int)>, std::allocator<int>, int ()>::_M_run() (this=0x578a814c)
at /opt/buildtools/gcc-7.3.0/include/c++/7.3.0/future:1423
#3 0x56cdc239 in std::packaged_task<int ()>::operator()() (this=0xffffc154) at /opt/buildtools/gcc-7.3.0/include/c++/7.3.0/future:1556
#4 0x56cdb072 in test () at /home/builduser/code/sourcecode/otn_xcs_board/bd_otn_test/code/test_frame/test_main.cpp:22
#5 0x56cdb11d in main (argc=1, argv=0xffffc244) at /home/builduser/code/sourcecode/otn_xcs_board/bd_otn_test/code/test_frame/test_main.cpp:28
i try to run same code in another environment, visual studio 2022 or clion . everything goes well.
but same code in linux environment gets segment fault, why ?
version
g++ (GCC) 7.3.0
c++17

Linker error in boost serialization of custom archive

I've tried to implement an own archive type for boost serialization following official boost example to write archives.
#include <iostream>
#include <vector>
#include <boost/serialization/nvp.hpp>
#include "boost/serialization/vector.hpp"
#include <boost/archive/detail/common_oarchive.hpp>
#include <boost/archive/detail/register_archive.hpp>
#include <boost/archive/detail/archive_serializer_map.hpp>
class complete_oarchive : public boost::archive::detail::common_oarchive<complete_oarchive>
{
friend class boost::archive::save_access;
template<class T>
void save(T & t){
std::cout << "saved data\n";
}
public:
void save_binary(void *address, std::size_t count){
}
};
template class boost::archive::detail::archive_serializer_map<complete_oarchive>;
template class boost::archive::detail::common_oarchive<complete_oarchive>;
BOOST_SERIALIZATION_REGISTER_ARCHIVE(complete_oarchive)
int main(int argc, char *argv[])
{
std::vector<double> testVector = {1, 2, 3, 4};
complete_oarchive oa;
std::vector<double>* pVec = &testVector;
oa << BOOST_SERIALIZATION_NVP(testVector);
oa << BOOST_SERIALIZATION_NVP(pVec);
return 0;
}
Compiling this example with
g++ -c -g -std=c++11 -MMD -MP -MF "build/Debug/GNU-Linux/demo.o.d" -o build/Debug/GNU-Linux/demo.o demo.cpp
g++ -o dist/Debug/GNU-Linux/serializationdemo build/Debug/GNU-Linux/demo.o -lboost_serialization
leads to the following linker error
build/Debug/GNU-Linux/demo.o: In function `boost::archive::detail::pointer_oserializer<complete_oarchive, std::vector<double, std::allocator<double> > >::pointer_oserializer()':
/opt/tools/boost/boostRdk-1.66.0/include/boost/archive/detail/oserializer.hpp:222: undefined reference to `boost::archive::detail::archive_serializer_map<complete_oarchive>::insert(boost::archive::detail::basic_serializer const*)'
build/Debug/GNU-Linux/demo.o: In function `boost::archive::detail::pointer_oserializer<complete_oarchive, std::vector<double, std::allocator<double> > >::~pointer_oserializer()':
/opt/tools/boost/boostRdk-1.66.0/include/boost/archive/detail/oserializer.hpp:227: undefined reference to `boost::archive::detail::archive_serializer_map<complete_oarchive>::erase(boost::archive::detail::basic_serializer const*)'
collect2: error: ld returned 1 exit status
It seems that serializing a pointer in
oa << BOOST_SERIALIZATION_NVP(pVec);
leads to this error. After deletion of this line everything works fine and the result is as expected.
Does anybody have experience in writting own serialization archives?
A simimal Problem was solved here
https://groups.google.com/forum/#!topic/boost-list/CMoDosGZUo8
but I wasn't able to solve this by forward declarations.
I solved the issue by replacing
#include <boost/archive/detail/archive_serializer_map.hpp>
by
#include <boost/archive/impl/archive_serializer_map.ipp>

C++17 refuses to compile example if constexpr giving expected ‘(’ before ‘constexpr’

I am trying out this text-book example of using if constexpr and I am getting error expected ‘(’ before ‘constexpr’ when compiling.
I am compiling with g++ -std=c++17 test.cpp so the version should support it. Visual Studio Code understands this and hints that this expression will be compiled to number 120 (correct).
#include <iostream>
using std::cout;
using std::endl;
template <int N>
constexpr int fun() {
if constexpr (N <= 1) {
return 1;
} else {
return N * fun<N - 1>();
}
}
int main(int argc, char** argv) {
cout << fun<5>() << endl;
return 0;
}
This code should compile error-free
You need a more recent version of GCC. Version 7 and up support this. See:
https://en.cppreference.com/w/cpp/compiler_support#cpp17
(Search for "constexpr if".)
So upgrade your GCC version. If you're on Ubuntu, you can add the Toolchain PPA to install the latest available GCC version:
https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test

GetProcAddress returning the correct address with Visual C++ and an incorrect address with g++

This is going to sound really strange. I am using Visual Studio 2017 C++ (native mode) and also, g++ 4.7.1-2 of the MingW toolchain. Target is Windows 64bit.
Using VS C++, I compile the following trivial program:
`
#include "stdafx.h"
#include <Windows.h>
#include <winternl.h>
typedef NTSTATUS (NTAPI* RTLINT64)(ULONGLONG, ULONG, PUNICODE_STRING);
RTLINT64 RtlInt64 = (RTLINT64) nullptr;
int main()
{
UNICODE_STRING unicodestring = { 0 };
WCHAR localbuffer[256] = { 0 }; // way more than enough
__int64 value = 0;
unicodestring.Length = 0;
unicodestring.MaximumLength = sizeof(localbuffer);
unicodestring.Buffer = (PWCH) &localbuffer;
// get ntdll's module handle
HMODULE NtDllModule = LoadLibrary(L"ntdll.dll");
if (NtDllModule)
{
RtlInt64 = (RTLINT64) GetProcAddress(NtDllModule,
"RtlInt64ToUnicodeString");
value = 0xFFFFFFFFF;
RtlInt64 (value, 10, &unicodestring);
wprintf(L"%s\n", unicodestring.Buffer);
}
return 0;
}
`
As expected, GetProcAddress returns the address of RtlInt64ToUnicodeString (no surprise there!)
The code below is, with exception of the includes, pretty much a carbon copy of the above. Yet, somehow, in that version compiled with G++, GetProcAddress returns the address of RtlInterlockedSetBitRun instead of the address of RtlInt64ToUnicodeString (that IS a surprise!). Here is the code:
// GCC and MingW version
#include <Windows.h>
#include <winbase.h>
#include <strsafe.h>
#include <winuser.h>
#include <winternl.h>
// --------------------------------------------------------------------------
typedef NTSTATUS(NTAPI* RTLINT64)(ULONGLONG, ULONG, PUNICODE_STRING);
RTLINT64 RtlInt64 = (RTLINT64) nullptr;
// --------------------------------------------------------------------------
int main(int argc, char *argv[])
{
WCHAR localbuffer[256] = {0}; // way more than enough
UNICODE_STRING unicodestring = {0};
__int64 value = 0;
unicodestring.Length = 0;
unicodestring.MaximumLength = sizeof(localbuffer);
unicodestring.Buffer = (PWCH) &localbuffer;
// get ntdll's module handle
HMODULE NtDllModule = LoadLibraryW(L"ntdll.dll");
if (NtDllModule)
{
RtlInt64 = (RTLINT64) GetProcAddress(NtDllModule,
"RtlInt64ToUnicodeString");
// the above call to GetProcAddress returned the address of
// RtlInterlockedSetBitRun instead of the address of the requested function
// as a result, the statements below don't work.
value = 0xFFFFFFFFF;
RtlInt64(value, 10, &unicodestring);
wprintf(L"%s\n", unicodestring.Buffer);
}
return 0;
}
my question is: is there something in the above code that justifies the discrepancy ?
Also note that, I am using G++ with a tool called VisualGDB which integrates the compiler and the debugger into Visual Studio. Normally things of that kind can cause strange "side effects" but, in this case, it seems rather unlikely for something that has nothing to do with ntdll to be the culprit.
Thank you for your help.

Why do I need separable compilation?

I have the code shown below. As far as I understood, separable compilation must be turned on when
CUDA device code is separated into .h and .cu files
Use ObjectA's device code into Object's B device code
however, in my main function I am not having any of the cases above. Could you tell me why do I have to set separable compilation for this sample project?
BitHelper.h
#pragma once
#include <cuda_runtime.h>
#define COMPILE_TARGET __host__ __device__
class BitHelper
{
public:
COMPILE_TARGET BitHelper();
COMPILE_TARGET ~BitHelper();
COMPILE_TARGET static void clear(unsigned int& val0);
};
BitHelper.cu
#include "bithelper.h"
BitHelper::BitHelper()
{}
BitHelper::~BitHelper()
{}
void BitHelper::clear(unsigned int& val0)
{
val0 = 0x0000;
}
Consume_BitHelper.h
#pragma once
class Consume_BitHelper
{
public:
void apply();
private:
bool test_cpu();
bool test_gpu();
};
Consume_BitHelper.cu
#include "consume_bithelper.h"
#include <cuda_runtime.h>
#include <iostream>
#include "bithelper.h"
__global__
void myKernel()
{
unsigned int FLAG_VALUE = 0x2222;
printf("GPU before: %d\n", FLAG_VALUE);
BitHelper::clear(FLAG_VALUE);
printf("GPU after: %d\n", FLAG_VALUE);
}
void Consume_BitHelper::apply()
{
test_cpu();
test_gpu();
cudaDeviceSynchronize();
}
bool Consume_BitHelper::test_cpu()
{
std::cout << "TEST CPU" << std::endl;
unsigned int FLAG_VALUE = 0x1111;
std::cout << "CPU before: " << FLAG_VALUE << std::endl;
BitHelper::clear(FLAG_VALUE);
std::cout << "CPU after : " << FLAG_VALUE << std::endl;
return true;
}
bool Consume_BitHelper::test_gpu()
{
std::cout << "TEST GPU" << std::endl;
myKernel << <1, 1 >> > ();
return true;
}
main.cu
#include "consume_bithelper.h"
#include "bithelper.h"
#include <iostream>
int main(int argc, char** argv)
{
Consume_BitHelper cbh;
cbh.apply();
std::cout << "\nPress any key to continue...";
std::cin.get();
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(cuda_class LANGUAGES CXX CUDA)
#BitHelper needs separable compilation because we have separated declaration from definition
add_library(bithelper_lib STATIC bithelper.cu)
set_property(TARGET bithelper_lib PROPERTY CUDA_SEPARABLE_COMPILATION ON)
#Consume_BitHelper needs separable compilation because we call BitHelper's device code
#from Consume_BitHelper's kernel
add_library(consume_bithelper_lib STATIC consume_bithelper.cu)
set_property(TARGET consume_bithelper_lib PROPERTY CUDA_SEPARABLE_COMPILATION ON)
target_link_libraries(consume_bithelper_lib bithelper_lib)
#We only call CPU code so no need of separable compilation?
add_executable(${PROJECT_NAME} main.cu)
target_link_libraries(${PROJECT_NAME} bithelper_lib consume_bithelper_lib)
The errors I'm getting are these
EDIT
According to Robert Crovella's post Consume_BitHelper.cu uses BitHelper::clear defined in a separate compilation unit.
Does it mean I have to activate only separate compilation for BitHelper?
Since separate compilation has to do only with device code called from device code.
Why am I getting the mentioned errors when separate compilation is NOT on for cuda_class? (which is the executable created from CMake and is not calling any device code)
Separable compilation has to do with how the compiler handles function calls. In exchange for a little bit of overhead, you get the ability to make true function calls and thus access code from other "compilation units" (i.e. .cu source files).
As GPU programmers are obsessed with performance (particularly the extra registers that get used when separable compilation is enabled) Nvidia made it an option instead of default.
You should only need separable compilation for .cu files that access functions/globals defined in other .cu files.