0

I have a CLR project that includes a form (Project1), and another General project (Project2) in visual studio, both are in C++ and they both work perfectly by themselves. I'm trying to link them, but I keep getting the following error as soon as the program starts:

Exception thrown at 0x77400A36 (ntdll.dll) in BrailleGUI.exe: 0xC0000005: ?>Access violation reading location 0x029905BB.

If there is a handler for this exception, the program may be safely continued.

I tried adding Project2 to the solution of Project1, I tried adding the .h and .cpp files of Project2 into Project1, I even tried just copying the code into the files that already exist in Project1. I still get the same error. Any ideas?

Thank you in advance, please let me know if you need more info.

Code:

Project2.h

#pragma once
#include <Windows.h>
#include <iostream>
#include <WbemCli.h>
#include <string>
#include <comutil.h>
#include <regex>

#pragma comment(lib, "comsuppw.lib")
#pragma comment (lib, "wbemuuid.lib")

int ReturnCOM();
int FindPort(char *com);

Project2.cpp

#include "ChipCommunication.h"

using namespace std;

int ReturnCOM(){
    int COMNumber = 0;
    HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    
    if (FAILED(hRes)){
        cout << "Unable to CoInitialize";
        return -1;
    }

    if ((FAILED(hRes = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0))))
    {
        cout << "Unable to initialize security: 0x" << std::hex << hRes << endl;
        return -1;
    }

    IWbemLocator* pLocator = NULL;
    if (FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator)))){
        cout << "Unable to create a WbemLocator: " << hRes << endl;
        return -1;
    }

    IWbemServices* pService = NULL;
    if (FAILED(hRes = pLocator->ConnectServer(L"root\\CIMV2", NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService))){
        pLocator->Release();
        cout << "Unable to connect to \"CIMV2\": " << hRes << endl;
        return -1;
    }

    IEnumWbemClassObject* pEnumerator = NULL;
    if (FAILED(hRes = pService->ExecQuery(L"WQL", L"SELECT * FROM Win32_PnPEntity", WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator))){
        pLocator->Release();
        pService->Release();
        cout << "Unable to retrive com ports" << hRes << endl;
        return -1;
    }

    IWbemClassObject* clsObj = NULL;
    int numElems;

    while ((hRes = pEnumerator->Next(WBEM_INFINITE, 1, &clsObj, (ULONG*)&numElems)) != WBEM_S_FALSE){
        if (FAILED(hRes))
            break;

        VARIANT vRet;
        VARIANT DeviceName;
        VariantInit(&vRet);
        VariantInit(&DeviceName);

        if (SUCCEEDED(clsObj->Get(L"PNPDeviceID", 0, &vRet, NULL, NULL)) && vRet.vt == VT_BSTR){
            if (wcsstr(vRet.bstrVal, L"VID_0525&PID_A4A7") != NULL){
                if (SUCCEEDED(clsObj->Get(L"Name", 0, &DeviceName, NULL, NULL)) && DeviceName.vt == VT_BSTR){
                    char* PointAtCOM = _com_util::ConvertBSTRToString(DeviceName.bstrVal);
                    COMNumber = FindPort(PointAtCOM);
                    delete[] PointAtCOM;

                }
            }
        
            VariantClear(&vRet);
        }


        clsObj->Release();
    }

    pEnumerator->Release();
    pService->Release();
    pLocator->Release();

    return COMNumber;

}

int FindPort(char *com){
    int ComNumber = 0;
    regex FindCOM("\\(COM([0-9]+)");
    smatch NumberinString;
    string DeviceName (com);

    if (regex_search(DeviceName, NumberinString, FindCOM)){
        DeviceName = NumberinString[1].str();
        ComNumber = stoi (DeviceName);
    }
    return ComNumber;
}

Project1.h

#pragma once
#include <windows.h>
#include <iostream>
#include <sstream>
#include <msclr\marshal_cppstd.h>

int comNum;                                         
std::ostringstream  cmdCHIPStream;                  
std::string         cmdCHIPString;                  

namespace BrailleGUI {

    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;

    public ref class MyForm : public System::Windows::Forms::Form
    {
    public:
        MyForm(void)
        {
            InitializeComponent();
        }

    protected:
        ~MyForm()
        {
            if (components){
                delete components;
            }
        }
    private: System::Windows::Forms::Button^  button1;
    protected:
    private: System::Windows::Forms::Button^  button2;
    private: System::Windows::Forms::Label^  label1;
    private: System::Windows::Forms::TextBox^  textBox1;
    private: System::Windows::Forms::Label^  label2;

    private:
        System::ComponentModel::Container ^components;

    #pragma region Windows Form Designer generated code
    ...

Project1.cpp

#include "ChipCommunication.h"
#include "MyForm.h"


using namespace System;
using namespace System::Windows::Forms;
[STAThread]

void main(array<String^> ^ args) {

    comNum = ReturnCOM();
    std::cout << "ReturnCOM is " << comNum << std::endl;

    if (comNum == -1) {
        std::cout << "Translator not connected" << std::endl;
    }

    std::ostringstream  comConStream;
    std::string         comConString;

    comConStream << "mode com" << comNum << " BAUD=115200 PARITY=n DATA=8" << std::endl;
    comConString = comConStream.str();

    system(comConString.c_str());       

    Application::EnableVisualStyles();
    Application::SetCompatibleTextRenderingDefault(false);
    BrailleGUI::MyForm form;
    Application::Run(%form);
}
Community
  • 1
  • 1
Armando
  • 11
  • 2
  • 1
    Problem might not be becasue of linking (since you get a functional executable out of it) but rather some programming error. Attach the debugger and see where the exception originates then post code to reproduce it. – stijn Jan 08 '17 at 19:35
  • Well, that's code but it's a lot of it. Please read http://stackoverflow.com/help/mcve. Also: where in this code the exception gets thrown? – stijn Jan 09 '17 at 09:16
  • @stijn sorry, this is the first time I'm asking on stackoverflow. I narrowed down the problem to this line in Project2.cpp: `char* PointAtCOM = _com_util::ConvertBSTRToString(DeviceName.bstrVal);` – Armando Jan 09 '17 at 17:21
  • Last line in debugger: 'Project1.exe' (CLR v4.0.30319: DefaultDomain): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. Exception thrown at 0x77400A36 (ntdll.dll) in Project1.exe: 0xC0000005: Access violation reading location 0x5E17496C. – Armando Jan 09 '17 at 17:36
  • Sorry I tried a while but I can't reproduce it: I pasted project2.h/cpp into a CLR project (console app, I don't have WinForms installed) then called ReturnCOM from the CLR main function. This leads to CoInitialize failing because of the [StaThread] attribute on main. If I remove the STAThread it works ok and the ConvertBSTRToString works ok.. I also don't immediately see a problem with the code except that I think you're supposed to call VariantClear on DeviceName, see https://msdn.microsoft.com/en-us/library/aa391442(v=vs.85).aspx – stijn Jan 09 '17 at 20:35
  • What is [StaThread] though? Do I not need it? – Armando Jan 10 '17 at 17:39
  • No real experience with it.. Questions like http://stackoverflow.com/questions/165316/stathread-and-multithreading might provide insight.. – stijn Jan 10 '17 at 18:49
  • Thanks! I got it to work by removing the [StaThread] and replacing the _com_util::ConvertBSTRToString() with the function in here https://www.codeproject.com/Articles/1969/BUG-in-com-util-ConvertStringToBSTR-and-com-util – Armando Jan 10 '17 at 19:36
  • Wow, interesting find. Maybe post that as an answer instead of a comment, for future reference. – stijn Jan 10 '17 at 19:53

1 Answers1

1

I got it to work by removing the [StaThread] line in Project1.cpp and I replaced the _com_util::ConvertBSTRToString() function with one that I found here: https://www.codeproject.com/Articles/1969/BUG-in-com-util-ConvertStringToBSTR-and-com-util

Armando
  • 11
  • 2