Linking a C++ project with a form project in visual studio - c++

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);
}

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

Related

Dynamically allocate buffer[] for URLOpenBlockingStreamW() output

I'm super new to C++ and I'm trying to download an executable file from a URL and write it to disk.
I have the below code which successfully downloads the file and stores it in memory. The issue I am having is then writing that to disk.
I am pretty sure this is down to where I am creating the buffer where the downloaded data will be written to before being going to the new file.
char buffer[4096];
The 4096 is an arbitrary number from the template code I got elsewhere. What I can't figure out or don't know is how to dynamically allocate that buffer size based on the size of the data at &pStream.
I have tried using functions such as sizeof() but these just get me the memory address size rather than the value itself.
Alternatively, is there better way to try and accomplish this download and write?
#include <Windows.h>
#include <Urlmon.h> // URLOpenBlockingStreamW()
#include <atlbase.h> // CComPtr
#include <iostream>
#include "download.h"
#include <fstream>
#include <assert.h>
#include <chrono>
#include <thread>
#pragma comment( lib, "Urlmon.lib" )
struct ComInit
{
HRESULT hr;
ComInit() : hr(::CoInitialize(nullptr)) {}
~ComInit() { if (SUCCEEDED(hr)) ::CoUninitialize(); }
};
int download_file()
{
ComInit init;
HRESULT hr;
// use CComPtr so you don't have to manually call Release()
CComPtr<IStream> pStream;
bool success = false;
while (success == false)
{
try {
// Open the HTTP request.
hr = URLOpenBlockingStreamW(nullptr, L"https://www.foo.bar/download/somefile.exe", &pStream, 0, nullptr);
if (FAILED(hr))
{
std::cout << "ERROR: Could not connect. HRESULT: 0x" << std::hex << hr << std::dec << "\n";
}
else
{
success = true;
}
}
catch (const std::exception& ex) {
std::cout << ex.what();
}
}
// Download the response and write it to stdout.
char buffer[4096]; // Issue is here I think
do
{
DWORD bytesRead = 0;
hr = pStream->Read(buffer, sizeof(buffer), &bytesRead);
if (bytesRead > 0)
{
//std::cout.write(buffer, bytesRead);
std::ofstream file;
file.open("some_path_dot_exe", std::ios_base::binary);
assert(file.is_open());
for (int i = 0; i < sizeof(buffer) / sizeof(buffer[0]); ++i)
file.write((char*)(buffer + i * sizeof(buffer[0])), sizeof(buffer[0]));
file.close();
}
} while (SUCCEEDED(hr) && hr != S_FALSE);
if (FAILED(hr))
{
std::cout << "ERROR: Download failed. HRESULT: 0x" << std::hex << hr << std::dec << "\n";
return 2;
}
std::cout << "\n";
return 0;
}
The IStream that URLOpenBlockingStreamW() gives you isn't guaranteed to be able to give you the full file size up front, so if you want to hold the entire file in memory, you will have to use std::vector or other dynamically-growing buffer.
Though, you don't actually need to hold the entire file in memory just to save it to disk, you can use a fixed array and write it to disk as it is being downloaded, as you already are doing.
The real problem is, you are opening and closing the file on every Read(), wiping out all previous data written. And you are ignoring the bytesRead value that Read() gives you.
You need to open the file one time, leave it open until you are done with the download, and don't write more than is actually in the buffer on each write().
Try this:
#include <Windows.h>
#include <Urlmon.h> // URLOpenBlockingStreamW()
#include <atlbase.h> // CComPtr
#include <iostream>
#include "download.h"
#include <fstream>
#include <assert.h>
#include <chrono>
#include <thread>
#pragma comment( lib, "Urlmon.lib" )
struct ComInit
{
HRESULT hr;
ComInit() : hr(::CoInitialize(nullptr)) {}
~ComInit() { if (SUCCEEDED(hr)) ::CoUninitialize(); }
};
int download_file()
{
ComInit init;
HRESULT hr;
// use CComPtr so you don't have to manually call Release()
CComPtr<IStream> pStream;
do
{
try {
// Open the HTTP request.
hr = URLOpenBlockingStreamW(nullptr, L"https://www.foo.bar/download/somefile.exe", &pStream, 0, nullptr);
if (SUCCEEDED(hr)) break;
std::cout << "ERROR: Could not connect. HRESULT: 0x" << std::hex << hr << std::dec << "\n";
}
catch (const std::exception& ex) {
std::cout << ex.what();
}
}
while (true);
std::ofstream file("some_path_dot_exe", std::ios_base::binary);
if (!file.is_open()) {
std::cout << "ERROR: Download failed. Unable to create output file.\n";
return 1;
}
// Download the response and write it to file.
char buffer[4096];
DWORD bytesRead;
do
{
hr = pStream->Read(buffer, sizeof(buffer), &bytesRead);
if (bytesRead > 0)
file.write(buffer, bytesRead);
} while (SUCCEEDED(hr) && hr != S_FALSE);
file.close();
if (FAILED(hr))
{
std::cout << "ERROR: Download failed. HRESULT: 0x" << std::hex << hr << std::dec << "\n";
return 2;
}
std::cout << "\n";
return 0;
}

C++ How do I make it so my program wouldn't delete files that are in use?

So basically, I'm listing all of the files in my temp directory, and then deleting them. Obviously, some of the files are in use and the program itself is using the files that it's deleting. I tried fiddling around with SHFileOperation with no success. (tbh I got no idea how to use it). How do I make it check if the file is in use by another program before deleting it? Thanks!
This is giving me the error: fs::remove_all(entry.path());
Code:
#include <iostream>
#include <Windows.h>
#include <filesystem>
#include <lmcons.h>
#include <fileapi.h>
#include "cColors.h"
using namespace std;
namespace fs = filesystem;
char type;
int main()
{
SetConsoleTextAttribute(h, 15);
while (true)
{
cout << "[~] Are you sure you want to run Windows Cleaner? [Y/N]";
cin >> type;
if (type == 'n')
{
break;
exit(0);
}
else if (type == 'y')
{
cout << "[#] Cleaning temp directory\n";
for (const auto& entry : fs::directory_iterator(fs::temp_directory_path()))
{
cout << "[#] Deleting " << entry.path();
fs::remove_all(entry.path()); //This is giving me the error
}
}
else
{
break;
exit(0);
}
}
}
Here's what I came up with. A recursive delete function which uses CreateFile. My original comment
Maybe you could use CreateFile with desired access 0 and share mode OPEN_EXISTING. Then you have to check the failing reason. If it doesn't fail; close and delete.
wasn't 100% correct. dwDesiredAccess should be 0, dwShareMode should be FILE_SHARE_DELETE, dwCreationDisposition should be OPEN_EXISTING and dwFlagsAndAttributes should be FILE_FLAG_DELETE_ON_CLOSE. If then a valid handle is received the last CloseHandle on the file will lead to deletion (see here).
Here's an example:
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <tchar.h>
#include <iostream>
#include <filesystem>
#ifdef _UNICODE
auto& cout = std::wcout;
#else
using std::cout;
#endif // _UNICODE
using std::endl;
namespace fs=std::filesystem;
void deleteRecursive(const fs::path& path);
void tryDeleteFile(const fs::path& path);
int main(int argc, char* argv[])
{
TCHAR tempDir[255];
GetEnvironmentVariable(_T("TEMP"), tempDir, 255);
deleteRecursive(fs::path(tempDir));
return 0;
}
void deleteRecursive(const fs::path& path)
{
fs::directory_iterator dirs(path);
for (const auto& entry : dirs)
{
const auto& path = entry.path();
if (entry.is_directory())
{
deleteRecursive(path);
if (fs::is_empty(path))
{
if (!RemoveDirectory(path.c_str()))
{
cout << _T("Can't delete dir: ") << path << endl;
}
}
}
else
{
tryDeleteFile(path);
}
}
}
void tryDeleteFile(const fs::path& path)
{
const auto file = path.c_str();
HANDLE fileHandle = CreateFile(
file, // lpFileName,
0, // dwDesiredAccess,
FILE_SHARE_DELETE, // dwShareMode,
NULL, // lpSecurityAttributes,
OPEN_EXISTING, // dwCreationDisposition,
FILE_FLAG_DELETE_ON_CLOSE, // dwFlagsAndAttributes,
NULL // hTemplateFile
);
if (fileHandle == INVALID_HANDLE_VALUE)
{
DWORD lastErr = GetLastError();
if (lastErr != ERROR_FILE_NOT_FOUND) // gone in the mean time
{
cout << _T("Can't delete file: ") << file << endl;
}
}
else
{
CloseHandle(fileHandle);
}
}
tryDeleteFile contains the crucial part.
Catch the exception Just ignore the error and continue. Or use the second form and pass an error_code argument. Than you get no exception and you can check the reason why it failed.
If the file is in use you get an error. So you can't delete it. If you have no rights you can't delete it too.
Checking the usage first is a race condition. After the check, the file might get closed and you may be able to delete it safely. There is no difference in checking first and than delete it or trying to delete it and it fails.

C++ I cant upload file to FTP server

I want to upload a file to my FTP server using C++ code and I'm able to FTP my server with FileZilla.
When I run my C++ code, it throws me an output "3" error ( GetLastError() function returned this value to the FtpPutFile() function
#pragma comment (lib,"wininet.lib")
#include <windows.h>
#include <wininet.h> //for uploadFile function
#include <iostream>
using namespace std;
int main()
{
HINTERNET hint, hftp;
hint = InternetOpen("FTP", INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, INTERNET_FLAG_ASYNC);
hftp = InternetConnect(hint, "MY IP ADRESS", INTERNET_DEFAULT_FTP_PORT, "MY NAME", "MY PASS", INTERNET_SERVICE_FTP, 0, 0);
if (!FtpPutFile(hftp, "C://Users//Elliot//Desktop//log.txt", "//log.txt", FTP_TRANSFER_TYPE_BINARY, 0))
{
cout << "FAIL !" << endl;
cout << GetLastError() << endl;
}
else {
cout << "file sended !";
};
InternetCloseHandle(hftp);
InternetCloseHandle(hint);
system("PAUSE");
}
things i have tried :
Changing server ( i made new server but still same result )
Controlling firewall
Running as adminstrator
break points ( the ftpputfile is giving the error )
The error message is clear. File is not there, there is nothing to send. You can easily check the file's path using std::ifstream before continuing with internet functions.
Use FtpSetCurrentDirectory to set a target directory. In this example I used "public_html", maybe your server is different.
#include <windows.h>
#include <wininet.h>
#include <iostream>
#include <string>
#include <fstream>
#pragma comment (lib,"wininet.lib")
using namespace std;
int main()
{
string file = "C:\\path.txt";
string site = "www.site.com";
string user = "username";
string pass = "password";
if (!ifstream(file))
{
cout << "no file\n";
return 0;
}
HINTERNET hint = InternetOpen(0, INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0);
HINTERNET hftp = InternetConnect(hint, site.c_str(), INTERNET_DEFAULT_FTP_PORT,
user.c_str(), pass.c_str(), INTERNET_SERVICE_FTP, 0, 0);
if (FtpSetCurrentDirectory(hftp, "public_html"))
{
if (!FtpPutFile(hftp, file.c_str(), "log.txt", FTP_TRANSFER_TYPE_BINARY, 0))
{
cout << "FAIL!" << endl;
cout << GetLastError() << endl;
}
else
{
cout << "file sended !";
}
}
InternetCloseHandle(hftp);
InternetCloseHandle(hint);
return 0;
}

IWbemLocator::ConnectServer (WMI) crashes in Windows 7

I am writing a simple x86 application for extracting Harddrive/storage info by using WMI. The development environment is MS Visual Studio 2013 Update 5. However, everytime my code reaches this part :
hr = (*pLoc)->ConnectServer(....);
I receive this error
"Unhandled exception at 0x6C2BD183 (wbemcomn.dll) in HDDExtractor.exe: 0xC0000005: Access violation writing location 0x00DB9CAA"
The funny thing is that, this error occurs on the PCs with Windows 7, however it always works perfectly fine on PCs with Windows 10.
Below is the excerpt of the source code :
#include <iostream>
#include <winsock2.h>
#include <Winbase.h>
#include <Iphlpapi.h>
#include <stdlib.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <WinIoCtl.h>
#pragma comment(lib, "IPHLPAPI.lib")
////////////////////////////////////////
#include <icmpapi.h>
#pragma comment(lib, "ws2_32.lib")
#include <iostream>
#include <strsafe.h>
//////////////////////////////////////
//for WMI
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
/////////////////////////////
#include <sstream>
#include <vector>
#include <algorithm>
#include <conio.h>
std::string WMI_Initialize(IWbemServices **pSvc, IWbemLocator **pLoc)
{
//Initialize COM.
HRESULT hr;
hr = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hr))
{
std::string result;
std::ostringstream out;
out << "Failed to initialize COM library. Error code = 0x"
<< hex << hr << endl;
result = out.str();
return result;
}
hr = CoInitializeSecurity(
NULL, // Security descriptor
-1, // COM negotiates authentication service
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication level for proxies
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation level for proxies
NULL, // Authentication info
EOAC_NONE, // Additional capabilities of the client or server
NULL); // Reserved
if (FAILED(hr))
{
std::string result;
std::ostringstream out;
out << "Failed to initialize security. Error code = 0x"
<< hex << hr << endl;
CoUninitialize();
result = out.str();
return result;
}
hr = CoCreateInstance(CLSID_WbemLocator, 0,
CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pLoc[0]);
if (FAILED(hr))
{
string result;
std::ostringstream out;
out << "Failed to create IWbemLocator object. Err code = 0x"
<< hex << hr << endl;
result = out.str();
CoUninitialize();
return result;
}
// Connect to the root\default namespace with the current user.
hr = (*pLoc)->ConnectServer(
BSTR(L"\\\\.\\root\\CIMV2"),
NULL, // User name
NULL, // User password
0, // Locale
NULL, // Security flags
0, // Authority
0, // Context object
&pSvc[0]); // IWbemServices proxy
// The rest/other stuffs below
}
And this is the calling function
std::string WMI_getHDDSN(std::string str)
{
IWbemServices *pSvc = NULL;
IWbemLocator *pLoc = NULL;
HRESULT hr;
std::string result = WMI_Initialize(&pSvc, &pLoc);
//The rest/other stuffs are below
}
And lastly the main function
int main(int argc, char *argv[])
{
std::wcout << "Press AnyKey" << std::endl;
std::string SN = WMI_getHDDSN("C");
std::wcout << "Error Message : " << SN.c_str() << std::endl;
_getch();
_getch();
}
Thank you very much.

How to use IFileOperation CopyItems for a destination ZIP file

I am using IFileOperation interface's CopyItems method to copy one more files from source folder to a destination folder. This works without any error as long as the destination folder is a standard file system directory. However, my main motivation of using IFileOperation instead of SHFileOperation() method is to allow copying items from / into non-file-system objects as the documentation says (https://msdn.microsoft.com/en-us/library/windows/desktop/bb775771%28v=vs.85%29.aspx).
The following code works perfectly for file-system destination e.g. "g:\my folder" but does not work if the destination is a ZIP file e.g. "g:\Super Cars.zip". For this quick sample please overlook the resource leaks :).
Please note the ZIP file is an existing ZIP file created using standard built-in ZIP capability of Windows and it does not contain the file is am trying to copy.
#include "stdafx.h"
#include <Windows.h>
#include <shellapi.h>
#include <Shlobj.h>
#include <iostream>
#include <atlbase.h>
void CopyFile(LPCTSTR strSource, LPCTSTR strDestination)
{
PIDLIST_ABSOLUTE abSourcePidl = nullptr;
SFGAOF attrs;
HRESULT hr = SHParseDisplayName(strSource, nullptr, &abSourcePidl, 0, &attrs);
if (FAILED(hr))
{
std::wcout << _T("SHParseDisplayName failed for ") << strSource << std::endl;
return;
}
PIDLIST_ABSOLUTE abDestPidl = nullptr;
hr = SHParseDisplayName(strDestination, nullptr, &abDestPidl, 0, &attrs);
if (FAILED(hr))
{
std::wcout << _T("SHParseDisplayName failed for ") << strDestination << std::endl;
return;
}
IShellItem2* pDestShellItem;
hr = SHCreateItemFromIDList(abDestPidl, IID_IShellItem2, reinterpret_cast<LPVOID*>(&pDestShellItem));
if (FAILED(hr))
{
std::wcout << _T("SHCreateItemFromIDList failed") << std::endl;
return;
}
PIDLIST_ABSOLUTE* pPidlRawArray = new PIDLIST_ABSOLUTE[1];
pPidlRawArray[0] = abSourcePidl;
IShellItemArray* pShellItemArr = nullptr;
hr = SHCreateShellItemArrayFromIDLists(1, (LPCITEMIDLIST*)pPidlRawArray, &pShellItemArr);
if (FAILED(hr))
{
std::wcout << _T("SHCreateShellItemArrayFromIDLists failed") << std::endl;
return;
}
CComPtr<IFileOperation> fileOp;
hr = fileOp.CoCreateInstance(CLSID_FileOperation);
if (FAILED(hr))
{
std::wcout << _T("Creation of IFileOperation failed") << std::endl;
return;
}
hr = fileOp->CopyItems(pShellItemArr, pDestShellItem);
if (FAILED(hr))
{
std::wcout << _T("CopyItems fall failed") << std::endl;
return;
}
hr = fileOp->PerformOperations();
if (FAILED(hr))
{
std::wcout << _T("PerformOperations call failed") << std::endl;
return;
}
std::wcout << _T("File copied successfully") << std::endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
CopyFile(_T("D:\\TEMP\\COMTIME.TXT"), _T("G:\\My Folder")); // WORKS!!
CopyFile(_T("D:\\TEMP\\COMTIME.TXT"), _T("G:\\Super Cars.zip")); // DOES NOT WORK!!
CoUninitialize();
return 0;
}